servlet异步处理机制
Servlet 3.0 之前,一个普通 Servlet 的主要工作流程大致如下:首先,Servlet 接收到请求之后,可能需要对请求携带的数据进行一些预处理;接着,调用业务接口的某些方法,以完成业务处理;最后,根据处理的结果提交响应,Servlet 线程结束。其中第二步的业务处理通常是最耗时的,这主要体现在数据库操作,以及其它的跨网络调用等,在此过程中,Servlet 线程一直处于阻塞状态,直到业务方法执行完毕。在处理业务的过程中,Servlet 资源一直被占用而得不到释放,对于并发较大的应用,这有可能造成性能的瓶颈。对此,在以前通常是采用私有解决方案来提前结束 Servlet 线程,并及时释放资源。
Servlet 3.0 针对这个问题做了开创性的工作,现在通过使用 Servlet 3.0 的异步处理支持,之前的 Servlet 处理流程可以调整为如下的过程:首先,Servlet 接收到请求之后,可能首先需要对请求携带的数据进行一些预处理;接着,Servlet 线程将请求转交给一个异步线程来执行业务处理,线程本身返回至容器,此时 Servlet 还没有生成响应数据,异步线程处理完业务以后,可以直接生成响应数据(异步线程拥有 ServletRequest 和 ServletResponse 对象的引用),或者将请求继续转发给其它 Servlet。如此一来, Servlet 线程不再是一直处于阻塞状态以等待业务逻辑的处理,而是启动异步线程之后可以立即返回。
异步处理特性可以应用于 Servlet 和过滤器两种组件,由于异步处理的工作模式和普通工作模式在实现上有着本质的区别,因此默认情况下,Servlet 和过滤器并没有开启异步处理特性,如果希望使用该特性,则必须按照如下的方式启用:
- 对于使用传统的部署描述文件 (web.xml) 配置 Servlet 和过滤器的情况,Servlet 3.0 为 <servlet> 和 <filter> 标签增加了 <async-supported> 子标签,该标签的默认取值为 false,要启用异步处理支持,则将其设为 true 即可。以 Servlet 为例,其配置方式如下所示:
12345<servlet><servlet-name>DemoServlet</servlet-name><servlet-class>footmark.servlet.Demo Servlet</servlet-class><async-supported>true</async-supported></servlet>
- 对于使用 Servlet 3.0 提供的 @WebServlet 和 @WebFilter 进行 Servlet 或过滤器配置的情况,这两个注解都提供了 asyncSupported 属性,默认该属性的取值为 false,要启用异步处理支持,只需将该属性设置为 true 即可。以 @WebFilter 为例,其配置方式如下所示:
| 1 2 | @WebFilter(urlPatterns = "/demo",asyncSupported = true) public class DemoFilter implements Filter{...} | 
一个简单的模拟异步处理的 Servlet 示例如下:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | @WebServlet(urlPatterns = "/demo", asyncSupported = true)public class AsyncDemoServlet extends HttpServlet {    @Override    public void doGet(HttpServletRequest req, HttpServletResponse resp)    throws IOException, ServletException {        resp.setContentType("text/html;charset=UTF-8");        PrintWriter out = resp.getWriter();        out.println("进入Servlet的时间:" + new Date() + ".");        out.flush();        //在子线程中执行业务调用,并由其负责输出响应,主线程退出        AsyncContext ctx = req.startAsync();        new Thread(new Executor(ctx)).start();        out.println("结束Servlet的时间:" + new Date() + ".");        out.flush();    }}public class Executor implements Runnable {    private AsyncContext ctx = null;    public Executor(AsyncContext ctx){        this.ctx = ctx;    }    public void run(){        try {            //等待十秒钟,以模拟业务方法的执行            Thread.sleep(10000);            PrintWriter out = ctx.getResponse().getWriter();            out.println("业务处理完毕的时间:" + new Date() + ".");            out.flush();            ctx.complete();        } catch (Exception e) {            e.printStackTrace();        }    }} | 
除此之外,Servlet 3.0 还为异步处理提供了一个监听器,使用 AsyncListener 接口表示。它可以监控如下四种事件:
- 异步线程开始时,调用 AsyncListener 的 onStartAsync(AsyncEvent event) 方法;
- 异步线程出错时,调用 AsyncListener 的 onError(AsyncEvent event) 方法;
- 异步线程执行超时,则调用 AsyncListener 的 onTimeout(AsyncEvent event) 方法;
- 异步执行完毕时,调用 AsyncListener 的 onComplete(AsyncEvent event) 方法;
要注册一个 AsyncListener,只需将准备好的 AsyncListener 对象传递给 AsyncContext 对象的 addListener() 方法即可,如下所示:
| 1 2 3 4 5 6 7 | AsyncContext ctx = req.startAsync(); ctx.addListener(new AsyncListener() {     public void onComplete(AsyncEvent asyncEvent) throws IOException {         // 做一些清理工作或者其他    }     ... }); | 
servlet异步处理机制的更多相关文章
- nacos 使用 servlet 异步处理客户端配置长轮询
		config 客户端 ClientWorker#ClientWorker 构造方法中启动定时任务 ClientWorker.LongPollingRunnable 长轮询的任务,在 run 方法的结尾 ... 
- Servlet异步上传文件
		这里需要用到插件ajaxfileupload.js,jar包:commons-fileupload-1.3.2.jar,commons-io-2.5.jar 注意红色部分的字!!!! 1.创建一个we ... 
- Android异步任务机制之AsycTask
		在Android中实现异步任务机制有两种方式,Handler和AsyncTask. 本篇就说说AsyncTask的异步实现. 1.什么时候使用 AsnyncTask 在上一篇文章已经说了,主线程主要负 ... 
- Android异步消息处理机制
		安卓子线程无法直接更改UI,所以需要异步消息处理机制来解决 <?xml version="1.0" encoding="utf-8"?><Li ... 
- Android_AsyncTask异步任务机制
		今天我们学习了 AsyncTack, 这是一个异步任务. 那么这个异步任务可以干什么呢? 因为只有UI线程,即主线程可以对控件进行更新操作.好处是保证UI稳定性,避免多线程对UI同时操作. 同时要把耗 ... 
- Android 异步消息处理机制解析
		Android 中的异步消息处理主要由四个部分组成,Message.Handler.MessageQueue.Looper.下面将会对这四个部分进行一下简要的介绍. 1. Message: Messa ... 
- Android多线程----异步消息处理机制之Handler详解
		[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ... 
- 【译】深入理解python3.4中Asyncio库与Node.js的异步IO机制
		转载自http://xidui.github.io/2015/10/29/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3python3-4-Asyncio%E5%BA%93% ... 
- 【转】Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
		转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38377229 ,本文出自[张鸿洋的博客] 很多人面试肯定都被问到过,请问Andr ... 
随机推荐
- 【转载】JVM 学习——垃圾收集器与内存分配策略
			本文主要是对<深入理解java虚拟机 第二版>第三章部分做的总结,文章中大部分内容都来自这章内容,也是博客 JVM 学习的第二部分. 简述 说到垃圾收集(Garbage Collectio ... 
- numpy小结
			<python数据科学>笔记 在线版地址:https://github.com/jakevdp/PythonDataScienceHandbook 1.常用np简写 import num ... 
- linux中centros6.7安装php5.6,httpd-2.2.19(web产品化)遇到的问题总结
			前段时间在公司实习,web系统产品化的过程踩了很多坑,在这边总结一下,由于对linux不是很懂,全是自己一步步一个一个问题解决的 1,查看系统中是否安装apache,php,mysql环境 Apach ... 
- KAFKA跨主机部署网络不通解决思路
			Kafka的部署不仅需要集群可用,同时需要对orderer节点可连,这就是为什么有的时候,kafka集群本身没问题,但是orderer却总是报错. 为了试验kafka剥离方案的可行性,跨阿里云网络和内 ... 
- 解决一次git问题
			由于特殊原因,工作中不能使用sourcetree,今天遇到了一个问题记录一下解决办法,后续还是得好好去廖雪峰大神那里学习一下git的命令行操作呀 You have not concluded your ... 
- 近期wxss总结
			最近有一些需要点击才能实现的样式切换,我用的方法有2种 1 wxml 中 对class给一个判断式 class="变量?变化后的类:变化前的类" 这样在js中设一个变量,我是设成布 ... 
- String 、Stringbuilder和StringBuffer的区别
			JAVA平台提供了三个类:String.StringBuilder和StringBuffer,它们可以储存和操作字符串,即包含多个字符的字符数据.这个String类提供了数值不可改变的字符串.而这个S ... 
- 方程的解_NOI导刊2010提高
			方程的解 给定x,求\(a_1+a_2+...+a_k=x^x\ mod\ 1000\)的正整数解解的组数,对于100%的数据,k≤100,x≤2^31-1. 解 显然x是可以快速幂得到答案的,而该问 ... 
- 1GB pages can only be allocated at boot time using hugepages= and not freed afterwards
			2018-6-27 9:12:38 https://stackoverflow.com/questions/26385554/error-setting-nr-hugepages-via-sysfs ... 
- Postman中x-www-form-urlencoded请求K-V的ajax实现
			在Postman中使用x-www-form-urlencoded,并且用K-V传值,但是在代码中用ajax来请求,传值一直有问题,静下心来思考才发现K-V传入的是string,所以记录下来以防忘记!! ... 
