每个请求来到Web容器,Web容器会为其分配一条执行绪来专门负责该请求,直到回应完成前,该执行绪都不会被释放回容器。 执行绪会耗用系统资源,若有些请求需要长时间处理(例如长时间运算、等待某个资源),就会长时间占用执行绪,若这类的请求很多,许多执行绪都被长时间占用,对于系统就会是个效能负担,甚至造成应用程式的效能瓶颈。

基本上一些需长时间处理的请求,通常客户端也较不在乎请求后要有立即的回应,若可以,让这类请求先释放容器分配给该请求的执行绪,让容器可以有机会将执行绪资源分配给其它的请求,可以减轻系统负担。 原先释放了容器所分配执行绪的请求,其回应将被延后,直到处理完成(例如长时间运算完成、所需资源已获得)再行对客户端的回应。

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

  1. AsyncContext startAsync() throws java.lang.IllegalStateException;
  2. AsyncContext startAsync(ServletRequest servletRequest,
  3. ServletResponse servletResponse)
  4. throws java.lang.IllegalStateException

这两个方法都会传回AsyncContext介面的实作物件,前者会直接利用原有的请求与回应物件来建立AsyncContext ,后者可以让你传入自己建立的请求、回应包裹物件。 在呼叫了startAsync()方法取得AsyncContext物件之后,这次的回应会被延后,并释放容器所分配的执行绪。

你可以透过AsyncContext的getRequest() 、 getResponse()方法取得请求、回应物件,此次对客户端的回应将暂缓至呼叫AsyncContext的complete()方法或dispatch()为止,前者表示回应完成,后者表示将回应调派给指定的URL 。

若要能呼叫ServletRequest的startAsync()使用AsyncContext,你的 Servlet 必须能支援非同步处理,如果使用@WebServlet来标注,则可以设定其asyncSupported为true 。 例如:

  1. @WebServlet(urlPatterns = "/some.do", asyncSupported = true )
  2. public class AsyncServlet extends HttpServlet {
  3. ...

如果使用web.xml设定Servlet,则可以设定<async-supported>标签为true :

  1. ...
  2. <servlet>
  3. <servlet-name>AsyncServlet</servlet-name>
  4. <servlet-class>cc.openhome.AsyncServlet</servlet-class>
  5. <async-supported>true</async-supported>
  6. </servlet>
  7. ...

如果Servlet将会非同步处理,若其前端有过滤器,则过滤器亦需标示其支援非同步处理,如果使用@WebFilter ,同样是可以设定其asyncSupported为true 。 例如:

  1. @WebFilter(urlPatterns = "/some.do", asyncSupported = true )
  2. public class AsyncFilter implements Filter{
  3. ...

如果使用web.xml设定过滤器,则可以设定<async-supported>标签为true :

  1. ...
  2. <filter>
  3. < filter -name>AsyncFilter</ filter -name>
  4. < filter -class>cc.openhome.AsyncFilter</ filter -class>
  5. <async-supported>true</async-supported>
  6. </ filter >
  7. ...

底下示范一个非同步处理的例子,对于进来的请求,Servlet会取得其AsyncContext ,并释放容器所分配的执行绪,回应被延后,对于这些被延后回应的请求,建立一个Runnable的物件,并将其排入一个执行绪池(Thread pool),执行绪池的执行绪数量是固定的,让这些必须长时间处理的请求,在这些有限数量的执行绪中完成,而不用每次请求都占用容器所分配的执行绪。

  1. package cc.openhome;
  2. import java.io.*;
  3. import java.util.concurrent.*;
  4. import javax.servlet.*;
  5. import javax.servlet.annotation.*;
  6. import javax.servlet.http.*;
  7. @WebServlet(name="AsyncServlet", urlPatterns={"/async.do"},
  8. asyncSupported = true )
  9. public class AsyncServlet extends HttpServlet {
  10. // 执行绪池
  11. private ExecutorService executorService = Executors.newFixedThreadPool(10);
  12. protected void processRequest(HttpServletRequest request,
  13. HttpServletResponse response)
  14. throws ServletException, IOException {
  15. response.setContentType("text/html; charset=UTF8");
  16. AsyncContext ctx = request.startAsync();
  17. executorService.submit(new AsyncRequest(ctx));
  18. }
  19. @Override
  20. protected void doGet(HttpServletRequest request,
  21. HttpServletResponse response)
  22. throws ServletException, IOException {
  23. processRequest(request, response);
  24. }
  25. @Override
  26. protected void doPost(HttpServletRequest request,
  27. HttpServletResponse response)
  28. throws ServletException, IOException {
  29. processRequest(request, response);
  30. }
  31. @Override
  32. public void destroy() {
  33. executorService.shutdown();
  34. }
  35. }

AsyncRequest是个实作Runnable的类别,其模拟了长时间处理:

    1. package cc.openhome;
    2. import java.io.PrintWriter;
    3. import javax.servlet.AsyncContext;
    4. public class AsyncRequest implements Runnable {
    5. private AsyncContext ctx;
    6. public AsyncRequest( AsyncContext ctx ) {
    7. this.ctx = ctx;
    8. }
    9. @Override
    10. public void run() {
    11. try {
    12. // 模拟长时间的处理
    13. Thread.sleep(10000);
    14. PrintWriter out = ctx.getResponse() .getWriter();
    15. out.println("久等了...XD");
    16. // 这边才真正送出回应
    17. ctx.complete();
    18. } catch (Exception e) {
    19. e.printStackTrace();
    20. }
    21. }
    22. }  

Servlet3.0: 简介AsyncContext的更多相关文章

  1. Spring注解开发系列VII --- Servlet3.0

    Servlet3.0简介 Servlet 3.0 作为 Java EE 6 规范体系中一员,随着 Java EE 6 规范一起发布.该版本在前一版本(Servlet 2.5)的基础上提供了若干新特性用 ...

  2. Servlet3.0的异步

    servlet之前的操作同时同步的,就是按照这样的一个流程来走的: 1.请求根据一个路径路由到一个servlet中, 2.servlet获取一系列的参数 3.执行一系列的逻辑(花费时间所占的比重也更大 ...

  3. Servlet3.0中Servlet的使用

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

  4. Servlet3.0新特性

    1 Servlet3.0新特性概述 使用要求:MyEclipse10.0或以上版本,发布到Tomcat7.0或以上版本,创建JavaEE6.0应用! Servlete3.0的主要新特性如下三部分: 使 ...

  5. Servlet3.0的新特性

    注意:Servlet3.0的项目一定要使用Tomcat7.0才能看到效果!! 1.新增标注支持     在Servlet3.0的部署描述文件web.xml的顶层标签<web-app>中有一 ...

  6. [译]servlet3.0与non-blocking服务端推送技术

    Non-blocking(NIO)Server Push and Servlet 3 在我的前一篇文章写道如何期待成熟的使用node.js.假定有一个框架,基于该框架,开发者只需要定义协议及相关的ha ...

  7. Servlet3.0新特性使用详解

    可插拔的Web框架 几乎所有基于Java的web框架都建立在servlet之上.现今大多数web框架要么通过servlet.要么通过Web.xml插入.利用标注(Annotation)来定义servl ...

  8. Servlet3.0新特性(从注解配置到websocket编程)

    Servlet3.0的出现是servlet史上最大的变革,其中的许多新特性大大的简化了web应用的开发,为广大劳苦的程序员减轻了压力,提高了web开发的效率.主要新特性有以下几个: 引入注解配置 支持 ...

  9. Java自学手记——servlet3.0新特性

    servlet3.0出来已经很久了,但市场上尚未普遍应用,servlet3.0有三个比较重要的新特性:使用注解来代替配置文件,异步处理以及上传组件支持. 支持servlet3.0的要求:MyEclip ...

随机推荐

  1. HDOJ 4812 D Tree

    Discription There is a skyscraping tree standing on the playground of Nanjing University of Science ...

  2. Codeforces 785D Anton and School - 2(组合数)

    [题目链接] http://codeforces.com/problemset/problem/785/D [题目大意] 给出一个只包含左右括号的串,请你找出这个串中的一些子序列, 要求满足" ...

  3. POJ 2226 Muddy Fields (二分图匹配)

    [题目链接] http://poj.org/problem?id=2226 [题目大意] 给出一张图,上面有泥和草地,有泥的地方需要用1*k的木板覆盖, 有草地的地方不希望被覆盖,问在此条件下需要的最 ...

  4. 【数论】【最大公约数】【枚举约数】CODEVS 1012 最大公约数和最小公倍数问题 2001年NOIP全国联赛普及组

    对于一对数(p,q),若它们的gcd为x0,lcm为y0, 则:p*q/x0=y0,即q=x0*y0/p, 由于p.q是正整数,所以p.q都必须是x0*y0的约数. 所以O(sqrt(x0*y0))地 ...

  5. 1.2(学习笔记)Servlet基础(doGet、doPost、生命周期、页面跳转)

    一.doGet()与doPost() 我们在TestServlet类中重写doGet().doPost().service(). import javax.servlet.ServletExcepti ...

  6. 通信编码解码 c11 实现 [ lua 专用版]

    #include <istream> #include <ostream> #include <iostream> #include <strstream&g ...

  7. redis命令行清缓存

    任务管理器-服务-redis 右击打开详细信息--右击打开文件位置 在这个位置cmd 输入命令redis-cli 在输入命令:flushall 出现ok即清除缓存成功

  8. CSS部分属性的深入学习

    先上个张鑫旭大神的政治课,来个一棒打醒(手动滑稽): 说说CSS学习中的瓶颈: 虽然自己水平不高,但是对于重构这方面工作一直不怎么喜欢,可能觉得比较没有新意,但是看了大神文章突然有点一棍打醒的感觉,突 ...

  9. 【jQuery】jquery中 使用$('#parentUid').attr(parentUid);报错jquery-1.11.3.min.js:5 Uncaught TypeError: Cannot read property 'nodeType' of undefined

    jquery中 使用$('#parentUid').attr(parentUid);报错jquery-1.11.3.min.js:5 Uncaught TypeError: Cannot read p ...

  10. 用iptables做NAT代理,使内网机器上外网

    现状:服务器A只有一个内网IP,不能上外网,内网IP与服务器B内网相通:服务器B有一个内网IP和公网IP.想实现服务器A也能上外网. 1 2 3 4 服务器A:内网网卡:eth0 内网IP:192.1 ...