Servlet工作流程

Servlet 3.0 之前,一个普通 Servlet 的主要工作流程大致如下:

  1. Servlet 接收到请求之后,可能需要对请求携带的数据进行一些预处理;
  2. 调用业务接口的某些方法,以完成业务处理;
  3. 最后,根据处理的结果提交响应,Servlet 线程结束。

servlet是单例多线程的,当servlet线程池满了的时候,后续访问该Servlet的请求只能进行等待

其中第二步的业务处理通常是最耗时的,这主要体现在数据库操作,以及其它的跨网络调用等,在此过程中,Servlet 线程一直处于阻塞状态,直到业务方法执行完毕。在处理业务的过程中,Servlet 资源一直被占用而得不到释放,对于并发较大的应用,这有可能造成性能的瓶颈。对此,在以前通常是采用私有解决方案来提前结束 Servlet 线程,并及时释放资源。

Servlet3.0异步处理

Servlet 3.0 针对这个问题做了开创性的工作,现在通过使用 Servlet 3.0 的异步处理支持,之前的 Servlet 处理流程可以调整为如下的过程:

  1. 首先,Servlet 接收到请求之后,可能首先需要对请求携带的数据进行一些预处理;
  2. 接着,Servlet 线程将请求转交给一个异步线程来执行业务处理,线程本身返回至容器,此时 Servlet 还没有生成响应数据,异步线程处理完业务以后,可以直接生成响应数据(异步线程拥有 ServletRequest 和 ServletResponse 对象的引用),或者将请求继续转发给其它 Servlet。如此一来, Servlet 线程不再是一直处于阻塞状态以等待业务逻辑的处理,而是启动异步线程之后可以立即返回。

代码示例一:

首先创建一个动态的web工程

public class DemoThread implements Runnable {
private PrintWriter out; public DemoThread(PrintWriter out) {
this.out = out;
} @Override
public void run() {
out.println("子线程---运行<br>");
int sum = 0;
for (int i = 0; i < 10; i++) {
System.out.println("i = " + i);
sum += i;
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
out.println("sum = " + sum + "<br>");
out.println("子线程---结束<br>");
}
}
@WebServlet("/demo")
public class DemoServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.print("主线程开始运行<br>");
new Thread(new DemoThread(out)).start();
out.print("主线程运行结束<br>");
}
}

使用Servelt3.0注解方式创建的一个DemoServlet,我们运行tomcat容器并访问这个Servlet

观察控制台:

这与我们需要的展示效果相差甚远 :主线程直接就结束了,子线程依旧在运行


注意:

异步处理特性可以应用于 Servlet 和过滤器两种组件,由于异步处理的工作模式和普通工作模式在实现上有着本质的区别,因此默认情况下,Servlet 和过滤器并没有开启异步处理特性,如果希望使用该特性,则必须按照如下的方式启用:

我们开启Servelt异步处理后,改写代码观察结果:

// asyncSupported 默认为false,
@WebServlet(value = "/demo",asyncSupported = true)
public class DemoServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.println("进入Servlet的时间:" + new Date() + "<br>"); //在子线程中执行业务调用,并由其负责输出响应,主线程退出
AsyncContext ctx = request.startAsync();
new Thread(new DemoThread(ctx)).start();
out.println("结束Servlet的时间:" + new Date() + "<br>");
}
}
public class DemoThread implements Runnable {

    private AsyncContext ctx = null;

    public DemoThread(AsyncContext ctx) {
this.ctx = ctx;
} @Override
public void run() {
int sum = 0;
try {
// 通过此种方式就能获取到响应流
PrintWriter out = ctx.getResponse().getWriter();
out.println("子线程---运行<br>");
sum = 0;
for (int i = 0; i < 10; i++) {
System.out.println("i = " + i);
sum += i;
Thread.sleep(1000L);
}
out.println("sum = " + sum + "<br>");
out.println("子线程---结束<br>");
out.println("业务处理完毕的时间:" + new Date() + "<br>");
ctx.complete();
} catch (Exception e) {
e.printStackTrace();
}
}
}

观察时间可以发现,Servlet线程运行完就结束了,返回到线程池,大大节省了资源,如果有多个请求,就能够处理接下来的请求。而我们的DemoThread线程依旧能够生成响应数据

Servlet3.0对异步处理的支持的更多相关文章

  1. Servlet 3.0 对异步处理的支持

    Servlet 3.0 实现了对异步处理的支持 通过利用注解@WebServlet(urlPatterns="/AServlet" AysnsSupported=true) 让后n ...

  2. Servlet3.0的异步

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

  3. 十三:Servlet3.0的异步

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

  4. 深入理解Servlet3.0异步请求

    异步请求的基础概念 异步请求最直接的用法就是处理耗时业务,Http协议是单向的,只能客户端拉不能服务器主推. 异步请求的核心原理主要分为两大类:1.轮询.2长连接 轮询:就是定时获取返回结果. 长连接 ...

  5. Filter学习总结,顺便提及点servlet3.0异步filter和异步监听

      Filter介绍:     Filter在项目中经常可以用到,通常配置在web.xml中.是服务器端的一个组件,对于用户的请求和响应数据进行过滤操作,控制是否让用户访问到对应的web资源.常用于编 ...

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

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

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

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

  8. Javaweb学习笔记——(二十八)——————Servlet3.0、动态代理、类加载器

    web最后一天:完了. Servlet3.0          一.要求         1.MyEclipse10.0或以上版本         2.发布到Tomcat7.0或以上版本 二.步骤   ...

  9. Servlet3.0 新特性

    Servlet3.0 的注解 Servlet 允许开发人员采用注解的方式来配置 Servlet.Filter.Listener. Servlet3.0 规范在 javax.servlet.annota ...

随机推荐

  1. linux 查看硬盘使用情况

    在windows系统中,我们可以很容易的查看磁盘的使用情况,在linux系统中,我们可以使用命令来查看磁盘使用情况. 1.df命令 作用:用来查看硬盘的挂载点,以及对应的硬盘容量信息.包括硬盘的总大小 ...

  2. Arduino在串口监视器上输出字母表

    程序会在Arduino IDE的串口监视器上输出一个字母表. 不需要额外电路,但是板子必须通过串口线或USB线连接到电脑. 代码 程序在setup()函数中建立串口连接,然后逐行输出a~z的字母I表, ...

  3. 14-网页,网站,微信公众号基础入门(网页版MQTT,小试牛刀)

    https://www.cnblogs.com/yangfengwu/p/11192639.html 抱歉哈...最近由于做板子,,教程的进度落下了... 这些天总共做了还几块板子 首先对当前这个教程 ...

  4. 关于单片机的RAM

    一块RAM 分为了 堆 和 栈   名词而已,知道就可以了, 各种内存溢出问题: 全局数组访问越界 出现的问题:直接重启,或者死机 解决办法 :  额,写好自己的程序吧!!!!!!! 函数的局部变量过 ...

  5. poj2398 Toy Storage 计算几何,叉积,二分

    poj2398 Toy Storage 链接 poj 题目大意 这道题的大概意思是先输入6个数字:n,m,x1,y1,x2,y2.n代表卡片的数量,卡片竖直(或倾斜)放置在盒内,可把盒子分为n+1块区 ...

  6. 一篇JavaScript技术栈带你了解继承和原型链

    作者 | Jeskson 来源 | 达达前端小酒馆 1 在学习JavaScript中,我们知道它是一种灵活的语言,具有面向对象,函数式风格的编程模式,面向对象具有两点要记住,三大特性,六大原则. 那么 ...

  7. Map、Set、List是否有序

    首先我们应该清楚这个概念:这里的有序和无序不是指集合中的排序,而是是否按照元素添加的顺序来存储对象. list是按照元素的添加顺序来存储对象的,因此是有序的.他的实现类ArrayList.Linked ...

  8. npx 使用教程

    转自阮一峰http://www.ruanyifeng.com/blog/2019/02/npx.html npm 从5.2版开始,增加了 npx 命令.它有很多用处,本文介绍该命令的主要使用场景. N ...

  9. Spring实现多数据源配置

    一.前言 对于小型项目,服务器与数据库是可以在同一台机子上的,但随着业务的庞大与负责,数据库和服务器就会分离开来.同时随着数据量的增大,数据库也要分开部署到多台机子上. 二.Spring配置文件修改 ...

  10. 分布式系统之CAP原理

    参考链接:http://blog.csdn.net/wireless_com/article/details/79153643 CAP是什么? CAP理论,被戏称为[帽子理论].CAP理论由Eric ...