在spring 3.2 及以后版本中增加了对请求的异步处理,旨在提高请求的处理速度降低服务性能消耗。
在我们的请求中做了耗时处理,当并发请求的情况下,为了避免web server的连接池被长期占用而引起性能问题,调用后生成一个非web的服务线程来处理,增加web服务器的吞吐量。
为此 Servlet 3.0 新增了请求的异步处理,Spring 也在此基础上做了封装处理。
本文还是以代码例子的方式说明如何在 Spring Boot 中应用异步请求。
首先说一下几个要点:
1、@WebFilter 和 @WebServlet 注解中的 asyncSupported = true 属性
异步处理的servlet若存在过滤器,则过滤器的注解@WebFilter应设置asyncSupported=true,
否则会报错 A filter or servlet of the current chain does not support asynchronous operations.
2、@EnableAsync 注解
Spring Boot 默认添加了一些拦截 @WebServlet(urlPatterns = "/xs/cometservlet", asyncSupported = true) //异步处理的servlet若存在过滤器,则过滤器的注解@WebFilter应设置asyncSupported=true, //否则会报错A filter or servlet of the current chain does not support asynchronous operations. public class CometServlet extends HttpServlet { private static final long serialVersionUID = -8685285401859800066L; private final Queue asyncContexts = new linkedBlockingQueue<>(); private final Thread generator = new Thread("Async Event generator") { @Override public void run() { while (!generator.isInterrupted()) {// 线程有效 try { while (!asyncContexts.isEmpty()) {// 不为空 TimeUnit.SECONDS.sleep(10);// 秒,模拟耗时操作 AsyncContext asyncContext = asyncContexts.poll(); HttpServletResponse res = (HttpServletResponse) asyncContext.getResponse(); res.getWriter().write("{"result":"OK - "+System.currentTimeMillis()+""}"); res.setStatus(HttpServletResponse.SC_OK); res.setContentType("application/json"); asyncContext.complete();// 完成 } } catch (InterruptedException e) { Thread.currentThread().interrupt(); e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } }; @Override public void init() throws ServletException { super.init(); generator.start(); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println(">>>>>>>>>>CometServlet Request<<<<<<<<<<<"); doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { AsyncContext asyncContext = req.startAsync(); asyncContext.setTimeout(20 * 1000L); asyncContexts.offer(asyncContext); } @Override public void destroy() { super.destroy(); generator.interrupt(); } }
方法二:Controller 方式
@Controller
public class PageController {
@RequestMapping("/async/test")
@ResponseBody
public Callable callable() {
// 这么做的好处避免web server的连接池被长期占用而引起性能问题,
// 调用后生成一个非web的服务线程来处理,增加web服务器的吞吐量。
return new Callable() {
@Override
public String call() throws Exception {
Thread.sleep(3 * 1000L);
return "小单 - " + System.currentTimeMillis();
}
};
}
}
最后写一个comet.jsp页面测试:
<%@ page pageEncoding="UTF-8"%>长连接测试 长连接测试
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持考高分网。



