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. 谷歌浏览器打开不了Axure生成的html文件

    1.首先要进行翻墙.https://www.google.com 搜索Axure chrome软件 2. 3.安装axure插件即可. 4.管理扩展程序,允许访问文件网址.

  2. spi调试步骤,mcp2515调试整理

    1.先查看也硬件电路,一般都是单片机作为master,其他芯片作为slave.单片机的MOSI对应从机的SI,单片机的MISO对应从机的SO,如果两个引脚接反了,那是怎么调试都没有效果的. 2.单片机 ...

  3. IMP本质上是一个通用的函数指针

    IMP:通用的函数指针 /// A pointer to the function of a method implementation. #if !OBJC_OLD_DISPATCH_PROTOTY ...

  4. 牛客OI周赛10-普及组-A眼花缭乱的街市-(加速+二分)

    https://ac.nowcoder.com/acm/contest/901/A 很简单的一道题,全场只有20+AC,卡时间.新学了cin加速语法和数组二分查找的函数调用. 知道有个读写挂,可以加速 ...

  5. 开源项目(9-0)综述--基于深度学习的目标跟踪sort与deep-sort

    基于深度学习的目标跟踪sort与deep-sort https://github.com/Ewenwan/MVision/tree/master/3D_Object_Detection/Object_ ...

  6. pipelinewise 基于singer 指南的的数据pipeline 工具

    pipelinewise 是基于开源singer 指南开发的数据pipeline工具,与singer tap 以及target 兼容 支持的特性 内置的elt 特性 轻量级 支持多种复制方法,cdc( ...

  7. Spring Could Feign 设计原理

    什么是Feign? Feign 的英文表意为"假装,伪装,变形", 是一个http请求调用的轻量级框架,可以以Java接口注解的方式调用Http请求,而不用像Java中通过封装HT ...

  8. DT包 -- R语言中自定义表格数据

    DT 包提供了 JavaScript 库 DataTables 的一个R接口,它使得R对象(矩阵或数据框)可以在HTML页面上显示为表格. 该包的DataTables函数生成的表格提供了数据的筛选.分 ...

  9. 【Beta】Phylab 测试报告

    PhyLab Beta 测试报告 测试中发现的bug Beta阶段新Bug Bug 可能原因 markdown生成的报告可能溢出显示框 表格过长,显示框未设置横向溢出 移动端实验区无法评论 移动端社区 ...

  10. centos如何添加ftp目录

    检查Centos服务器中是否安装了vsftpd rpm -qa |grep vsftpd 如果没有显示则没有安装 2.安装vsftpd yum -y install vsftpd 3.打开vsftpd ...