Servlet-异步执行AsyncContext

Servlet-异步执行AsyncContext

[email protected]

2015年9月18日

 

1 目标:执行耗时操作时,异步返回,避免阻塞。

2 原理:启动新的线程执行耗时操作,实时返回。

3 流程:创建Servlet,异步开启新线程。线程结束后,将请求转发到其它的目标或结束。

4 方法:

4.1 创建Servlet:启用异步,设置响应内容类型。

启用异步:@WebServlet(value="/b.do",asyncSupported=true)

设置响应内容类型:response.setContentType("text/html;charset=GBK"); 

注意:如果不设置响应内容类型,将无法启用异步。

开启新线程:使用AsyncContext开启新的线程实例。

           AsyncContext ctx=request.startAsync();

           ctx.setTimeout(30*1000);

           ctx.start(new Task(ctx));

4.2 线程处理:设置异步上下文,处理请求

设置异步上下文:AsyncContext实例:

      public Task(AsyncContext ctx) {

           super();

           this.ctx = ctx;

      }

      private AsyncContext ctx=null;

处理请求:处理完成后可以转发(dispatch)或结束(complete)。

                 ServletRequest req=ctx.getRequest();

                 req.setAttribute("async", "This is anasync msg:"+new Date());

                 ctx.dispatch("/a.jsp");

4.3 示例:异步处理耗时任务

//AsynServlet.java

package lee;

 

import java.io.IOException;

import java.io.PrintWriter;

import java.util.Date;

 

importjavax.servlet.AsyncContext;

importjavax.servlet.ServletException;

importjavax.servlet.annotation.WebServlet;

importjavax.servlet.http.HttpServlet;

importjavax.servlet.http.HttpServletRequest;

importjavax.servlet.http.HttpServletResponse;

 

/**

 * Servlet implementation class AsynServlet

 */

@WebServlet(value="/b.do",asyncSupported=true)

public class AsynServletextends HttpServlet {

      private static final long serialVersionUID = 1L;

      

    /**

     * @see HttpServlet#HttpServlet()

     */

    public AsynServlet() {

        super();

        // TODO Auto-generated constructor stub

    }

 

      /**

       * @seeHttpServlet#service(HttpServletRequest request, HttpServletResponse response)

       */

      protected void service(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {

           // TODO Auto-generated method stub

           response.setContentType("text/html;charset=GBK"); 

           PrintWriter out=response.getWriter();

           out.println("Start="+newDate()+"</br>");

           out.flush();

           AsyncContextctx=request.startAsync();

           ctx.setTimeout(30*1000);

           ctx.start(newTask(ctx));

           out.println("Main Return="+newDate()+"</br>");

           out.flush();

      }

}

 

//工作线程:Task.java

package lee;

 

import java.util.Date;

 

importjavax.servlet.AsyncContext;

importjavax.servlet.ServletRequest;

 

public class Task implementsRunnable {

      public Task(AsyncContext ctx) {

           super();

           this.ctx= ctx;

      }

      private AsyncContext ctx=null;

      @Override

      public void run() {

           // TODO Auto-generated method stub

           try {

                 System.out.println("start task."+new Date());

                 Thread.sleep(5000);

                 ServletRequestreq=ctx.getRequest();

                 req.setAttribute("async","This is an async msg:"+new Date());

                 ctx.dispatch("/a.jsp");

                 System.out.println("finish task."+newDate());

           } catch (InterruptedException e) {

                 // TODO Auto-generated catch block

                 e.printStackTrace();

           }

      }

}

//a.jsp

<%@ pagelanguage="java" contentType="text/html; charset=UTF-8"   pageEncoding="UTF-8"session="false"%>

<!DOCTYPE html PUBLIC"-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<metahttp-equiv="Content-Type" content="text/html;charset=UTF-8">

<title>Insert titlehere</title>

</head>

<body>

      this is a.jsp

      <%="aync return="+new java.util.Date() %>

      <%=request.getAttribute("async")%>

</body>

</html>

 

5 创建异步监听程序:监听异步程序的执行状态。

5.1 目标:监听异步程序的执行进度。

5.2 原理:将消息注入指定类。

5.3 流程:创建Servlet,异步开启新线程。添加异步监听对象。线程结束后,将请求转发到其它的目标或结束。

5.4 方法:AsyncListener对象。

异步监听对象:AsyncListener对象。包括开始、结束、出错、超时的监听。

注意:onStartAsync()不会被调用。因为是startAsync()之后才添加的监听对象。

添加异步监听对象:addListener()。

           ctx.addListener(newAL1());

参考:

http://git.eclipse.org/c/jetty/org.eclipse.jetty.project.git/plain/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncContextListenersTest.java

https://java.net/projects/servlet-spec/lists/users/archive/2013-12/message/1

5.5 示例:监听异步线程

//AsynServlet.java

package lee;

 

import java.io.IOException;

import java.io.PrintWriter;

import java.util.Date;

 

importjavax.servlet.AsyncContext;

importjavax.servlet.ServletException;

importjavax.servlet.annotation.WebServlet;

importjavax.servlet.http.HttpServlet;

importjavax.servlet.http.HttpServletRequest;

importjavax.servlet.http.HttpServletResponse;

 

/**

 * Servlet implementation class AsynServlet

 */

@WebServlet(value="/b.do",asyncSupported=true)

public class AsynServletextends HttpServlet {

      private static final long serialVersionUID = 1L;

      

    /**

     * @see HttpServlet#HttpServlet()

     */

    public AsynServlet() {

        super();

        // TODO Auto-generated constructor stub

    }

 

      /**

       * @see HttpServlet#service(HttpServletRequestrequest, HttpServletResponse response)

       */

      protected void service(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {

           // TODO Auto-generated method stub

           response.setContentType("text/html;charset=GBK"); 

           PrintWriter out=response.getWriter();

           out.println("Start="+newDate()+"</br>");

           out.flush();

           request.setAttribute("org.apache.catalina.ASYNC_SUPPORTED",true);

           AsyncContext ctx=request.startAsync();

           ctx.addListener(newAL1());

           ctx.setTimeout(30*1000);

           ctx.start(new Task(ctx));

           out.println("Main Return="+newDate()+"</br>");

           out.flush();

      }

}

//AL1.java

package lee;

 

import java.io.IOException;

import java.util.Date;

 

importjavax.servlet.AsyncEvent;

import javax.servlet.AsyncListener;

 

public class AL1 implementsAsyncListener {

 

      @Override

      publicvoid onComplete(AsyncEvent arg0) throws IOException {

           // TODO Auto-generated method stub

           System.out.println("Listener=onComplete."+newDate());

      }

 

      @Override

      publicvoid onError(AsyncEvent arg0) throws IOException {

           // TODO Auto-generated method stub

           System.out.println("Listener=onError."+newDate());

      }

 

      @Override

      publicvoid onStartAsync(AsyncEvent arg0) throws IOException {

           // TODO Auto-generated method stub

           System.out.println("Listener=onStartAsync."+newDate());

      }

 

      @Override

      publicvoid onTimeout(AsyncEvent arg0) throws IOException {

           // TODO Auto-generated method stub

           System.out.println("Listener=OnTimeout."+newDate());

      }

 

}

//工作线程:Task.java

package lee;

 

import java.util.Date;

 

importjavax.servlet.AsyncContext;

importjavax.servlet.ServletRequest;

 

public class Task implementsRunnable {

      public Task(AsyncContext ctx) {

           super();

           this.ctx = ctx;

      }

      private AsyncContext ctx=null;

      @Override

      public void run() {

           // TODO Auto-generated method stub

           try {

                 System.out.println("start task."+newDate());

                 Thread.sleep(5000);

                 ServletRequest req=ctx.getRequest();

                 req.setAttribute("async", "This is anasync msg:"+new Date());

                 ctx.dispatch("/a.jsp");

                 System.out.println("finish task."+newDate());

           } catch (InterruptedException e) {

                 // TODO Auto-generated catch block

                 e.printStackTrace();

           }

      }

}

//a.jsp

<%@ pagelanguage="java" contentType="text/html; charset=UTF-8"   pageEncoding="UTF-8"session="false"%>

<!DOCTYPE html PUBLIC"-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<metahttp-equiv="Content-Type" content="text/html;charset=UTF-8">

<title>Insert titlehere</title>

</head>

<body>

      this is a.jsp

      <%="aync return="+new java.util.Date() %>

      <%=request.getAttribute("async") %>

</body>

</html>

 

//结果输出

 

你可能感兴趣的:(java,servlet,javaee,AsyncContext,异步执行)