异步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"及其使用情景? ...
随机推荐
- perl5
1.perl包加入环境 export PERL5LIB=/export/personal1/wanglh/.software/perl/lib:$PERL5LIB
- Ambient Light
[Ambient Light] Ambient light is light that is present all around the scene and doesn’t come from an ...
- Linq to sql 之 事务
描述:linq 是自带事物的.如果建了两个linq to sql 类,各自访问不同的数据库,事物如何保证呢. 验证:采用常用的COM+事务来验证一下是否有效. ServiceConfig config ...
- 解题8(FindLongestNumberStr)
题目描述 样例输出 输出123058789,函数返回值9 输出54761,函数返回值5 接口说明 函数原型: unsignedint Continumax(char** pOutputstr, ch ...
- DRDS SQL兼容性
SQL 兼容性 更新时间:2017-06-07 13:26:11 DRDS 高度兼容 MySQL 协议和语法,但由于分布式数据库和单机数据库存在较大的架构差异,存在 SQL 使用限制.相关兼容 ...
- 使用Fiddler远程抓包(转载)
转载自 http://www.cnblogs.com/111testing/p/6436372.html Fiddler简介以及web抓包 一.Fiddler简介 简单来说,Fiddler是一个htt ...
- 【Scheme】序列的操作
1.序列的表示 序列 序列(表)是由一个个序对组合而成的,具体来说就是让每个序对的car部分对应这个链的条目,cdr部分则是下一个序对. 对于1->2->3->4这个序列我们可以表示 ...
- 通过DataTable获得表的主键
转载http://www.cnblogs.com/hobe/archive/2005/10/07/249940.html 通过DataTable获得表的主键 很多情形下我们需要知道表的主键是什么.在A ...
- SpringCloud报错:Caused by: org.yaml.snakeyaml.parser.ParserException: while parsing MappingNode
今天在配置eureka集群时,SpringCloud报错如下: Caused by: org.yaml.snakeyaml.parser.ParserException: while parsing ...
- 第十章 优先级队列 (xa1)左式堆:结构