异步处理功能可以节约容器线程。此功能的作用是释放正在等待完成的线程,是该线程能够被另一请求所使用。

要编写支持异步处理的 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和异步过虑器的更多相关文章

  1. Filter 快速开始 异步Servlet 异步请求 AsyncContext 异步线程 异步派发 过滤器拦截

    [web.xml] <filter> <filter-name>normalFilter</filter-name> <filter-class>net ...

  2. java—过虑器基础(47)

    在web项目中就只有三大组件: Filter过虑器 监听器. Servlet 在web中过虑器就是一个类javax.servlet.Filter. 过虑器是用于在执行时,过虑用户的请求(request ...

  3. Servlet 3特性:异步Servlet

    解异步Servlet之前,让我们试着理解为什么需要它.假设我们有一个Servlet需要很多的时间来处理,类似下面的内容: LongRunningServlet.java package com.jou ...

  4. 使用tomcat7创建异步servlet

    该篇文章翻译自:http://developerlife.com/tutorials/?p=1437 一.简介 Servlet API 3.0 之前,需要使用类似Comet的方式来实现创建异步的Ser ...

  5. Java基于Servlet过虑器

  6. wemall app商城源码中基于JAVA的Android异步加载图片管理器代码

    wemall doraemon是Android客户端程序,服务端采用wemall微信商城,不对原商城做任何修改,只需要在原商城目录下上传接口文件即可完成服务端的配置,客户端可随意定制修改.本文分享其中 ...

  7. 关于servlet3.0中的异步servlet

    刚看了一下维基百科上的介绍,servlet3.0是2009年随着JavaEE6.0发布的: 到现在已经有六七年的时间了,在我第一次接触java的时候(2011年),servlet3.0就已经出现很久了 ...

  8. WebFlux01 webflux概念、异步servlet、WebFlux意义

    1 概念 待更新...... 2 异步servlet 2.1 同步servlet servlet容器(如tomcat)里面,每处理一个请求会占用一个线程,同步servlet里面,业务代码处理多久,se ...

  9. 异步Servlet的理解与实践

    AsyncContext理解 Servlet 3.0(JSR315)定义了Servlet/Filter的异步特性规范. 怎么理解"异步Servlet/Filter"及其使用情景? ...

随机推荐

  1. OpenCV SVM

    #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <ope ...

  2. Spring Boot application.yml bootstrap.yml

    yml与properties 其实yml和properties文件是一样的原理,且一个项目上要么yml或者properties,二选一的存在. 推荐使用yml,更简洁. bootstrap与appli ...

  3. xlrd使用

    import xlrd //导入模块filename='路径/文件名' //文件路径.名称python读取excel中单元格的内容返回的有5种类型,即ctype:0. empty(空的),1 stri ...

  4. React设置宽度的坑

    [React设置宽度的坑] 我们知道通过ref可以获取DOM元素,通过style属性可以给此DOM元素添加样式. 但下面两行的赋值是无效的: this.HomeRootDiv.style.width= ...

  5. 数据库表字段,DEFAULT NULL与NOT NULL DEFAULT

    为什么要把字段设置成not null 呢? 1.空值是不占用空间的 2.mysql中的NULL其实是占用空间的,下面是来自于MYSQL官方的解释 “NULL columns require addit ...

  6. 八 xml模块

    xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单,不过,古时候,在json还没诞生的黑暗年代,大家只能选择用xml呀,至今很多传统公司如金融行业的很多系统的 ...

  7. JavaScript 中this的实现原理

    学懂 JavaScript 言语,一个标志就是了解下面两种写法,或许有不一样的成果. <blockquote "=""> var obj = { foo: f ...

  8. css3 vw、vh属性详解,以及与%、rem的区别介绍

    最近的项目需求,内嵌电视端显示页面,所以使用到了css3的属性:vw \ vh,遇到一些问题,记录下来 vw.vh是什么? 字面上可以简单理解为,vw (view width),vh(view hei ...

  9. nohup top -p 22452 -b >>jiu.log &

    解释一下: 1. nohup \$order & 后台执行 2. nohup \$order >>$file & 后台执行,并输入指定文件 3. top -p $num 使 ...

  10. 写了一个兼容IE9的图片放大器(基于vue)

    photoloupe 图片放大器 第一次写vue插件,本人比较喜欢用简单易懂的写法,不喜勿喷. 本插件支持IE9及以上版本,已经过验证. 本插件可根据需要设置放大倍数,最小支持1倍,支持小数 下载地址 ...