package com.yc.servlet;
import java.io.IOException;
import java.util.concurrent.ThreadPoolExecutor;
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;
/**
* 源辰信息
* 异步访问方式
* 在Servlet3.0中,提供了AsyncContext,对异步执行的上下文提供支持。在ServletRequest上提供了 startAsync( )方法,
* 用于启动异步工作线程。而且AsynchContext还提供了Timeout等设置。
* 你可以透过AsyncContext的getRequest() 、 getResponse()方法取得Request、Response对象,
* 此时对客户端的响应将暂缓至调用AsyncContext的complete()方法或dispatch()为止,前者表示回应完成,后者表示将响应调派给指定的URL 。
* 若要能调用ServletRequest的startAsync()使用AsyncContext,则此Servlet 必须能支援非同步处理,如果使用@WebServlet来标注,
* 则可以设定其asyncSupported为true 。
* 注意:使用异步处理方式,web容器的请求处理线程释放了,可以服务其他的请求处理。
* 但是该Request的处理并没有结束,在使用AsyncContext的complete或者dispatch完成后,这个request的处理才结束。
* web.xml的配置
* <servlet>
* <servlet-name>AsyncServlet</servlet-name>
* <servlet-class>com.yc.servlet.AsyncServlet</servlet-class>
* <async-supported>true</async-supported>
* </servlet>
* @author navy
* 2017年4月28日
*/
@WebServlet(urlPatterns="/asyncServlet",asyncSupported=true)
public class AsyncServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public AsyncServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/plain;charset=utf-8");
long startTime = System.currentTimeMillis();
System.out.println("当前线程名:"+ Thread.currentThread().getName()
+ " 线程ID:" + Thread.currentThread().getId());
//获取异步执行上下文对象
AsyncContext asyncCtx = request.startAsync();
//给异步执行上下文对象添加监听事件
asyncCtx.addListener(new AppAsyncListener());
asyncCtx.setTimeout(2000000); //异步请求超市时间
//获取请求线程池
ThreadPoolExecutor executor = (ThreadPoolExecutor) request.getServletContext().getAttribute("executor");
executor.execute(new AsyncRequestProcessor(asyncCtx, 10000)); //使用异步方式处理请求
//非线程池方式
//new Thread(new AsyncRequestProcessor(asyncCtx, 10000)).start();
long endTime = System.currentTimeMillis();
System.out.println("当前线程名:"+ Thread.currentThread().getName()
+ " 线程ID:" + Thread.currentThread().getId()
+ " 程序运行时长 " + (endTime - startTime) + " 毫秒 ");
}
}
package com.yc.servlet;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
/**
* 源辰信息
* 应用程序启动时创建一个线程池,用来给servlet的异步请求提供线程
* @author navy
* 2017年4月28日
*/
@WebListener
public class ApplicationListener implements ServletContextListener {
/**
* corePoolSize: 线程池维护线程的最少数量
* maximumPoolSize:线程池维护线程的最大数量
* keepAliveTime: 线程池维护线程所允许的空闲时间
* unit: 线程池维护线程所允许的空闲时间的单位
* workQueue: 线程池所使用的缓冲队列
* handler: 线程池对拒绝任务的处理策略
*/
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("初始化线程池开始...");
ThreadPoolExecutor executor = new ThreadPoolExecutor(50,100,50000L,
TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(5000));
sce.getServletContext().setAttribute("executor", executor);
System.out.println("初始化线程池完毕...");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
ThreadPoolExecutor executor = (ThreadPoolExecutor) sce.getServletContext().getAttribute("executor");
executor.shutdown();
}
}
package com.yc.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.AsyncContext;
import javax.servlet.ServletRequest;
/**
* 源辰信息
* 异步servlet处理长时间任务的线程
* @author navy
* 2017年4月28日
*/
public class AsyncRequestProcessor implements Runnable {
private AsyncContext asyncContext;
private int milliseconds;
public AsyncRequestProcessor() {
}
public AsyncRequestProcessor(AsyncContext asyncContext, int milliseconds) {
this.asyncContext = asyncContext;
this.milliseconds = milliseconds;
}
@Override
public void run() {
ServletRequest request=asyncContext.getRequest(); //从异步请求上下文对象中获取请求对象
String uname=request.getParameter("uname"); //获取请求中的参数
System.out.println(uname);
System.out.println(" 异步请求方式 :"+ asyncContext.getRequest().isAsyncSupported());
try {
Thread.sleep(milliseconds); //休眠10秒
} catch (InterruptedException e1) {
e1.printStackTrace();
}
try {
PrintWriter out = asyncContext.getResponse().getWriter();
out.write("请求处理10秒后...");
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
asyncContext.complete(); //完成异步请求
//asyncContext.dispatch(""); //完成异步请求,跳转到另外一个页面
}
}
package com.yc.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebListener;
/**
* 源辰信息
* 异步监听器,监听异步servlet的过程
* @author navy
* 2017年4月28日
*/
@WebListener
public class AppAsyncListener implements AsyncListener {
@Override
public void onComplete(AsyncEvent event) throws IOException {
System.out.println("异步servlet处理完成...");
}
@Override
public void onTimeout(AsyncEvent event) throws IOException {
ServletResponse response = event.getAsyncContext().getResponse();
PrintWriter out = response.getWriter();
out.write("异步servlet处理超时...");
out.flush();
out.close();
}
@Override
public void onError(AsyncEvent event) throws IOException {
ServletResponse response = event.getAsyncContext().getResponse();
PrintWriter out = response.getWriter();
out.write("异步servlet处理出错...");
out.flush();
out.close();
}
@Override
public void onStartAsync(AsyncEvent event) throws IOException {
System.out.println("异步servlet处理开始...");
}
}
package com.yc.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 源辰信息
* 同步访问方式
* @author navy
* 2017年4月28日
*/
@WebServlet(urlPatterns="/syncServlet")
public class SyncServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public SyncServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/plain;charset=utf-8");
//获取当前系统时间
long startTime = System.currentTimeMillis();
System.out.println("当前线程名:"+ Thread.currentThread().getName()
+ " 线程ID:" + Thread.currentThread().getId());
String uname=request.getParameter("uname");
System.out.println(uname);
try {
Thread.sleep(10000);//休眠10秒
} catch (InterruptedException e) {
e.printStackTrace();
}
PrintWriter out = response.getWriter();
long endTime = System.currentTimeMillis();
out.write("请求处理10秒后...");
System.out.println("当前线程名:"+ Thread.currentThread().getName()
+ " 线程ID:" + Thread.currentThread().getId()
+ " 程序运行时长 " + (endTime - startTime) + " 毫秒 ");
out.flush();
out.close();
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>servlet3.0</title>
</head>
<body>
<h1>同步请求</h1>
<form action="syncServlet" method="post">
<label>用户名:</label><input type="text" name="uname" value="源辰"/>
<input type="submit" value="提交" />
</form>
<h1>异步请求</h1>
<form action="asyncServlet" method="post">
<label>用户名:</label><input type="text" name="uname" value="源辰"/>
<input type="submit" value="提交" />
</form>
</body>
</html>
import java.io.IOException;
import java.util.concurrent.ThreadPoolExecutor;
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;
/**
* 源辰信息
* 异步访问方式
* 在Servlet3.0中,提供了AsyncContext,对异步执行的上下文提供支持。在ServletRequest上提供了 startAsync( )方法,
* 用于启动异步工作线程。而且AsynchContext还提供了Timeout等设置。
* 你可以透过AsyncContext的getRequest() 、 getResponse()方法取得Request、Response对象,
* 此时对客户端的响应将暂缓至调用AsyncContext的complete()方法或dispatch()为止,前者表示回应完成,后者表示将响应调派给指定的URL 。
* 若要能调用ServletRequest的startAsync()使用AsyncContext,则此Servlet 必须能支援非同步处理,如果使用@WebServlet来标注,
* 则可以设定其asyncSupported为true 。
* 注意:使用异步处理方式,web容器的请求处理线程释放了,可以服务其他的请求处理。
* 但是该Request的处理并没有结束,在使用AsyncContext的complete或者dispatch完成后,这个request的处理才结束。
* web.xml的配置
* <servlet>
* <servlet-name>AsyncServlet</servlet-name>
* <servlet-class>com.yc.servlet.AsyncServlet</servlet-class>
* <async-supported>true</async-supported>
* </servlet>
* @author navy
* 2017年4月28日
*/
@WebServlet(urlPatterns="/asyncServlet",asyncSupported=true)
public class AsyncServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public AsyncServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/plain;charset=utf-8");
long startTime = System.currentTimeMillis();
System.out.println("当前线程名:"+ Thread.currentThread().getName()
+ " 线程ID:" + Thread.currentThread().getId());
//获取异步执行上下文对象
AsyncContext asyncCtx = request.startAsync();
//给异步执行上下文对象添加监听事件
asyncCtx.addListener(new AppAsyncListener());
asyncCtx.setTimeout(2000000); //异步请求超市时间
//获取请求线程池
ThreadPoolExecutor executor = (ThreadPoolExecutor) request.getServletContext().getAttribute("executor");
executor.execute(new AsyncRequestProcessor(asyncCtx, 10000)); //使用异步方式处理请求
//非线程池方式
//new Thread(new AsyncRequestProcessor(asyncCtx, 10000)).start();
long endTime = System.currentTimeMillis();
System.out.println("当前线程名:"+ Thread.currentThread().getName()
+ " 线程ID:" + Thread.currentThread().getId()
+ " 程序运行时长 " + (endTime - startTime) + " 毫秒 ");
}
}
package com.yc.servlet;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
/**
* 源辰信息
* 应用程序启动时创建一个线程池,用来给servlet的异步请求提供线程
* @author navy
* 2017年4月28日
*/
@WebListener
public class ApplicationListener implements ServletContextListener {
/**
* corePoolSize: 线程池维护线程的最少数量
* maximumPoolSize:线程池维护线程的最大数量
* keepAliveTime: 线程池维护线程所允许的空闲时间
* unit: 线程池维护线程所允许的空闲时间的单位
* workQueue: 线程池所使用的缓冲队列
* handler: 线程池对拒绝任务的处理策略
*/
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("初始化线程池开始...");
ThreadPoolExecutor executor = new ThreadPoolExecutor(50,100,50000L,
TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(5000));
sce.getServletContext().setAttribute("executor", executor);
System.out.println("初始化线程池完毕...");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
ThreadPoolExecutor executor = (ThreadPoolExecutor) sce.getServletContext().getAttribute("executor");
executor.shutdown();
}
}
package com.yc.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.AsyncContext;
import javax.servlet.ServletRequest;
/**
* 源辰信息
* 异步servlet处理长时间任务的线程
* @author navy
* 2017年4月28日
*/
public class AsyncRequestProcessor implements Runnable {
private AsyncContext asyncContext;
private int milliseconds;
public AsyncRequestProcessor() {
}
public AsyncRequestProcessor(AsyncContext asyncContext, int milliseconds) {
this.asyncContext = asyncContext;
this.milliseconds = milliseconds;
}
@Override
public void run() {
ServletRequest request=asyncContext.getRequest(); //从异步请求上下文对象中获取请求对象
String uname=request.getParameter("uname"); //获取请求中的参数
System.out.println(uname);
System.out.println(" 异步请求方式 :"+ asyncContext.getRequest().isAsyncSupported());
try {
Thread.sleep(milliseconds); //休眠10秒
} catch (InterruptedException e1) {
e1.printStackTrace();
}
try {
PrintWriter out = asyncContext.getResponse().getWriter();
out.write("请求处理10秒后...");
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
asyncContext.complete(); //完成异步请求
//asyncContext.dispatch(""); //完成异步请求,跳转到另外一个页面
}
}
package com.yc.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebListener;
/**
* 源辰信息
* 异步监听器,监听异步servlet的过程
* @author navy
* 2017年4月28日
*/
@WebListener
public class AppAsyncListener implements AsyncListener {
@Override
public void onComplete(AsyncEvent event) throws IOException {
System.out.println("异步servlet处理完成...");
}
@Override
public void onTimeout(AsyncEvent event) throws IOException {
ServletResponse response = event.getAsyncContext().getResponse();
PrintWriter out = response.getWriter();
out.write("异步servlet处理超时...");
out.flush();
out.close();
}
@Override
public void onError(AsyncEvent event) throws IOException {
ServletResponse response = event.getAsyncContext().getResponse();
PrintWriter out = response.getWriter();
out.write("异步servlet处理出错...");
out.flush();
out.close();
}
@Override
public void onStartAsync(AsyncEvent event) throws IOException {
System.out.println("异步servlet处理开始...");
}
}
package com.yc.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 源辰信息
* 同步访问方式
* @author navy
* 2017年4月28日
*/
@WebServlet(urlPatterns="/syncServlet")
public class SyncServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public SyncServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/plain;charset=utf-8");
//获取当前系统时间
long startTime = System.currentTimeMillis();
System.out.println("当前线程名:"+ Thread.currentThread().getName()
+ " 线程ID:" + Thread.currentThread().getId());
String uname=request.getParameter("uname");
System.out.println(uname);
try {
Thread.sleep(10000);//休眠10秒
} catch (InterruptedException e) {
e.printStackTrace();
}
PrintWriter out = response.getWriter();
long endTime = System.currentTimeMillis();
out.write("请求处理10秒后...");
System.out.println("当前线程名:"+ Thread.currentThread().getName()
+ " 线程ID:" + Thread.currentThread().getId()
+ " 程序运行时长 " + (endTime - startTime) + " 毫秒 ");
out.flush();
out.close();
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>servlet3.0</title>
</head>
<body>
<h1>同步请求</h1>
<form action="syncServlet" method="post">
<label>用户名:</label><input type="text" name="uname" value="源辰"/>
<input type="submit" value="提交" />
</form>
<h1>异步请求</h1>
<form action="asyncServlet" method="post">
<label>用户名:</label><input type="text" name="uname" value="源辰"/>
<input type="submit" value="提交" />
</form>
</body>
</html>