文档章节

Servlet3.0提供的异步处理

摆渡者
 摆渡者
发布于 2014/03/03 21:18
字数 1054
阅读 316
收藏 3

    在以前的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类:

@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();
  }
}

 

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的内容:

<%@ 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>子元素,以下是一个配置片段:

<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):当异步调用超时时触发该方法

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

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()方法即可完成监听器的注册:

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


© 著作权归作者所有

摆渡者
粉丝 343
博文 171
码字总数 206504
作品 0
成都
程序员
私信 提问
多线程和Servlet3.0中的异步有什么区别啊

最近在看servlet3.0异步处理,为什么感觉servlet3.0的异步也就是增加了一个线程,他们有什么区别啊。我写了两个实验,一个是直接调用线程,另一个用异步,发现没什么区别啊????...

jerry2012
2013/09/14
316
0
Servlet3.0中Servlet的使用

目录 1.注解配置 2.异步调用 3.文件上传 相对于之前的版本,Servlet3.0中的Servlet有以下改进: 支持注解配置。 支持异步调用。 直接有对文件上传的支持。 在这篇文章中我将主要讲这三方面的...

王爵nice
2014/08/04
3.2K
0
java web 当有一个耗时操作时,该怎么处理

java web servlet 当有一个耗时操作时,该怎么处理,需要考虑到并发的情况!是直接用servlet3.0提供的异步处理,还是开一个线程池呢。

jerry2012
2013/10/08
365
2
Servlet3.0异步的实现需要http1.1的支持?

今天我在学习servlet3.0的新特性:servlet3.0对异步的支持。 网上有人说,servlet3.0对异步的支持需要http1.1。 现在我把servelt3.0对异步支持的原理也理解的差不多了,并且查阅了http1.1相比...

张凯乐
2016/12/30
252
3
Servlet3.0新特性剖析

Servlet3.0规范的新特性主要是为了3个目的: 1.简化开发 2.便于布署 3.支持Web2.0原则 为了简化开发流程,Servlet3.0引入了注解(annotation),这使得web布署描述符web.xml不在是必须的选择...

长平狐
2012/09/03
222
0

没有更多内容

加载失败,请刷新页面

加载更多

Hibernate 5 的模块/包(modules/artifacts)

Hibernate 的功能被拆分成一系列的模块/包(modules/artifacts),其目的是为了对依赖进行独立(模块化)。 模块名称 说明 hibernate-core 这个是 Hibernate 的主要(main (core))模块。定义...

honeymoose
29分钟前
2
0
CSS--属性

一、溢出 当内容多,元素区域小的时候,就会产生溢出效果,默认是纵向溢出 横向溢出:在内容和容器之间再套一层容器,并且内部容器要比外部容器宽 属性:overflow/overflow-x/overflow-y 取值...

wytao1995
48分钟前
4
0
精华帖

第一章 jQuery简介 jQuery是一个JavaScript库 jQuery具备简洁的语法和跨平台的兼容性 简化了JavaScript的操作。 在页面中引入jQuery jQuery是一个JavaScript脚本库,不需要特别的安装,只需要...

流川偑
今天
6
0
语音对话英语翻译在线翻译成中文哪个方法好用

想要进行将中文翻译成英文,或者将英文翻译成中文的操作,其实有一个非常简单的工具就能够帮助完成将语音进行翻译转换的软件。 在应用市场或者百度手机助手等各大应用渠道里面就能够找到一款...

401恶户
今天
3
0
jenkins 插件下载加速最终方案

推荐做法 1、告诉jenkins 我哪些插件需要更新 jenkins插件清华大学镜像地址 https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json 1.进入jenkins系统管理 2.进入插件管...

vasks
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部