异步Servlet和异步过虑器
异步处理功能可以节约容器线程。此功能的作用是释放正在等待完成的线程,是该线程能够被另一请求所使用。
要编写支持异步处理的 Servlet 或者过虑器,需要设置 asyncSupported 属性为 true。
@WebServlet(asyncSupported=true ... )
@WebFilter(asyncSupported=true ... )
当然也可以在部署描述符(web.xml)里面指定这个描述符。
<servlet>
<servlet-name>AsyncServlet</servlet-name>
<servlet-class>servlet.MyAsyncServlet</servlet-class>
<async-supported>true</async-supported>
</servlet>
注意,这个异步支持仅适合有一个长时间运行的任务并且要把运行结果通知给用户。如果你只有一个长期运行的任务,但用户并不需要知道处理结果,则可以提交一个 Runnable 该 Executor (执行器)并立即返回,
编写异步Servlet
(1)调用 ServletRequest 中的 startAsync 方法,该方法返回一个 AsyncContext 实例对象。
(2)调用 AsyncContext 的 setTimeout(),传递容器等待任务完成的超时时间的毫秒数。若不设置容器采用默认的超时时间,如果任务未能在指定的超时时间内完成,将会抛出一个超时异常。
(3)调用 asyncContext.start(),传递一个 Runnable 来执行一个长时间运行的任务。
(4)调用 Runnable 的 asyncContext.complete() 或 asyncContext.dispatch()方法来完成任务。
异步监听器
为支持 Servlet 和 过虑器配合执行异步操作,Servlet 3.0 增加了 asyncListener 接口用于接受异步处理过程中发生事件的通知。该接口提供了四个方法
void onStartAsync(AsyncEvent event) throws java.io.IOException // 异步操作启动完毕后调用该方法
void onComplete(AsyncEvent event) throws java.io.IOException // 异步操作完成后调用该方法
void onError(AsyncEvent event) throws java.io.IOException // 异步操作失败后调用该方法
void onTimeout(AsyncEvent event) throws java.io.IOException // 异步操作超时后调用该方法
异步事件类 AsyncEvent 提供了四个方法
public class AsyncEvent extends java.lang.Object //
public AsyncContext getAsyncContext() //
public ServletRequest getSuppliedRequest() //
public ServletResponse getSuppliedResponse() //
public java.lang.Throwable getThrowable() //
一个简单的异步调度的Servlet
package app11a; 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(name = "AsyncDispatchServlet",
urlPatterns = { "/asyncDispatch" },
asyncSupported = true )
public class AsyncDispatchServlet extends HttpServlet {
private static final long serialVersionUID = 1L; public AsyncDispatchServlet() {
super();
} protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
final AsyncContext asyncContext = request.startAsync(); // 调用 ServletRequest 中的 startAsync 方法
request.setAttribute("mainThread", Thread.currentThread().getName());
asyncContext.setTimeout(5000); // 调用 AsyncContext 的 setTimeout(),传递容器等待任务完成的超时时间的毫秒数
asyncContext.start(new Runnable() { // 调用 asyncContext.start(),传递一个 Runnable 来执行一个长时间运行的任务。
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
request.setAttribute("workerThread", Thread.currentThread().getName());
asyncContext.dispatch("/threadNames.jsp"); // 调用 Runnable 的 asyncContext.complete() 或 asyncContext.dispatch()方法来完成任务
}
});
} protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
<!-- threadNames.jsp -->
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Asynchronous servlet</title>
</head>
<body>
Main thread: ${mainThread }
<br />
Worker thread: ${workerThread }
</body>
</html>

发送最新进度更新的异步servlet
package app11a; import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; public class AsyncCompleteServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
final PrintWriter writer = response.getWriter();
writer.println("<html>");
writer.println("<head>");
writer.println("<title>Async Servlet</title>");
writer.println("<body>");
writer.println("<div id='progress'></div>");
final AsyncContext asyncContext = request.startAsync(); // 获取asynccontext对象
asyncContext.setTimeout(60000); // 设置超时
asyncContext.start(new Runnable() { // 开启一个线程
@Override
public void run() {
System.out.println("new thread: " + Thread.currentThread());
for (int i=0; i < 10; i++) {
writer.println("<script>");
writer.println("document.getElementById('progress').innerHTML='" + (i * 10) + "% complete'");
writer.println("</script>");
writer.flush();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
writer.println("<script>");
writer.println("document.getElementById('progress').innerHTML = 'DONE'");
writer.println("</script>");
writer.println("</body>");
writer.println("</html>");
asyncContext.complete(); //
}
});
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<display-name>app11a</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list> <servlet>
<servlet-name>AsyncComplete</servlet-name>
<servlet-class>app11a.AsyncCompleteServlet</servlet-class>
<async-supported>true</async-supported>
</servlet> <servlet-mapping>
<servlet-name>AsyncComplete</servlet-name>
<url-pattern>/asyncComplete</url-pattern>
</servlet-mapping> </web-app>
异步监听器的例子
package app11a; import java.io.IOException; import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener; public class MyAsyncListener implements AsyncListener { @Override
public void onComplete(AsyncEvent asyncEvent) throws IOException {
System.out.println("onComplete");
} @Override
public void onError(AsyncEvent asyncEvent) throws IOException {
System.out.println("onError");
} @Override
public void onStartAsync(AsyncEvent asyncEvent) throws IOException {
System.out.println("onStartAsync");
} @Override
public void onTimeout(AsyncEvent asyncEvent) throws IOException {
System.out.println("onTimeout");
}
}
package app11a; 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(name = "AsyncListenerServlet",
urlPatterns = { "/asyncListener" },
asyncSupported = true)
public class AsyncListenerServlet extends HttpServlet {
private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
final AsyncContext asyncContext = request.startAsync();
asyncContext.setTimeout(5000);
asyncContext.addListener(new MyAsyncListener());
asyncContext.start(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
String greeting = "hi from listener";
System.out.println("waiting ...");
request.setAttribute("greeting", greeting);
asyncContext.dispatch("/test.jsp");
}
});
} protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
<!-- test.jsp -->
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
This is the test.jsp
<br />
${greeting }
</body>
</html>

控制台输出

异步Servlet和异步过虑器的更多相关文章
- Filter 快速开始 异步Servlet 异步请求 AsyncContext 异步线程 异步派发 过滤器拦截
[web.xml] <filter> <filter-name>normalFilter</filter-name> <filter-class>net ...
- java—过虑器基础(47)
在web项目中就只有三大组件: Filter过虑器 监听器. Servlet 在web中过虑器就是一个类javax.servlet.Filter. 过虑器是用于在执行时,过虑用户的请求(request ...
- Servlet 3特性:异步Servlet
解异步Servlet之前,让我们试着理解为什么需要它.假设我们有一个Servlet需要很多的时间来处理,类似下面的内容: LongRunningServlet.java package com.jou ...
- 使用tomcat7创建异步servlet
该篇文章翻译自:http://developerlife.com/tutorials/?p=1437 一.简介 Servlet API 3.0 之前,需要使用类似Comet的方式来实现创建异步的Ser ...
- Java基于Servlet过虑器
- wemall app商城源码中基于JAVA的Android异步加载图片管理器代码
wemall doraemon是Android客户端程序,服务端采用wemall微信商城,不对原商城做任何修改,只需要在原商城目录下上传接口文件即可完成服务端的配置,客户端可随意定制修改.本文分享其中 ...
- 关于servlet3.0中的异步servlet
刚看了一下维基百科上的介绍,servlet3.0是2009年随着JavaEE6.0发布的: 到现在已经有六七年的时间了,在我第一次接触java的时候(2011年),servlet3.0就已经出现很久了 ...
- WebFlux01 webflux概念、异步servlet、WebFlux意义
1 概念 待更新...... 2 异步servlet 2.1 同步servlet servlet容器(如tomcat)里面,每处理一个请求会占用一个线程,同步servlet里面,业务代码处理多久,se ...
- 异步Servlet的理解与实践
AsyncContext理解 Servlet 3.0(JSR315)定义了Servlet/Filter的异步特性规范. 怎么理解"异步Servlet/Filter"及其使用情景? ...
随机推荐
- 表的转置 行转列: DECODE(Oracle) 和 CASE WHEN 的异同点
异同点 都可以对表行转列: DECODE功能上和简单Case函数比较类似,不能像Case搜索函数一样,进行更复杂的判断 在Case函数中,可以使用BETWEEN, LIKE, IS NULL, IN, ...
- 接收Android数据 递归显示表格数据
<html> <head> <title>展示</title> <script type="text/javascript" ...
- Linux系统服务之inetd
[Linux系统服务之inetd] inetd的角色是作为Telnet和FTP等与网络服务器相关的进程的“超级服务器”.这是一个简单的道理:并不是全部的服务器进程(包括那些接受新的Telnet和FTP ...
- 解题6(OutputNMin)
题目描述 输入n个整数,输出其中最小的k个. 详细描述: 接口说明 原型: bool GetMinK(unsignedint uiInputNum, int * pInputArray, unsign ...
- maven开发工具安装
Maven安装并测试步骤: 1.下载并解压meaven.zip: 2.配置环境变量“M2_HOME”指向meaven安装目录: 3.添加“%M2_HOME%\bin;”到path环境变量中: 4.测试 ...
- Python十分适合用来开发网页爬虫
Python十分适合用来开发网页爬虫,理由如下:1.抓取网页自身的接口比较与其他静态编程语言,如java,c#,c++,python抓取网页文档的接口更简练:比较其他动态脚本语言,如perl,shel ...
- no module named cv2
运行python脚本时报错: ImportError: No module named cv2 第一想法: 使用命令: pip install cv2 会报错找不到请求的版本 解决方法: 使用命令 p ...
- TOJ 3589 likaer的最长点距
传送门:http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=3589 时间限制(普通/Jav a) ...
- ECMAScript2017之async function
An async function can contain an await expression that pauses the execution of the async function an ...
- C++ 单例模式(懒汉、饿汉模式)
1.简单的单例模式实现 2.C++的构造函数不是线程安全的,所以上述代码在多线程的情况下是不安全的,原因是new Singelton时,这句话不是原子的,比如一个线程执行了new的同时,另一个线程对i ...