十三:Servlet3.0的异步
servlet之前的操作同时同步的,就是按照这样的一个流程来走的:
1.请求根据一个路径路由到一个servlet中,
2.servlet获取一系列的参数
3.执行一系列的逻辑(花费时间所占的比重也更大)
4.返回结果
上面的问题出现在这一系列的操作都是同步的,所以这个请求必定是堵塞到所以任务都完成之后才返回的,
这样将会很浪费资源,因为线程堵塞在那里,仅仅是等待任务的完成。但是在servlet3.0之后,我们基本上可以
是这样做的
1.请求根据一个路径路由到一个servlet中,
2.将逻辑放入到异步队列中去
3.返回结果
4.异步队列处理任务,得出结果,返回给页面
而servet3.0对于异步的处理主要涉及的有两个特性,一个是新增的类AsyncContext,另外的一个就是asyncSupported属性
①如果我们想要让我们的servlet支持异步的话,那么asyncSupported这个属性是一定需要设置的,对于注解的类型来说,我们直接设置属性
@WebServlet(asyncSupported=true,urlPatterns={"/async"})
就可以了,对于老版本的配置问价来说,只需要在配置web.xml 的servlet那里增加一个
<async-supported>true</async-supported>
②而对于AsyncContext 需要记住的东西还是蛮多的,但是它主要的是保留了请求和相应的引用,在前面提到的返回结果之后的操作就是通过在异步环境下,对这两个引用进行操作。
要获取这个就需要使用request在3.0之后增加的方法,startAsync(..) ,这个方法就是返回一个AsyncContext实体对象,这里包含了request和response的引用,直接使用AsyncContext.start(Runnable)方法启动一个新的线程去进行处理逻辑
AsyncContext主要的方法:
getRequest() 获得请求即request,我们可以在异步的环境像在service中使用一样
getReponse() 和上面差不多一个意思
hasOriginalRequestAndResponse()这个方法表示的是我们使用的AsyncContext是使用原始的请求获取的,还是通过封装过的请求和相应创建的
简单的讲就是 原始的类型表示的是调用startAsync()。但是封装的就是startAsync(ServletRequest, ServletResponse)或者其他类型啦,
dispatch()方法,这个方法有有好几个重载,表示的是转发,和req.getRequestDispatcher()有点类似,但是比较丰富
如果使用的是startAsync(ServletRequest, ServletResponse)初始化AsyncContext,且传入的请求是HttpServletRequest的一个实例,则使用HttpServletRequest.getRequestURI()返回的URI进行分派。否则分派的是容器最后分派的请求URI。
下面的代码是网上的:dispatch(String path) 这个方法就是转发到指定的url上去
// 请求到 /url/A
AsyncContext ac = request.startAsync();
...
ac.dispatch(); // 异步分派到 /url/A // 请求到 /url/A
// 转发到 /url/B
request.getRequestDispatcher(“/url/B”).forward(request, response);
// 从FORWARD的目标内启动异步操作
AsyncContext ac = request.startAsync();
ac.dispatch(); // 异步分派到 /url/A // 请求到 /url/A
// 转发到 /url/B
request.getRequestDispatcher(“/url/B”).forward(request, response);
// 从FORWARD的目标内启动异步操作
AsyncContext ac = request.startAsync(request, response);
ac.dispatch(); //异步分派到 /url/B
complete():在我们使用了request.startAsync(..)获得AsyncContext之后,在完成异步操作以后,需要调用这个方法结束异步的操作。如果请求分派到一个不支持异步操作的Servlet,或者由AsyncContext.dispatch调用的目标servlet之后没有调用complete,则complete方法会由容器调用。
setTimeOut(..) 设置超时的时间 表示的是异步处理的最大时间,如果是一个负数的话,那么表示永远不会超时
start(Runnable run) Runnable表示的就是异步处理的任务。我们在做的时候 会AsyncContext 带进去 因为所以的操作 都需要依靠他呢
addListener(AsyncListener listener);增加监听器 就是监听AsyncContext各种状态发现变化的,主要有
前面三个都比较好理解,最后异步监听器将以它们添加到请求时的顺序得到通知。
下面是AsyncContext的一般使用方式
1. 模拟注册发信息到邮件的简单的异步处理 Servlet 示例代码:
package com.servlet; import java.io.IOException; import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; @WebServlet(value="/asyn-servlet",asyncSupported=true)
public class ServletAsyn extends HttpServlet {
private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("Servlet is start"); //1.获得异步上下文对象
AsyncContext ac = request.startAsync();
//2.启动一个耗时的子线程
ThreadTask tt = new ThreadTask(ac);
//3.可设置异步超时对象,需在启动异步上下文对象前设置
/*
* 设置超时后,在超时时间内子线程没有结束,主线程则会停止等待,继续往下执行
*/
ac.setTimeout(3000);
//4.开启异步上下文对象
ac.start(tt); //主线程结束向客户端发送消息
System.out.println("Servlet is end");
response.setContentType("text/html;charset=utf-8");
response.getWriter().append("信息已发送到邮箱");
} protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
} }
异步线程的执行类:
package com.servlet; import java.util.Date; import javax.servlet.AsyncContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession; public class ThreadTask implements Runnable{
private AsyncContext ac; //定义一个异步上下文 public ThreadTask(AsyncContext ac) {
super();
this.ac = ac;
} @Override
public void run() {
/*
* 服务端异步典型应用是注册时向邮箱发送验证码
*/
try {
//进行异步的一些处理
HttpServletRequest requst = (HttpServletRequest) ac.getRequest();
HttpSession session = requst.getSession();
System.out.println("asyn-task start" + new Date());
for(int i=5;i>0; i--) {
System.out.println(i);
Thread.sleep(1000);
}
//将结果放到session等方式
session.setAttribute("message", "This is the result of asyn");
System.out.println("asyn-task end" + new Date()); //通知主线程已经处理完成
/*
* 除了使用 ac.complete() 方法通知主线程已经处理外
* 还可以使用 ac.dispatch() 方法重定向到一个页面
*/
ac.dispatch("/show.jsp");
} catch (Exception e) {
e.printStackTrace();
}
} }
十三:Servlet3.0的异步的更多相关文章
- Servlet3.0的异步
servlet之前的操作同时同步的,就是按照这样的一个流程来走的: 1.请求根据一个路径路由到一个servlet中, 2.servlet获取一系列的参数 3.执行一系列的逻辑(花费时间所占的比重也更大 ...
- Servlet3.0对异步处理的支持
Servlet工作流程 Servlet 3.0 之前,一个普通 Servlet 的主要工作流程大致如下: Servlet 接收到请求之后,可能需要对请求携带的数据进行一些预处理: 调用业务接口的某些方 ...
- Filter学习总结,顺便提及点servlet3.0异步filter和异步监听
Filter介绍: Filter在项目中经常可以用到,通常配置在web.xml中.是服务器端的一个组件,对于用户的请求和响应数据进行过滤操作,控制是否让用户访问到对应的web资源.常用于编 ...
- 深入理解Servlet3.0异步请求
异步请求的基础概念 异步请求最直接的用法就是处理耗时业务,Http协议是单向的,只能客户端拉不能服务器主推. 异步请求的核心原理主要分为两大类:1.轮询.2长连接 轮询:就是定时获取返回结果. 长连接 ...
- Servlet3.0的新特性
注意:Servlet3.0的项目一定要使用Tomcat7.0才能看到效果!! 1.新增标注支持 在Servlet3.0的部署描述文件web.xml的顶层标签<web-app>中有一 ...
- Servlet3.0新特性使用详解
可插拔的Web框架 几乎所有基于Java的web框架都建立在servlet之上.现今大多数web框架要么通过servlet.要么通过Web.xml插入.利用标注(Annotation)来定义servl ...
- Servlet3.0新特性(从注解配置到websocket编程)
Servlet3.0的出现是servlet史上最大的变革,其中的许多新特性大大的简化了web应用的开发,为广大劳苦的程序员减轻了压力,提高了web开发的效率.主要新特性有以下几个: 引入注解配置 支持 ...
- Servlet 3.0 对异步处理的支持
Servlet 3.0 实现了对异步处理的支持 通过利用注解@WebServlet(urlPatterns="/AServlet" AysnsSupported=true) 让后n ...
- Servlet3.0 新特性
Servlet3.0 的注解 Servlet 允许开发人员采用注解的方式来配置 Servlet.Filter.Listener. Servlet3.0 规范在 javax.servlet.annota ...
随机推荐
- EXCEL:宏 考场考号打印
Sub addwork() Rem 当前宏是根据学生数量 .每考场人数计算工作表数Dim i As IntegerRem xx为每个考场的人数Rem yy为当前专业标记Rem mm为当前专业考生人数R ...
- Requests方法 -- 关联用例执行
1.参照此篇流程 :Requsts方法 -- Blog流程类进行关联 2.用例接口目录如下: 3.用例代码如下: import requestsimport unittestfrom Request. ...
- 9Java基础总结
1.psvm定义的意义 public:保证了方法的访问权限 static:保证在类未被实例化的时候就能调用(加载的时机) void:不需要返回值 main:约定俗成的名字 String[] args: ...
- Qt+MPlayer音乐播放器开发笔记(一):ubuntu上编译MPlayer以及Demo演示
前言 在ubuntu上实现MPlayer播放器播放音乐. Demo Mplayer MPlayer是一款开源多媒体播放器,以GNU通用公共许可证发布.此款软件 ...
- java String转List<Device>集合
// 从Redis中获得正常设备的数量 String success = redisService.get(RedisKey.CULTIVATION_RECORD_SUCCESS); //建立一个li ...
- Deepin V20.1 解决安装Edge浏览器后更新系统报错的方法
问题描述:有些人在deepin系统上安装完edge浏览器后采用sudo apt update命令更新系统,却报出了错误,更新失败.原因是更新deepin系统的时候,最好把其它的源禁用了,不然会有各样的 ...
- vulnhub-DC:6靶机渗透记录
准备工作 在vulnhub官网下载DC:6靶机DC: 6 ~ VulnHub 导入到vmware,设置成NAT模式 打开kali准备进行渗透(ip:192.168.200.6) 信息收集 利用nmap ...
- 安装Linux的步骤 包含linux下安装jdk,及mysql
https://mirrors.tuna.tsinghua.edu.cn/centos/7.9.2009/isos/x86_64/ 镜像下载网址,4G 左右. 安装VMware 15版本 一路下一步, ...
- Jarvis OJ部分逆向
Jarvis OJ部分逆向题解 很久没有写博客了,前天上Jarvis OJ刷了几道逆向,保持了一下感觉.都是简单题目,写个writeup记录一下. easycrackme int __cdecl ma ...
- 如何实现让div垂直居中,左右10px,高度始终为宽度一半
方法一:利用height:0; padding-bottom: 50%; <!DOCTYPE html><html lang="en"> <head& ...