servlet3.0规范中添加了异步处理,即一部分操作处理完成之后,先行把数据返回来,对于另一部分比较耗时的操作可以放置到另外一个线程中进行处理,该线程保留有连接的请求和响应对象,在处理完成之后可以把处理的结果通知到客户端,实例代码如下:
- import java.io.IOException;
- import java.io.PrintWriter;
- import java.util.Date;
- import javax.servlet.AsyncContext;
- import javax.servlet.AsyncEvent;
- import javax.servlet.AsyncListener;
- import javax.servlet.ServletException;
- import javax.servlet.annotation.WebServlet;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- /**
- * @Title: AsynServlet.java
- * @Package
- * @Description: TODO
- * @author ynb
- * @date 2014-7-24 下午5:07:00
- * @version V1.0
- */
- /**
- * @author admin
- *
- */
- @WebServlet(urlPatterns="/demo", asyncSupported=true)
- public class AsynServlet extends HttpServlet {
- private static final long serialVersionUID = -8016328059808092454L;
- /* (non-Javadoc)
- * @see javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
- */
- @Override
- protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- resp.setContentType("text/html;charset=UTF-8");
- PrintWriter out = resp.getWriter();
- out.println("进入Servlet的时间:" + new Date() + ".");
- out.flush();
- //在子线程中执行业务调用,并由其负责输出响应,主线程退出
- final AsyncContext ctx = req.startAsync();
- ctx.setTimeout(200000);
- new Work(ctx).start();
- out.println("结束Servlet的时间:" + new Date() + ".");
- out.flush();
- }
- }
- class Work extends Thread{
- private AsyncContext context;
- public Work(AsyncContext context){
- this.context = context;
- }
- @Override
- public void run() {
- try {
- Thread.sleep(2000);//让线程休眠2s钟模拟超时操作
- PrintWriter wirter = context.getResponse().getWriter();
- wirter.write("延迟输出");
- wirter.flush();
- context.complete();
- } catch (InterruptedException e) {
- } catch (IOException e) {
- }
- }
- }
对于异步执行,我们可以添加一个监听器,监听异步执行的状态。
- ctx.addListener(new AsyncListener() {
- @Override
- public void onTimeout(AsyncEvent arg0) throws IOException {
- // TODO Auto-generated method stub
- }
- @Override
- public void onStartAsync(AsyncEvent arg0) throws IOException {
- // TODO Auto-generated method stub
- }
- @Override
- public void onError(AsyncEvent arg0) throws IOException {
- // TODO Auto-generated method stub
- }
- @Override
- public void onComplete(AsyncEvent arg0) throws IOException {
- // TODO Auto-generated method stub
- }
- );
在Servlet返回之前,我们可以把持有request和response对象的AsyncContext对象放置到一个全局可访问的静态容器中
- map.put("id",ctx);
- map.remove("id",ctx);
如下服务器和客户端之间数据交互的模型图