Servlet3.0异步支持

来源:互联网 发布:php截断上传 编辑:程序博客网 时间:2024/06/04 19:05

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();        }    }}
原创粉丝点击