Servlet3.0提供的异步处理

简介:

    在以前的Servlet规范中,如果Servlet作为控制器调用了一个耗时的业务方法,那么Servlet必须等到业务方法完全返回之后才会生成响应,这将使得Servlet对业务方法的调用变成一种阻塞式的调用,因此效率比较低。Servlet3.0规范引入了异步处理来解决这个问题,异步处理允许Servlet重新发起一条线程去调用耗时的业务方法,这样就可以避免等待。

    Servlet3.0的异步处理是通过AsyncContext类来处理的,Servlet可通过ServletRequest的如下两个方法来开启异步调用、创建AsyncContext对象:

  • AsyncContext startAsync()

  • AsyncContext startAsync(ServletRequest, ServletResponse)

    重复调用上面的方法将得到同一个AsyncContext对象。AsyncContext对象代表异步处理的上下文,它提供了一些工具方法,可完成设置异步调用的超时时长,dispatch用于请求、启动后台线程、获取request,response对象等功能,下面是一个进行异步处理的Servlet类:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@WebServlet (urlPatterns= "/async" , asyncSupported= true )
public  class  AsyncServlet  extends  HttpServlet {
   public  void  doGet(HttpServletRequest req, HttpServletResponse resp)  throws  IOException, ServletException {
    response.setContentType( "text/html;charset=GBK" );
    PrintWriter out = response.getWriter();
    out.println( "进入Servlet的时间:"  new  Date() +  ".<br/>" );
    out.flush();
    AsyncContext acontext = request.startAsync();
    acontext.setTimeout( 20 * 1000 );
    acontext.start( new  Executor(acontext));
    out.println( "结束Servlet的时间:"  new  Date() +  ".<br/>" );
    out.flush();
  }
}

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public  class  Executor  implements  Runnable {
   private  AsyncContext context;
   public  Executor(AsyncContext context) { this .context = context;}
   public  void  run(){
     try  {
      Thread.sleep( 5000 );
      ServletRequest request = context.getRequest();
      List<String> books =  new  ArrayList<String>();
      books.add( "book1" ); books.add( "book2" ); books.add( "book3" );
      request.setAttribute( "books" , books);
      context.dispatch( "/async.jsp" );
    }  catch  (Exception e) {
      e.printStachTrace();
    }
  }
}

    在此Executor中,让线程睡眠5秒来模拟调用的耗时的业务方法,最后调用AsyncContext的dispatch方法把请求转发到指定的JSP页面。被异步请求的JSP页面需要指定session="false",表明该页面不会重新创建Session,下面是async.jsp的内容:

?
1
2
3
4
5
6
7
8
9
10
11
<%@ page contentType="text/html;chaset=GBK" language="java" session="fasle" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
< ul >
  < c:forEach  items = "${books}"  var = "book"  >
    < li >${book}</ li >
  </ c:forEach >
</ ul >
<%
  out.println("业务调用结束的时间:" + new Date());
  request.getAsyncContext().complete();//完成异步调用
%>

    上面的页面只是一个JSP页面,只是使用了JSTL标签库来迭代输出books集合,因此需要将JSTL的两个Jar包复制到项目的lib目录中。

对于希望启用异步调用的Servlet而言,开发者必须显示指定开启异步调用,为Servlet开启异步调用有两种方式:1). 在@WebServlet中指定asyncSupported=true  2). 在web.xml的<servlet>元素中增加<async-supported>子元素,以下是一个配置片段:

?
1
2
3
4
5
6
7
8
9
< servlet >
  < servlet-name >async</ servlet-name >
  < servlet-class >com.abc.AsyncServlet</ servlet-class >
  < async-supported >true</ async-supported >
</ servlet >
< servlet-mapping >
  < servlet-name >async</ servlet-name >
  < url-pattern >/async</ url-pattern >
</ servlet-mapping >

    对于支持异步调用的Servlet来说,当Servlet以异步方式启用新线程后,该Servlet的执行不会被阻塞,该Servlet将可以向客户端浏览器生成相应——当新线程执行完成后,新线程生成的相应将再次被送往客户端浏览器。

    当Servlet启用异步调用的线程之后,该线程的执行过程对开发者是透明的。但在有些情况下,开发者需要了解该异步线程的执行细节,并针对特定的执行结果进行针对性处理,这可以借助于Servlet3.0提供的异步监听器来实现。异步监听器需要实现AsyncListener接口,该接口中定义了如下方法:

  • onStartAsync(AsyncEvent event):当异步调用开始时触发该方法

  • onComplete(AsyncEvent event):当异步调用结束时触发该方法

  • onError(AsyncEvent event):当异步调用出错时触发该方法

  • onTimeout(AsyncEvent event):当异步调用超时时触发该方法

    下面是一个简单的监听器类:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public  class  MyAsyncListener  implements  AsyncListener {
   public  void  onComplete(AsyncEvent event) {
    System.out.println( "异步调用完成:"  new  Date());
  }
   public  void  onError(AsyncEvent event) {
    System.out.println( "异步调用出错:"  new  Date());
  }
   public  void  onStartAsync(AsyncEvent event) {
    System.out.println( "异步调用开始:"  new  Date());
  }
   public  void  onTimeout(AsyncEvent event) {
    System.out.println( "异步调用超时:"  new  Date());
  }
}

提供了监听器之后,还需要通过AsynContext来注册此监听器,调用该对象的addListener()方法即可完成监听器的注册:

?
1
2
AsyncContext acontext = request.startAsync();
acontext.addListener( new  MyAsyncListener());

目录
相关文章
|
4月前
|
存储 Java 容器
SpringMVC与Servlet3.0整合实现异步处理
SpringMVC与Servlet3.0整合实现异步处理
66 1
|
4月前
|
Java 数据库 容器
Servlet3.0中支持的异步处理
Servlet3.0中支持的异步处理
59 1
|
Java 数据库 容器
Servlet异步处理性能优化的过程
Servlet异步处理性能优化的过程
193 0
Servlet异步处理性能优化的过程
厉害了,Servlet3的异步处理机制
Servlet3发布好几年了,又有多少人知道它的新特性呢?下面简单介绍下。
107 0
厉害了,Servlet3的异步处理机制
Servlet3发布好几年了,又有多少人知道它的新特性呢?下面简单介绍下。 主要增加了以下特性: 1、异步处理支持 2、可插性支持 3、注解支持,零配置,可不用配置web.xml ... 异步处理是什么鬼? 直接操起键盘干。
958 0
|
Java 容器 调度
Servlet 异步处理
web容器会为每个请求分配一个线程,Servlet3.0新增了异步处理,解决多个线程不释放占据内存的问题。可以先释放容器分配给请求的线程与相关资源,减轻系统负担,原先释放了容器所分配线程的请求,其响应将被延后,可以在处理完成后再对客户端进行响应。
873 0
|
22天前
|
缓存 安全 Java
Java服务器端技术:Servlet与JSP的集成与扩展
Java服务器端技术:Servlet与JSP的集成与扩展
15 3
|
22天前
|
存储 缓存 前端开发
Servlet与JSP在Java Web应用中的性能调优策略
Servlet与JSP在Java Web应用中的性能调优策略
22 1
|
22天前
|
存储 Java 关系型数据库
基于Servlet和JSP的Java Web应用开发指南
基于Servlet和JSP的Java Web应用开发指南
14 0
|
22天前
|
前端开发 安全 Java
在Java服务器端开发的浩瀚宇宙中,Servlet与JSP犹如两颗璀璨的明星,它们联袂登场,共同编织出动态网站的绚丽篇章。
在Java服务器端开发的浩瀚宇宙中,Servlet与JSP犹如两颗璀璨的明星,它们联袂登场,共同编织出动态网站的绚丽篇章。
15 0