Servlet 3.0异步处理请求

来源:互联网 发布:sql insert into set 编辑:程序博客网 时间:2024/05/20 17:25

一、servlet3.0异步请求相关方法

startAsync(servletRequest, servletResponse)

传入指定的request和response对象,便于在AsyncContext中重复使用(这样被Filter、Servlet包装过的请求、相应对象才会在异步的环境下继续生效)。

startAsync()

若request或者response被包装,将失去预期的效果。

isAsyncSupported() 和 isAsyncStarted()

辅助性的方法,用于判断当前请求是否支持异步或者异步已经开始。

getAsyncContext()

需要在异步启动之后才能够访问,否则会报异常。

二、在AsyncContext中分发的方法有三个,不太容易区分

AsyncContext.dispatch()

若当前AsyncContext由ServletRequest.startAsync(ServletRequest, ServletResponse)方法启动,返回的地址可以通过HttpServletRequest.getRequestURI()得到。否则,分发的地址则是当前URL request对象最后一次分发的地址。虽有些拗口,两者分发的地址大部分情况下一致;但尽量使用带有参数的异步上下文启动器。如请求/asyncDispatch2Async?disUrl=self,执行dispatch()方法之后,自身会再次分发到自身,包括传递的参数。

AsyncContext.dispatch(String path)

等同于ServletRequest.getRequestDispatcher(String),算是一个快捷方法。 可以转向一个同步或异步的servlet,或者JSP,或其它资源地址等。

AsyncContext.dispatch(ServletContext context, String path)

请求的地址将在给定的上下文里面(ServletContext),有有可能传入的上下文与当前站带你应用的上下文有所区别。

三、范例:

AsyncContext context = request.startAsync(request, response);String result = remoteServerHandle(context, requestObject, isEncrypt);          //获取处理结果context.complete();protected void doPost(HttpServletRequest req, HttpServletResponse resp)         throws ServletException, IOException {      resp.setContentType("text/plain;charset=UTF-8");      final PrintWriter writer = resp.getWriter();      writer.println("异步之前输出的内容。");      writer.flush();      //开始异步调用,获取对应的AsyncContext。      final AsyncContext asyncContext = req.startAsync();      //设置超时时间,当超时之后程序会尝试重新执行异步任务,即我们新起的线程。      asyncContext.setTimeout(10*1000L);      //新起线程开始异步调用,start方法不是阻塞式的,它会新起一个线程来启动Runnable接口,之后主程序会继续执行      asyncContext.start(new Runnable() {         @Override         public void run() {            try {                Thread.sleep(5*1000L);                writer.println("异步调用之后输出的内容。");                writer.flush();                //异步调用完成,如果异步调用完成后不调用complete()方法的话,异步调用的结果需要等到设置的超时                //时间过了之后才能返回到客户端。                asyncContext.complete();            } catch (Exception e) {                e.printStackTrace();            }         }      });      writer.println("可能在异步调用前输出,也可能在异步调用之后输出,因为异步调用会新起一个线程。");      writer.flush();}

四、注意事项:

在Servlet 3.0中,在ServletRequest上提供了startAsync()方法:

AsyncContext startAsync() throws java.lang.IllegalStateException;AsyncContext startAsync(ServletRequest servletRequest,  ServletResponse servletResponse)                        throws java.lang.IllegalStateException

这两个方法都会返回AsyncContext接口的实现对象,前者会直接利用原有的请求与响应对象来创建AsyncContext,后者可以传入自行创建的请求、响应封装对象。在调用了startAsync()方法取得AsyncContext对象之后,此次请求的响应会被延后,并释放容器分配的线程。
可以通过AsyncContext的getRequest()、getResponse()方法取得请求、响应对象,此次对客户端的响应将暂缓至调用AsyncContext的complete()或dispatch()方法为止,前者表示响应完成,后者表示将调派指定的URL进行响应。

  • 如果使用web.xml设置Servlet,则可以在中设置标签为true:
<servlet>    <servlet-name>AsyncServlet</servlet-name>    <servlet-class>cc.openhome.AsyncServlet</servlet-class>    <async-supported>true</async-supported></servlet><filter>    <filter-name>gzipFilter</filter-name>    <filter-class>com.vlife.health.web.filter.gzip.GZIPFilter</filter-class>    <async-supported>true</async-supported></filter><filter-mapping>    <filter-name>gzipFilter</filter-name>    <url-pattern>*.do</url-pattern></filter-mapping><servlet>    <servlet-name>dispatcher</servlet-name>    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>    <init-param>        <param-name>namespace</param-name>        <param-value>conf/hipee</param-value>    </init-param>    <load-on-startup>1</load-on-startup>    <async-supported>true</async-supported></servlet><servlet-mapping>    <servlet-name>dispatcher</servlet-name>    <url-pattern>*.do</url-pattern></servlet-mapping>
  • 如果在web.xml中设置了其他的filter或者servlet,都需要添加 <async-supported>true</async-supported>
原创粉丝点击