Servlet3.0对异步处理的支持

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线程依旧能够生成响应数据

原文地址:https://www.cnblogs.com/heliusKing/p/11620958.html

时间: 2024-10-31 04:11:18

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

Servlet 3.0 对异步处理的支持

Servlet 3.0 实现了对异步处理的支持 通过利用注解@WebServlet(urlPatterns="/AServlet" AysnsSupported=true) 让后new一个上下文对象 代码如下 AsyncContext ac= request.startAysnc(request,response) 传入一个Runnable  对象 ac.start(new Runnable(){ // 加入代码 });   上述表示Servlet3.0 对异步处理的支持

Servlet3.0的异步

servlet之前的操作同时同步的,就是按照这样的一个流程来走的: 1.请求根据一个路径路由到一个servlet中, 2.servlet获取一系列的参数 3.执行一系列的逻辑(花费时间所占的比重也更大) 4.返回结果 上面的问题出现在这一系列的操作都是同步的,所以这个请求必定是堵塞到所以任务都完成之后才返回的, 这样将会很浪费资源,因为线程堵塞在那里,仅仅是等待任务的完成.但是在servlet3.0之后,我们基本上可以 是这样做的 1.请求根据一个路径路由到一个servlet中, 2.将逻辑放入

[Servlet3.0]Servlet异步处理

所谓异步处理就是指数据发送方发送数据给数据接收方后,不必等待数据接收方作出响应,可以继续发送下一个数据的通信方式. Servlet 3.0版本提供了相关异步处理的功能,具体实现方式如下: 需要使用注解在对应Servlet配置asyncSupported=true,表示当前Servlet支持异步. 通过Request对象的startAsync(Request, Response)方法获取异步上下文对象. 通过异步上下文对象调用start(new Runnable(){})方法开始异步处理,Runn

Servlet3.0中的异步请求

package com.itheima.async; import java.io.IOException; import javax.servlet.AsyncContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; i

初次接触Servlet3.0

Servlet3.0 一.要求 MyEclipes10.0或以上版本! 发布到Tomcat7.0或以上版本!二.步骤 创建JavaEE6.0应用 -------------------------------------------三.概述 *注解代替web.xml配置文件 *异步处理 *对上传的支持 Servlet3.0在市场上没有应用! --------------------------------------------四.注解替代配置文件 1.删除web.xml 2.在servlet类

框架学习前基础加强 泛型,注解,反射(泛型&注解)应用案例,IOC,Servlet3.0,动态代理,类加载器

泛型 1. 泛型类 :具有一个或多个类型变量的类,称之为泛型类! class A<T> { } 2. 在创建泛型类实例时,需要为其类型变量赋值 A<String> a = new A<String>(); * 如果创建实例时,不给类型变量赋值,那么会有一个警告! 3. 泛型方法 :具有一个或多个类型变量的方法,称之为泛型方法! class A<T> { public T fun(T t1) {} } fun()方法不是泛型方法!它是泛型类中的一个方法! pu

Servlet3.0注解为什么不能使用?及配置多个Tomcat

在学校学习Servlet和过滤器的时候,通常是在web.xml文件中配置的,这样可以将配置信息集中在一起,方便修改,而且如果采用注解的形式,会在编译的过程中将注解一同编译进去,这样就无法方便的进行修改了,如果是远程操作的话,就造成了很大的麻烦. 一,使用注解应当注意的事项: 开发Servlet3.0的程序需要环境支持: IDE:MyEclipse 10+ JDK:JDK 1.6+ tomcat:tomcat 7+ 当你的环境正确的时候才能正常使用,尤其需要注意的是,MyEclipse自带的Tom

关于servlet3.0中的异步servlet

刚看了一下维基百科上的介绍,servlet3.0是2009年随着JavaEE6.0发布的: 到现在已经有六七年的时间了,在我第一次接触java的时候(2011年),servlet3.0就已经出现很久了,但是到现在,里边的一些东西还是没有能够好好地了解一下 最近在研究java的长连接,在了解jetty中的continuations机制的时候也重新了解了一下servlet3.0中的异步servlet机制,通过看几个博客,加上自己的一些测试,算是搞明白了一些,在这里记录一下: 在服务器的并发请求数量比

servlet3.0 新特性——异步处理

Servlet 3.0 之前,一个普通 Servlet 的主要工作流程大致如下: 首先,Servlet 接收到请求之后,可能需要对请求携带的数据进行一些预处理: 接着,调用业务接口的某些方法,以完成业务处理: 最后,根据处理的结果提交响应,Servlet 线程结束. 其中第二步的业务处理通常是最耗时的,这主要体现在数据库操作,以及其它的跨网络调用等,在此过程中,Servlet 线程一直处于阻塞状态,直到业务方法执行完毕.在处理业务的过程中,Servlet 资源一直被占用而得不到释放,对于并发较大