如今,像 Struts、JSF 和 Springweb 这样的 web 框架已经被普遍接受,并已经确立成为构建 web 应用程序的技术。将这些框架集成为一个 web 应用程序并不是那么容易,因为这一过程涉及将不同的片段同化在一起,之后编辑一个描述如何将所有这些片段配合在一起的单独描述符文件。绝大多数框架强制您在应用程序的部署描述符文件中配置像 servlet 类(通常为 控制器 Servlet)、过滤器类或者侦听器类这样的框架细节。这种必备配置的主要原因是当今的 web 应用程序只支持一个单独的整体部署描述符,其中定义了所有的部署信息。当应用程序的大小增加时,外部框架的依赖关系可能也增加,从而生成复杂的部署描述符文件。正如您可能知道的,复杂描述的维护始终存在争议。
为了解决这些问题,Servlet 3.0 API 最为显著的概念之一是 web 片段 或者 模块 web.xml 的思想。Web 片段是将 web 应用程序逻辑分区为 servlet、servlet-mapping、servlet-filter、filter-mapping、servlet-listener 之类的元素及其子元素。框架开发人员可以利用该功能以定义存在于框架内自己的 web 片段,开发人员可以在不修改现有的部署描述符的情况下仅仅通过将库文件包含到应用程序的类路径中来插入越来越多的框架。简言之,该功能旨在当用框架或者库进行工作时进行零配置。
对该部署描述符已经进行了更改以包含保存 web 片段细节的 这一新元素。如果该片段被打包为一个 .jar 文件且以部署描述符的形式具备元数据信息,则 web.xml 文件必须包含在 .jar 文件的 META-INF 目录下。在部署时,器扫描应用程序的类路径,查找所有 web 片段并加以处理。前面讨论过的 metadata-complete 标志在应用程序启动期间控制 web 片段的扫描。以下显示了一个示例 web 片段:
- <web-fragment>
- <servlet>
- <servlet-name>myservlet</servlet-name>
- <servlet-class>samples.MyServlet</servlet-class>
- </servlet>
- <listener>
- <listener-class>samples.MyListener</listener-class>
- </listener>
- </web-fragment>
为了提供增强的可插拔性,Servlet 3.0 借助添加到 ServletContext 的 API 为增加 servlets 和过滤器类的编程提供了非常需要的支持。这些新的 API 使您能通过编程来声明 servlets、过滤器类及其 URL 映射。这些类在应用程序启动或者运行期间进行初始化。最重要的是,您只能通过 ServletContext 的 contextInitialized 方调用这些 API。有关这些 API 的更多信息,请参阅 Servlet 3.0 API 文档。通过编程添加 servlet 和过滤器类的代码示例如下所示:
- @ServletContextListener
- public class MyListener {
- public void contextInitialized (ServletContextEvent sce) {
- ServletContext sc = sce.getServletContext();
- //Declare servlet and servlet mapping
- sc.addServlet("myServlet", "Sample servlet", "samples.MyServlet", null, -1);
- sc.addServletMapping("myServlet", new String[] {"/urlpattern/*"});
- //Declare filter and filter mapping
- sc.addFilter("myFilter", "Sample Filter", " samples.MyFilter", null);
- sc.addFilterMapping("myFilter", new String[] {"/urlpattern/*"}, "myServlet",
- DispatcherType.REQUEST, false);
- }
- }
大家应该都遇到过 servlets 运行缓慢的问题,特别是 servlets 必须等待来自 web 服务、JDBC 连接、JMS 消息等的响应。在当前情况下,servlet 在生成响应前需要等待进程完成,这会导致低效率阻塞操作消耗容器的线程或者其他有限的资源。在采用 JDBC 连接时的另一个不利影响是,数据库可能存在许多等待访问的阻塞线程。这种情况最终将导致整个 web 容器的线程不足和服务质量下降。
为了克服上述缺点,Servlet 3.0 添加了对挂起和恢复请求处理的支持,使 servlet 以异步、非阻塞的方式响应请求(这就是编程的 Comet 样式)。当一项请求被挂起时,处理请求的线程将在不生成任何响应的情况下返回给容器并准备执行其他任务。处理请求的 resume 方法恢复请求处理。只要当所请求的资源可用时,处理事件的线程才恢复被挂起的请并进行处理以生成响应。以下列举的是异步 servlets 的一些功能:
即使数据到达缓慢(非阻塞输入),也能在没有阻塞事件的情况下从客户机接收数据。
即使客户机或者网络运行缓慢(非阻塞输出),也能在不发生阻塞的情况下向客户机发送数据。
能处理被延迟的请求。如果在响应请求前必须获得远程/缓慢的资源,或者如果需要抑制访问特定的资源以防止过多的同步访问,对被延迟事件的处理是非常有用的。
能处理被延迟的响应关闭;也就是响应将保持打开以允许在发生异步事件时发送其他数据。
能通知阻塞或者非阻塞事件。
将新的 API 添加到 ServletRequest 和 ServletResponse,用于挂起、恢复和查询请求的状况、启用禁用和查询响应的状况。开发人员可以分别通过 requestSuspended(), requestResumed() 和 requestCompleted() 方法使用请求的 resume、suspend 和 complete 方法通知事件。有关这些方法的详细信息请参阅 Servlet 3.0 API。