今天主要介绍一些Servlet的异步处理
1、异步处理
一个普通Servlet工作流程:接受请求,对数据进行处理,调用业务接口方法完成业务处理,将结果返回给客户端,显然最耗时的步骤是业务逻辑处理,在Servlet3.0后支撑异步处理,可以将业务逻辑处理部分交给一个异步线程处理,这样当前的请求所占的线程就会被释放,结果由异步线程处理完后返回给客户端就行了。
Servlet中异步处理是由AsyncContext接口来实现的。
AsyncContext asyncContext = request.startAsync(request,response);
AsyncContext asyncContext1 = request.startAsync();
可以通过这2种形式得到AsyncContext接口的实现类对象。当调用startAsync方法后,该Servlet会延迟响应,并释放容器分配的线程。
AsyncContext 接口的主要方法
可以通过注解或者web.xml方式来进行声明Servlet支持异步处理请求,下面通过注解的方法来演示Servlet异步处理业务逻辑
注意:如果支持异步处理的Servlet前面有Filter,则Filter也需要支持异步处理
比如:
@WebFilter(
asyncSupported = true,
description = "字符编码过滤器",
filterName = "encodingFilter",
urlPatterns = { "/*" },
initParams = {
@WebInitParam(name = "ENCODING", value = "UTF-8")
}
)
否则会报如下错误
package com.wen.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
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(
asyncSupported = true,
urlPatterns = { "/asyncdemo.do" },
name = "myAsyncServlet"
)
public class MyAsyncServlet extends HttpServlet {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.println("开始时间:" + sdf.format(new Date()) + " <br/> ");
out.flush();
//在子线程中执行业务调用,并由其负责输出响应,主线程退出
AsyncContext asyncContext = request.startAsync(request,response);
asyncContext.setTimeout(900000000);//设置最大的超时时间
new Thread(new Executor(asyncContext)).start();
out.println("结束时间:" + sdf.format(new Date())+ " <br/> ");
out.flush();
}
//内部类
public class Executor implements Runnable {
private AsyncContext ctx = null;
public Executor(AsyncContext ctx){
this.ctx = ctx;
}
@Override
public void run(){
try {
//等待5秒钟,以模拟业务方法的执行
Thread.sleep(5000);
PrintWriter out = ctx.getResponse().getWriter();
out.println("业务处理完毕的时间:" + sdf.format(new Date()) + " <br/> ");
out.flush();
ctx.complete();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
在浏览器输入:http://localhost:8080/asyncdemo.do
上述demo运行的结果为