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

要编写支持异步处理的 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. 基于docker的wekan部署

    镜像地址: https://hub.docker.com/r/wekanteam/wekan/ wiki: https://github.com/wekan/wekan/wiki#Developmen ...

  2. QQ传文件测试要点

    总-分-总 UI:   进度:进度条.百分比.速度.已传文件大小 显示传送文件图标.悬浮有文字 功能入口:图标.菜单项 各种提示:开始传送.各种异常信息的提示.传送结束 给好友传文件.给群传文件 功能 ...

  3. 微信文档采用第三方方式打开选择qq

    本篇文章主要记录解决: 微信打开文档后,----选择第三方应用打开---选择自己的项目,跳转到--列表选择界面--选择好友---然后返回到最近聊天界面,其中列表选择界面onDestroy的问题. 反编 ...

  4. ServiceWork的五种状态

    [ServiceWork的五种状态] installing.installed.activating.activated.redundant 参考:https://developer.mozilla. ...

  5. Beef的使用

    应用普遍转移到B/S架构,浏览器成为统一客户端程序 通过注入JS脚本,利用浏览器攻击其他网站 ruby编写 攻击手段 利用网站XSS漏洞实现攻击 诱使客户端访问含有hook的伪造站点 结合中间人攻击注 ...

  6. 【Django】ModuleNotFoundError: No module named 'books_ordersschool'

    Unhandled exception in thread started by <function check_errors.<locals>.wrapper at 0x00000 ...

  7. leetcode 中等题(1)

    2. Add Two Numbers(中等) /** * Definition for singly-linked list. * struct ListNode { * int val; * Lis ...

  8. 获取标签as3.0

    import flash.utils.Timer; import flash.events.TimerEvent; var time:Timer=new Timer(25); time.addEven ...

  9. python 学习笔记---Locust 测试服务端性能

    由于人工智能的热度, python目前已经成为最受欢迎的编程语言,一度已经超越Java . 本文将介绍开源的python 测试工具: locust 使用步骤: 1. 安装python 3.0以上版本 ...

  10. stm32GPIO的8种工作模式

    推挽输出:可以输出高.低电平,连接数字器件:推挽结构一般是指两个三极管分别受两个互补信号的控制,总是在一个三极管导通的时候另一个截止.高低电平由IC的电源决定. 推挽电路是两个参数相同的三极管或MOS ...