Servlet容器中的Java Web应用程序与独立版本

构建一个小型Java Web应用程序以在Servlet容器(如Tomcat)中运行与构建具有内置Web服务器的独立Java应用程序并在反向代理后面运行它有什么好处?

我已经玩Java一年了。 我注意到启动Tomcat需要时间,并且由于类加载器问题,并不总是可以进行热重新部署。 对我来说,Servlet API似乎有点令人费解,特别是从配置和RESTful设计的角度来看(它并没有真正完全支持)。

另一方面,我注意到我的IDE可以以闪电般的速度编译和运行独立的应用程序。 配置Apache进行反向代理是一件小事,嵌入式Jetty似乎可以处理任何我可以抛出的内容。 当我可以使用Restlet,Wicket等时,我不需要Servlet。能够更好地了解我的应用程序是如何工作的(因为它没有与庞大的应用程序服务器集成)让人感觉更有能力。 堆栈跟踪更短。 下载大小更小。 最终用户配置更容易。 我猜测性能可能更好,因为涉及的软件层较少。

但是,我想起了通常听起来好得令人难以置信的说法。 所以我的问题是,为什么我不想让我的网络应用程序独立? Servlet容器给了我和/或我的最终用户我们真正需要但不知道的是什么?

这里有2个单独的问题:

  1. 我应该使用嵌入式服务器,还是部署到容器中?

    我不认为你应该看到这种或那种方式有很大的不同。 以编程方式启动Jetty服务器的代码略多,配置更容易以编程方式完成。 尽管IDE对Web应用程序配置和部署的支持越来越好,但它仍然比独立应用程序更糟糕(这有点像定义,因为有一些支持的超集)。

    另一方面,应用服务器为您提供了一些很好的好处,如内置管理,内置的服务运行能力等。

    您甚至可以使用混合方法:使用嵌入式服务器在本地开发,然后在生产中部署到容器中。 但这有点奇怪:如果你经历了制作一个正确的WAR文件的麻烦,IDE应该能够充分地处理容器中的部署。

    顺便说一句,你有热重新部署的问题很奇怪; Tomcat不应该遇到问题,除非你遇到一些奇怪的角落……

  2. 我应该使用Servlet API吗?

    这与#1正交。 你可以很好地嵌入Jetty并实现Servlets。 您还可以通过ServerServlet http://www.restlet.org/documentation/1.0/faq#02在Tomcat中使用Restlet API。

    我个人觉得Servlet API非常简单。你可以得到很好的东西,比如并发和状态管理。 我不太清楚这意味着什么不支持RESTful设计,但如果Restlets更好地满足您的要求,那么使用它……

如果您不需要完整的Servlet堆栈,嵌入式Jetty可能是一个不错的选择。 与Tomcat不同,Jetty可以轻松摆脱您不使用的部分(JSP,JNDI等)。

另一方面,编写自己的HTTP服务器是一个糟糕的主意。 当然,编写处理基本请求的东西很容易。 但很快你就会发现有些客户遇到了麻烦,因为它不支持完整的协议规范; 或者当有超过几百个用户时崩溃; 或者说有一个漏洞允许马来西亚的一些孩子炸毁你的打印机。 所以不要重新发明轮子。

至于你抱怨Servlet API不支持RESTful设计 – 你错过了重点,它从来没有打算这样做。 但是有很多REST库在Servlet API 之上运行。

嵌入式Jetty也是一个servlet容器。 我假设您的应用程序包含一个web.xml,您可以在其中定义wicketfilter/ servlet,RESTlet servlet及其映射(至少)。 所以你无法摆脱Servlet API(或者servlet容器,即使你嵌入它),但是你可以在框架下面以及你自己的一些main()方法中隐藏它。 RESTlet(或Jersey或任何JAX-RS实现)以及Spring MVC都基于servlet,因此Servlet API确实很好地支持REST,我会说。

PS这两种方法并不相互排斥。 您可以在开发期间很好地使用Jetty,然后将您的战争部署到一些(非嵌入式)容器中以进行QA /生产。 或者……如果真的适合您的需要,坚持使用Jetty进行生产。

Servlet容器通常提供许多有用的东西,如自动会话管理,热部署,故障转移和集群框架等。 当然,这取决于容器,但有时这些是非常有用的工具。 有时他们不是。

编辑:刚刚注意到您对热重新部署的评论。 是的,有时候容器很麻烦并且很难用,而且它们都有自己的怪癖。 然而,有时他们确实提供了一些非常好的东西。

进程内Servlet容器是在Web服务器的JVM内部工作的容器,它们提供了良好的性能但可扩展性差。

进程外容器是在Web服务器外部的JVM中工作的容器。 性能较差但可扩展性更好在进程外容器,Web服务器和容器之间通过使用IPC等标准机制进行会话。

除了这些类型的容器之外,还有第三种类型,它是独立的servlet容器。 这些是Web服务器不可或缺的一部分。

如果您的热部署存在问题,很可能您没有清理外部连接或其他资源。 要处理这个问题,通常你想要实现一个监听器,让你知道什么时候启动或停止。

你可能应该在你的战​​争中实现这样的东西(tomcat 6):

public class MyTomcatInitCleanupListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent arg0) { super.contextInitialized(arg0); } @Override public void contextDestroyed(ServletContextEvent arg0) { super.contextDestroyed(arg0); } } 

对于tomcat 7+,你可以google“tomcat lifecycle listener”