开门见山
每一个大更新都是一种变革,对于 Servlet 同样也是。但对联盟不是,特喵的 29 号怎么还不到!!!
Servlet 3.0 作为 Java EE 6 规范体系中一员。
今儿我们从这几点说说
· 注解支持
· 可插性支持
· 动态配置
· 异步处理
一、注解支持
Servlet 的新增注解除了用于指定 Servlet 的 @WebServlet,还有指定过滤器的 @WebFilter、指定监听器的 @WebListener、为 Servlet 或者过滤器指定初始化参数的 @WebInitParam、提供对上传文件支持的 @MultiPartConfig 等。
二、可插性支持
可以再不修改已有 Web 应用的前提下,只需按照一定格式达成的 JAR 包的模块放到 WEB-INF/lib 目录下,即可实现新功能的扩充,而不需要进行额外的配置。
Servlet3.0 通过引入了称之为 “Web 模块部署描述符片段”的 web-fragment.xml 部署描述文件来实现此功能。
该文件必须存放在引入 JAR 包放在当前应用程序的 WEB-INF/lib 目录下,在应用程序启动期间对其进行合并使用。
除此之外,所有该模块使用的资源,如 class 文件、配置文件等,只需要放在能够被容器的类加载器链加载的路径上(如 classes 目录)。
三、动态配置
Servlet 3.0中 ServletContext 对象可以支持运行时动态部署 Servlet、过滤器、监听器以及为 Servlet 和过滤器增加 URL 映射等。
以 Servlet 为例,ServletContext 动态配置增加了的方法:
· addServlet() 方法
· addServlet() 方法
· addServlet() 方法
· createServlet() 方法
· getServletRegistration() 方法
· getServletRegistrations() 方法
createServlet():通过ServletContext 对象的 createServlet() 方法创建的 Servlet,通常需要做一些自定义配置,然后使用 addServlet() 方法。
addServlet():使用 addServlet() 方法来将 createServlet() 方法创建的 Servlet 增加映射信息,等价于在 web.xml(或 web-fragment.xml)中使用 标签为 Servlet 增加映射信息
ServletContext 对象新增的这些方法可以在 ServletContextListener 监听器接口的 contexInitialized() 方法和 ServletContainerInitializer 接口的 onStartup() 方法中使用
【示例】在 web.xml 中配置 Struts 框架
【示例】在 ServletContextListener 的 contexInitialized() 方法中动态配置 Struts 框架
四、异步处理
Servlet 3.0 的异步处理:
· 首先,Servlet 接收到请求之后,可能首先需要对请求携带的数据进行预处理
· 其次,Servlet 线程将请求转交给一个异步线程来执行业务处理,线程本身返回至容器,此时 Servlet 还没有生成响应数据
· 异步线程处理完业务后,可以直接生成响应数据,或者将请求继续转发给其他 Servlet。
Servlet 和过滤器在默认情况下,并没有开启异步处理特性,如果希望使用该特性,则必须按照如下方式启动:
· 以 Servlet 为例,配置方式
· 以 @WebFilter 为例,配置方式
一个简单的模拟异步处理的 Servlet
【代码】AsyncDemoServlet.java
【运行结果】
Servlet3.0 是对 Servlet 2.4 之后的重大修订。尤其是异步处理特性和可插性支持的出现, 必将对现有的 MVC 框架开发产生深远影响。
代码啦~
【AsyncDemoServlet.java】
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
- Servlet implementation class AsyncDemoServlet
*/
@WebServlet(urlPatterns = “/AsyncDemoServlet”, asyncSupported = true)
public class AsyncDemoServlet extends HttpServlet {
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException{
resp.setContentType("text/html;charset=UTF-8");
PrintWriter out = resp.getWriter();
out.println("<p>进入 Servlet 的时间: " + new Date().toLocaleString() + "</p>");
out.flush();
// 开启子线程执行业务调用,并由其负责输出响应 主线程退出
AsyncContext ctx = req.startAsync();
new Thread(new Executor(ctx)).start();
out.println("<p>结束 Servlet 的时间: " + new Date().toLocaleString() + "</p>");
out.flush();
}
}
class Executor implements Runnable {
private AsyncContext ctx = null;
public Executor(AsyncContext ctx) {
this.ctx = ctx;
}
public void run() {
try {
// 等待10秒,以模拟业务方法的执行
Thread.sleep(10000);
PrintWriter out = ctx.getResponse().getWriter();
out.println("<p>子线程业务处理完毕的时间: " + new Date().toLocaleString() + "</p>");
out.flush();
// 真正送出回应
ctx.complete();
} catch(Exception e) {
e.printStackTrace();
}
}
}