1. 大概介绍
我们之前做的异步操作是在JSP中,进行的异步操作,但是有时候我们需要在Servlet或者Filter中进行异步操作,这时候可以使用Servlet3.0的新特性,它支持异步操作。
Servlet3.0允许,在接收到请求之后,Servlet 线程可以将耗时的操作委派给另一个线程来完成,自己在不生成响应的情况下返回至容器。
2. 第一步
@WebServlet、@WebFilter 两个注解都支持asyncSupported 属性。在我们需要进行异步操作的Servlet或Filter注解上增加一个属性,以Servlet为例子:
@WebServlet(urlPatterns=”/async”,asyncSupported=true)
asyncSupported=true,代表当前servlet支持异步操作。
3.第二步
<1>需要一个异步上下文对象,通过这个对象可以获取request和response对象。
AsyncContext context = request.startAsync();这个request对象的传进来的请求参数。
<2>开启线程
在开启的线程中进行自己的操作。通过asyncContext 获得request response进行操作。
4.第三步
对异步上下文进行监听,在它的监听器方法中有一个onComplete,可以用于判断结束。在onComplete中进行收尾工作,比如关闭流。
5. 异步处理监听器
使用AsyncListener可以监控异步线程事件。
异步线程开始时,调用 onStartAsync(AsyncEvent event) 方法
异步线程出错时,调用 onError(AsyncEvent event) 方法;
异步线程执行超时,调用 onTimeout(AsyncEvent event) 方法;
异步执行完毕时,调用 onComplete(AsyncEvent event) 方法;
6. 小例子
一个注册完了,发邮件的简单抽象例子。
@WebServlet(value="/reg",asyncSupported=true)
public class RegistServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setCharacterEncoding("UTF-8");
final PrintWriter out = response.getWriter();
System.out.println("开始注册");
System.out.println("注册结束");
//获取一个异步上下文对象。
AsyncContext context = request.startAsync();
//添加监听
context.addListener(new AsyncListener() {
@Override
public void onTimeout(AsyncEvent event) throws IOException {
}
@Override
public void onStartAsync(AsyncEvent event) throws IOException {
}
@Override
public void onError(AsyncEvent event) throws IOException {
}
@Override
public void onComplete(AsyncEvent event) throws IOException {
//监听到线程结束。
out.flush();
out.close();
}
});
//开启线程
new Thread(new SendEmail(context)).start();
}
}
另一个线程SendEmail的操作代码:
class SendEmail implements Runnable{
private AsyncContext context;
//构造一个有参数构造函数,接收异步上下文对象。
public SendEmail(AsyncContext context){
this.context = context;
}
@Override
public void run() {
PrintWriter out;
try {
out = context.getResponse().getWriter();
//发送邮件,通过另一个线程来完成。
System.out.println("开始发送邮件。");
System.out.println("邮件发送成功。");
} catch (IOException e) {
e.printStackTrace();
}
}
}