1、什么是servlet异步请求

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

(1)、Servlet 接收到请求之后,可能需要对请求携带的数据进行一些预处理;

(2)、调用业务接口的某些方法,以完成业务处理;

(3)、根据处理的结果提交响应,Servlet 线程结束。

其中第二步处理业务逻辑时候很可以碰到比较耗时的任务,此时servlet主线程会阻塞等待完成业务处理,对于并发比较大的请求可能会产生性能瓶颈,则servlet3.0之后再此处做了调整,引入了异步的概念。

(1)、Servlet 接收到请求之后,可能需要对请求携带的数据进行一些预处理;

(2)、调用业务接口的某些方法过程中request.startAsync()请求,获取一个AsyncContext

(3)、紧接着servlet线程退出(回收到线程池),但是响应response对象仍旧保持打开状态,新增线程会使用AsyncContext处理并响应结果。

(4)、AsyncContext处理完成触发某些监听通知结果

2、Servlet异步请求示例

2.1、示例准备

本示例采用web.xml配置的形式,模拟场景为:笔者所在的it公司每周的工作内容,首先研发总监分配给产品、研发、测试相关的任务,布置完任务就出差(模拟请求响应),余下的各个小组进行自己任务操作(模拟的耗时操作),最终出周报完成任务(异步任务处理完成的通知)

git地址:https://github.com/liushangzaibeijing/spsm.git  分支:dev_async

2.2、实现自定义的Servlet

/**
 * @ClassName AsyncServlet
 * @Desc 自定义异步Servlet处理器
 * @Author xieqx
 * @Date 2020/12/9 15:38
 **/
//通过注解的形式开始异步
@WebServlet(urlPatterns = "*.async",asyncSupported = true)
public class AsyncServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       doPost(req,resp);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //开启异步支持
        //异步管理上下文
        resp.setCharacterEncoding("GBK");
        PrintWriter writer = resp.getWriter();
        writer.println("周工作任务布置开始");
        AsyncContext asyncContext = req.startAsync();
        asyncContext.start(new WeekTask(asyncContext));
        //添加监听器 处理完成监听
        asyncContext.addListener(new AsyncListener() {
            @Override
            public void onComplete(AsyncEvent asyncEvent) throws IOException {
                System.out.println("工作在" new Date() "处理完成");
            }
            @Override
            public void onTimeout(AsyncEvent asyncEvent) throws IOException {
                System.out.println("工作在" new Date() "处理超时");
            }
            @Override
            public void onError(AsyncEvent asyncEvent) throws IOException {
                System.out.println("工作在" new Date() "处理出错");
            }
            @Override
            public void onStartAsync(AsyncEvent asyncEvent) throws IOException {
                System.out.println("工作在" new Date() "处理开始");
            }
        });
        writer.println("周工作任务布置完成");
        writer.flush();
    }
}

  开启异步支持(默认异步支持不开启)有两种方式:

使用注解

web.xml配置

	<servlet>
		<servlet-name>asyncServlet</servlet-name>
		<servlet-class>com.xiu.async.servlet.AsyncServlet</servlet-class>
		<!-- 开启servlet的异步请求操作 -->
		<async-supported>true</async-supported>
	</servlet>
	<servlet-mapping>
		<servlet-name>asyncServlet</servlet-name>
		<url-pattern>*.async</url-pattern>
	</servlet-mapping>

上述代码中通过request.startAsync()启动异步处理 返回一个异步上下文对象AsyncContext最终是使用该上下文对象来进行异步业务逻辑处理,其中有两个核心方法 

asyncContext.start(new WeekTask(asyncContext));  添加一个异步任务该任务是一个Runnable线程接口,这里就清晰了其实是servlet线程将处理任务交给另一个子线程,servlet直接返回从而达到提高系统吞吐量的作用。
对于异步请求可以我们需要获取其中的结果,所有这里提供了监听器模式添加事件监听AsyncListener

onComplete 异步请求处理完成触发 前提示需要调用 asyncContext.complete()方法(因为程序也不知道什么时候任务算是调用完毕了)
onTimeout 异步请求处理超时触发,一般来说采用异步请求的任务都是比较耗时的任务,所以需要修改servlet默认的超时时间(修改的长一点)
onError 异步处理错误的时候触发
onStartAsync 异步处理开始的时候触发即为request.startAsync(),因为添加监听器在startAsync()方法后,所以第一个启动是无法触发该监听的

这里异步处理只是简单的打印了相关日志,不过真实的业务场景中可以写复杂的业务处理逻辑。

2.3、异步任务

这里提供相关的异步操作是实现runnable的线程实现类,同时这里提供了相关Job,PmJob(产品任务),RDJob(研发任务),TestJob(测试任务),每个任务模拟了10秒的耗时任务。

/**
 * @ClassName WeekTask
 * @Desc 每周任务 
 * @Author xieqx
 * @Date 2020/12/10 9:36
 **/
public class WeekTask implements Runnable {
 
    private List<Job> jobs = null;
 
    private AsyncContext asyncContext = null;
    //这里初始化产品任务PmJob、研发任务RDJob  测试任务TestJob
    public WeekTask(AsyncContext asyncContext) {
       this.asyncContext = asyncContext;
       jobs = new ArrayList<>();
       PmJob pmJob = new PmJob();
       RDJob rdJob = new RDJob();
       TestJob testJob = new TestJob();
       jobs.add(pmJob);
       jobs.add(rdJob);
       jobs.add(testJob);
    }
 
    @Override
    public void run() {
        for(Job job:jobs){
            job.execute();
        }
        System.out.println("周任务工作完成");
        //job执行完成后通知
      asyncContext.complete();
    }
}

  PmJob

/**
 * @ClassName PmTask
 * @Desc 产品经理任务
 * @Author xieqx
 * @Date 2020/12/9 16:03
 **/
public class PmJob implements Job {
    @Override
    public void execute() {
        System.out.println("产品经理开评审会议");
        try {
            Thread.sleep(10);
            System.out.println("模拟需求评审会议...");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

RDJob

/**
 * @ClassName PmTask
 * @Desc 研发任务
 * @Author xieqx
 * @Date 2020/12/9 16:03
 **/
public class RDJob implements Job {
    @Override
    public void execute() {
        System.out.println("程序猿开始开发");
        try {
            Thread.sleep(10);
            System.out.println("程序猿哼哧哼哧干活中...");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

TestJob

/**
 * @ClassName TestJob
 * @Desc 测试任务
 * @Author xieqx
 * @Date 2020/12/9 16:03
 **/
public class TestJob implements Job {
    @Override
    public void execute()  {
        System.out.println("测试开始测试");
        try {
            Thread.sleep(10);
            System.out.println("测试用例测试...");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

2.4、测试场景

请求立马响应,但是异步任务在后面处理

到此这篇关于servlet异步请求的实现的文章就介绍到这了,更多相关servlet异步请求内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

servlet异步请求的实现的更多相关文章

  1. HTML5 WebSocket实现点对点聊天的示例代码

    这篇文章主要介绍了HTML5 WebSocket实现点对点聊天的示例代码的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. 浅谈ajax在jquery中的请求和servlet中的响应

    下面小编就为大家分享一篇浅谈ajax在jquery中的请求和servlet中的响应,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

  3. SpringBoot如何切换成其它的嵌入式Servlet容器(Jetty和Undertow)

    这篇文章主要介绍了SpringBoot如何切换成其它的嵌入式Servlet容器(Jetty和Undertow),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  4. JSP+Servlet实现文件上传到服务器功能

    这篇文章主要为大家详细介绍了JSP+Servlet实现文件上传到服务器功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AJAX实现简单的注册页面异步请求实例代码

    下面小编就为大家带来一篇AJAX实现简单的注册页面异步请求实例代码。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  6. 关于Ajax技术中servlet末尾的输出流

    这篇文章主要介绍了关于Ajax技术中servlet末尾的输出流的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下

  7. javascript请求servlet实现ajax示例(分享)

    下面小编就为大家带来一篇javascript请求servlet实现ajax示例(分享)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  8. 使用$.get()根据选项的不同从数据库异步请求数据

    本例实现的是这样的一个效果:当从select下拉框选择编程语言时时,根据选项的不同,异步请求不同的函数API描述,需要的朋友可以参考下

  9. ajax异步请求详解

    做前端开发的朋友对于ajax异步更新一定印象深刻,本文主要介绍了关于ajax异步请求的那点事,具有一定的参考价值,下面跟着小编一起来看下吧

  10. Ajax异步请求技术实例讲解

    ajax是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。下面通过本文给大家分享Ajax异步请求技术实例讲解,非常不错,具有参考借鉴价值,需要的的朋友参考下吧

随机推荐

  1. 基于EJB技术的商务预订系统的开发

    用EJB结构开发的应用程序是可伸缩的、事务型的、多用户安全的。总的来说,EJB是一个组件事务监控的标准服务器端的组件模型。基于EJB技术的系统结构模型EJB结构是一个服务端组件结构,是一个层次性结构,其结构模型如图1所示。图2:商务预订系统的构架EntityBean是为了现实世界的对象建造的模型,这些对象通常是数据库的一些持久记录。

  2. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  3. Mybatis分页插件PageHelper手写实现示例

    这篇文章主要为大家介绍了Mybatis分页插件PageHelper手写实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  4. (jsp/html)网页上嵌入播放器(常用播放器代码整理)

    网页上嵌入播放器,只要在HTML上添加以上代码就OK了,下面整理了一些常用的播放器代码,总有一款适合你,感兴趣的朋友可以参考下哈,希望对你有所帮助

  5. Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下

  6. Java异常Exception详细讲解

    异常就是不正常,比如当我们身体出现了异常我们会根据身体情况选择喝开水、吃药、看病、等 异常处理方法。 java异常处理机制是我们java语言使用异常处理机制为程序提供了错误处理的能力,程序出现的错误,程序可以安全的退出,以保证程序正常的运行等

  7. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  8. 面试突击之跨域问题的解决方案详解

    跨域问题本质是浏览器的一种保护机制,它的初衷是为了保证用户的安全,防止恶意网站窃取数据。那怎么解决这个问题呢?接下来我们一起来看

  9. Mybatis-Plus接口BaseMapper与Services使用详解

    这篇文章主要为大家介绍了Mybatis-Plus接口BaseMapper与Services使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  10. mybatis-plus雪花算法增强idworker的实现

    今天聊聊在mybatis-plus中引入分布式ID生成框架idworker,进一步增强实现生成分布式唯一ID,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部