springboot原生异步请求API说明

转载 謝謝同学  2019-07-28 17:00  阅读 26 次 评论 0 条

在编写实际代码之前,我们来了解下一些关于异步请求的api的调用说明。

获取AsyncContext:根据HttpServletRequest对象获取

  1. AsyncContext asyncContext = request.startAsync();  

设置监听器:可设置其开始、完成、异常、超时等事件的回调处理

  1. public interface AsyncListener extends EventListener {  
  2.     void onComplete(AsyncEvent event) throws IOException;  
  3.     void onTimeout(AsyncEvent event) throws IOException;  
  4.     void onError(AsyncEvent event) throws IOException;  
  5.     void onStartAsync(AsyncEvent event) throws IOException;  
  6. }  
说明:
  1. onStartAsync:异步线程开始时调用
  2. onError:异步线程出错时调用
  3. onTimeout:异步线程执行超时调用
  4. onComplete:异步执行完毕时调用

一般上,我们在超时或者异常时,会返回给前端相应的提示,比如说超时了,请再次请求等等,根据各业务进行自定义返回。同时,在异步调用完成时,一般需要执行一些清理工作或者其他相关操作。

需要注意的是只有在调用request.startAsync前将监听器添加到AsyncContext,监听器的onStartAsync方法才会起作用,而调用startAsyncAsyncContext还不存在,所以第一次调用startAsync是不会被监听器中的onStartAsync方法捕获的,只有在超时后又重新开始的情况下onStartAsync方法才会起作用。

设置超时:通过setTimeout方法设置,单位:毫秒。
一定要设置超时时间,不能无限等待下去,不然和正常的请求就一样了。

Servlet方式实现异步请求

面已经提到,可通过HttpServletRequest对象中获得一个AsyncContext对象,该对象构成了异步处理的上下文。所以,我们来实际操作下。

0.编写一个简单控制层

  1. package Net.XiangCaoWuYu.Controllers;  
  2.   
  3. import io.swagger.annotations.Api;  
  4. import io.swagger.annotations.ApiOperation;  
  5. import org.slf4j.Logger;  
  6. import org.slf4j.LoggerFactory;  
  7. import org.springframework.web.bind.annotation.*;  
  8.   
  9. import javax.servlet.AsyncContext;  
  10. import javax.servlet.AsyncEvent;  
  11. import javax.servlet.AsyncListener;  
  12. import javax.servlet.http.HttpServletRequest;  
  13. import javax.servlet.http.HttpServletResponse;  
  14. import java.io.IOException;  
  15.   
  16. /** 
  17.  * ClassName: AsyncController <br/> 
  18.  * Description: <br/> 
  19.  * date: 2019/7/28 16:06<br/> 
  20.  * 
  21.  * @author lisen01<br /> 
  22.  * @since JDK 1.8 
  23.  */  
  24. @RestController  
  25. @Api(tags = "测试异步请求")  
  26. @ResponseBody  
  27. @RequestMapping(value = "/AsyncTest")  
  28. public class ServletAsyncController {  
  29.   
  30.     private final static Logger logger = LoggerFactory.getLogger(ServletAsyncController.class);  
  31.   
  32.     @PostMapping(value = "test")  
  33.     @ApiOperation(value = "测试异步请求")  
  34.     public void test(HttpServletRequest request, HttpServletResponse response) {  
  35.         AsyncContext context = request.startAsync();  
  36.         context.addListener(new AsyncListener() {  
  37.             @Override  
  38.             public void onComplete(AsyncEvent asyncEvent) throws IOException {  
  39.                 logger.info("执行完成");  
  40.             }  
  41.   
  42.             @Override  
  43.             public void onTimeout(AsyncEvent asyncEvent) throws IOException {  
  44.                 logger.info("执行超时:");  
  45.             }  
  46.   
  47.             @Override  
  48.             public void onError(AsyncEvent asyncEvent) throws IOException {  
  49.                 logger.info("发生错误:" + asyncEvent.getThrowable());  
  50.             }  
  51.   
  52.             @Override  
  53.             public void onStartAsync(AsyncEvent asyncEvent) throws IOException {  
  54.                 logger.info("开始执行:");  
  55.             }  
  56.         });  
  57.   
  58.         //设置超时  
  59.         context.setTimeout(2000);  
  60.   
  61.         //开启线程  
  62.         context.start(new Runnable() {  
  63.             @Override  
  64.             public void run() {  
  65.                 try{  
  66.                     Thread.sleep(100);  
  67.                     logger.info("内部线程:"+Thread.currentThread().getName());  
  68.                     context.getResponse().setCharacterEncoding("UTF-8");  
  69.                     context.getResponse().setContentType("text/html;charset=utf-8");  
  70.                     context.getResponse().getWriter().println("这是内部线程");  
  71.                     //异步请求完成通知  
  72.                     //此时整个请求才完成  
  73.                     //其实可以利用此特性 进行多条消息的推送 把连接挂起。。  
  74.                     context.complete();  
  75.                 } catch (InterruptedException e) {  
  76.                     e.printStackTrace();  
  77.                 } catch (IOException e) {  
  78.                     e.printStackTrace();  
  79.                 }  
  80.             }  
  81.         });  
  82.   
  83.         //此时之类 request的线程连接已经释放了  
  84.         logger.info("线程:" + Thread.currentThread().getName());  
  85.     }  
  86. }  
注意:异步请求时,可以利用ThreadPoolExecutor自定义个线程池
使用过滤器时,需要加入asyncSupportedtrue配置,开启异步请求支持。
  1. @WebServlet(urlPatterns = "/okong", asyncSupported = true )     
  2. public  class AsyncServlet extends HttpServlet ...  
本文地址:https://www.lisen.me/springboot-native-asynchronous-request-api-description.html
温馨提示:文章内容系作者个人观点,不代表木子网对观点赞同或支持。
版权声明:本文为转载文章,来源于 謝謝同学 ,版权归原作者所有,欢迎分享本文,转载请保留出处!

发表评论


表情