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

要编写支持异步处理的 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. OD调试17

    程序先出现一个nag 然后出现主窗口 然后出现第二个nag窗口        我们查个壳   没有壳 那就载入OD看看,继续用调用堆栈的方法 发现一直执行用的都是这一个call,最后执行到程序结束.之 ...

  2. Codeforces 424A (思维题)

    Squats Time Limit: 1000MS   Memory Limit: 262144KB   64bit IO Format: %I64d & %I64u Submit Statu ...

  3. 10socket编程

    这一节主要关注的还是粘包问题,我们利用recv实现一个recv_peek函数,它的目的是偷窥目的,它是利用recv的一个msg_peek参数与read的区别,read读取后 会擦除缓冲区的内容,而re ...

  4. Microsoft Office 2007 Professional Plus+ 正版密钥

    Microsoft Office 2007 Professional Plus+  正版密钥         说微软原版,自有Microsoft官方MSDN网站有关下载的校验值为证(附后).密钥安装后 ...

  5. [LeetCode 109] - 将已排序链表转换为二叉搜索树 (Convert Sorted List to Binary Search Tree)

    问题 给出一个元素以递增序列排序的单链表,将其转换为一棵高度平衡的二叉搜索树. 初始思路 二叉搜索树高度平衡,意味着左右子树的高度要平衡.根据二叉树左子树节点小于根节点,右子树节点大于根节点的性质:我 ...

  6. [置顶] 【cocos2d-x入门实战】微信飞机大战之十二:分数的本地存储

    转载请表明地址:http://blog.csdn.net/jackystudio/article/details/12036237 作为一个单机游戏,连分数存储的的功能都没有,让它怎么在单机游戏圈里混 ...

  7. mongoose的virtual属性

    设置vitual属性 personSchema.virtual('name.full').get(function () { return this.name.first + ' ' + this.n ...

  8. iOS开发常用第三库

    字典转模型 1.(MJExtension) https://github.com/CoderMJLee/MJExtension 2.(YYModel) https://github.com/ibire ...

  9. 【ARC076D/F】Exhausted?

    Description ​ 题目链接 Solution ​ 场上尝试使用优化建图网络流实现,结果T到怀疑人生. ​ 鉴于这是个匹配问题,考虑用贪心做一下. ​ 先退一步,想一下如果每一个人只有\([1 ...

  10. cf1090 I.Minimal Product(贪心)

    题意 题目链接 给出长度为\(n\)的序列\(a\),序列中的元素取值为\([-2e9, 2e9]\) 找到两个位置\((i, j) (i <j, a[i] < a[j])\),最小化\( ...