BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

Java EE 6 Web层综述:Servlet获得异步支持、扩展性改善

| 作者 Charles Humble 关注 902 他的粉丝 ,译者 张龙 关注 14 他的粉丝 发布于 2010年1月20日. 估计阅读时间: 8 分钟 | QCon上海2018 关注大数据平台技术选型、搭建、系统迁移和优化的经验。

很多Java Web应用都是基于某个框架的,如Apache Wicket、Java ServerFaces、Struts或是Spring MVC等等。要想使用框架,开发者需要在应用的web.xml配置文件中注册框架的切入代码,如Servlet、Filter或是Listener。这么做的后果就是部署描述符变得很庞大,同时导致框架所用的XML与特定于应用的XML混杂在了一起。Servlet 3.0规范的一个主要目标就是让开发者无需编辑web.xml部署描述符就能部署Servlet、Filter和Listener,同时可以将web.xml文件拆分成多个模块。为了实现这一点,Servlet 3.0规范增加了基于注解的配置(@WebServlet、@ServletFilter以及@WebServletContextListener),这使得我们可以不再需要web.xml文件,同时规范还引入了一个新的概念:Web片段(Web Fragment)。

Web片段可以将框架的“样板”XML与应用的其他配置分开,并且能够实现应用的自我注册。Web片段必须放在名为web-fragment.xml的文件中,该文件只要位于Web应用的classpath下即可,但通常都将其放到META-INF目录下或是框架的jar文件中。XML以<web-fragment>元素开始,里面包含的元素与web.xml部署描述符大同小异。如下代码所示:

<web-fragment>
	<filter>
		<filter-name>MyXSSFilter</filter-name>
		<filter-class> MyXssFilter</filter-class>
	</filter>
	<servlet>
		<servlet-name>myFrameworkServlet</servlet-name>
		<servlet-class> MyFrameworkServlet</servlet-class>
	</servlet>
	<listener>
		<listener-class> MyFrameworkListener</listener-class>
	</listener>
</web-fragment>

容器在部署时会处理XML片段并组装成最终的部署描述符。由于容器负责组装web.xml文件,因此如果需要按照特定的顺序来调用框架的Servlet、Listener或Filter时就可能产生问题。为了避免这个问题,Servlet 3.0 API支持绝对与相对顺序的部署描述符。我们可以在web.xml文件中使用<absolute-ordering>元素指定绝对顺序,这样WEB-INF/lib下的每个jar都可以通过META-INF/web-fragment.xml文件的<name>元素获得一个名字。接下来,Web应用的WEB-INF/web.xml文件可以通过<absolute-ordering>元素按照顺序列举出这些片段名,这个顺序就是jar的调用顺序,同时还有一个可选的<others/>元素用于指定是否以及何时包含那些未命名的jar文件。由于部署者可以选择只列出那些受信任的jar以进行部署,这样就可以避免意外情况的发生。除此之外,通过顺序还可以排除那些不需要被扫描的jar,这样就可以加快应用的部署速度。最后,如果你不想在产品环境下看到自我注册的情况发生,那就可以在web.xml文件中使用<metadata-complete>元素,这会告诉Web容器只去寻找注解而非Web片段。

由于既支持片段,又可以使用注解作为另一种配置机制,Servlet 3.0可以插入框架的共享拷贝,比如JAX-WS、JAX-RS以及JSF等,他们都构建在Web容器之上,使用了ServletContainerInitializers。这些框架是通过jar services API被检测到的,同时还可以指定其处理的类型列表。对于WEB-INF/lib下的任何jar来说,只要其中包含的类被检测到都会传递给ServletContainerInitializer。这样,我们还可以将同样的API作为ServletContextListeners。

从Servlet API首次发布以来,构建Web应用的方法发生了翻天覆地的变化,尤其是使用越来越多的异步Web技术。这些技术(一般统称为Ajax或是Web 2.0)对于Web客户端(比如浏览器)与服务器端之间的传输机制产生了重要的影响,因为客户端会在一个页面中向服务器端发出更多的请求而不是每次请求都刷新一次页面。

长时间的服务器端处理会恶化这一情况,比如等待JDBC连接池中的连接,或是等待JMS队列中的消息等。在Servlet中等待实在是太低效了,因为这种阻塞会消耗线程以及其他有限的系统资源。鉴于此,Servlet 3.0引入了异步处理请求的功能,这样线程就可以返回到容器中并执行其他任务。在请求上的异步处理开始时,其他线程或是回调既可以生成响应,也可以分发请求以便通过AsyncContext.dispatch方法在容器上下文中执行请求。

由于异步Servlet的行为与同步的差别非常大,因此Servlet 3.0要求开发者指定asyncSupported=true以表示Servlet支持异步请求。不仅是Servlet,Filter也可以异步执行。Servlet 3.0通过新的ServletRequest方法来支持异步处理,比如startAsync()会返回一个AsyncContext对象,该对象用于持有传递给方法的request与response对象。这里,处理原始请求的线程还可以执行其他操作。此外,API还引入了一个新的Listener类:AsyncListener,它会告诉我们异步操作何时结束或者是否超时了。AsyncContext类拥有一个complete()方法,凭借该方法我们可以在异步操作结束后提交响应。AsyncListener类拥有一个dispatch()方法,它会将异步请求转发给容器,这样其他框架(比如JSP)就可以生成响应了。

除了引入大量的新技术和新方法外,Servlet 3.0规范还对其他地方进行了大量的增强:HttpServletRequest终于获得对multipart/form-data MIME类型的内置支持了、Cookie类开始支持“HttpOnly” cookie以避免某些跨站点的脚本攻击、ServletContext API也得到了更新,我们可以通过编程的方式将Servlet和Filter加到上下文中了。

查看英文原文:The Java EE 6 Web Tier: Servlets Gain Asynchronous Support, Improved Extensibility

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

看样子. by Ma Karl

看样子,Servlet3.0确实是加入了一些处理异步的东西。
大量的异步会造成服务器的疯狂发包。

web-fragment很好 by yang romza

部分解决了模块化问题,和OSGi结合起来效果应当不错

Re: web-fragment很好 by Ma Karl

一直在做东西,还没时间尝尝3.0的鲜呀。

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

3 讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT