Java充电社
专辑
博文
联系我
本人继续续收门徒,亲手指导
SpringMVC教程
-> 异步处理请求
1、Helloword
2、@Controller、@RequestMapping
3、接口测试利器
4、如何接受请求中的参数?
5、@RequestBody接收Json格式数据
6、多文件上传
7、返回页面常见的5种方式
8、返回json格式数据 & 通用返回值设计
9、SpringMVC返回null是什么意思?
10、异步处理请求
11、如何集成静态资源?
12、拦截器怎么用?
13、统一异常处理
14、实战篇:通用返回值 & 异常处理设计
15、全注解的方式 & 原理解析
16、源码解析SpringMVC处理请求的流程
17、源码解析SpringMVC容器的启动过程
18、RequestBodyAdvice:对@ReuqestBody进行增强
19、ResponseBodyAdvice:对@ResponseBody进行增强
20、RESTful接口详解
21、接口调用利器RestTemplate
22、参数解析器HandlerMethodArgumentResolver解密
23、@RequestParam用法及原理详解
24、@RequestBody原理解密
25、@RequestHeader详解
26、@CookieValue详解
27、@RequestAttribute详解
28、@SessionAttribute详解
29、重定向和转向详解
30、Converter转换器详解
31、跨域问题详解
32、类容协商,颠覆你的认知
33、终章
34、CORS通信
35、浏览器安全策略 & CORS
36、Http中的Content-Type详解
上一篇:SpringMVC返回null是什么意思?
下一篇:如何集成静态资源?
<div style="display:none"></div> **大家好,我是路人,本文如果对你有帮助,点个在看,顺便忙转发一下,非常需要大家的支持,对java有兴趣的朋友欢迎加我微信itsoku交流。** ## 1、本篇内容 本文让大家掌握springmvc中异步处理请求,特别牛逼的一个功能,大家一定要掌握。 看本文之前,需要一些预备知识,大家先看下这篇文章:[servlet3.0中的异步处理](https://mp.weixin.qq.com/s/ylJdW1Nlmsfw2Aaq1uDZcg)。 ## 2、看段代码,分析问题 ```java @ResponseBody @RequestMapping("/async/m1.do") public String m1() throws InterruptedException { long st = System.currentTimeMillis(); System.out.println("主线程:" + Thread.currentThread() + "," + st + ",开始"); //休眠3秒,模拟耗时的业务操作 TimeUnit.SECONDS.sleep(3); long et = System.currentTimeMillis(); System.out.println("主线程:" + Thread.currentThread() + "," + st + ",结束,耗时(ms):" + (et - st)); return "ok"; } ``` > 这段代码很简单 > > - 这段代码是springmvc提供的一个接口 > > - 内部休眠了3秒钟,用来模拟耗时的操作 > - 方法内部有2条日志(日志中包含了当前线程、开始时间、结束时间、耗时) 浏览器中访问下这个接口,效果如下,可以看到接口耗时3s左右。 ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/221/0ae06da9-cdc9-46a0-848a-edf6f9a96b4e.png) 控制台输出 ```html 主线程:Thread[http-nio-8080-exec-1,5,main],1624889293055,开始 主线程:Thread[http-nio-8080-exec-1,5,main],1624889293055,结束,耗时(ms):3002 ``` 从输出中,我们可以看出,这个接口从开始到结束都是由tomcat中的线程来处理用户请求的,也就是说,3秒这段时间内,tomcat中的一个线程会被当前请求一直占用了则,tomcat线程是有最大值的,默认情况下好像是75,那么问题来了。 当3秒之内,来的请求数量超过了tomcat最大线程数的时候,其他请求就无法处理了,而此时tomcat中这些线程都处理sleep 3s的休眠状态,cpu此时没活干,此时就会造成机器没活干,但是呢又不能处理新的请求,这就是坑啊,浪费资源,怎么办呢? 遇到这种场景的,也就是说接口内部比价耗时,但是又不能充分利用cpu的,我们可以采用异步的方式来处理请求,过程如下: tomcat线程,将请求转发给我们自定义的子线程去处理这个请求,然后tomcat就可以继续去接受新的请求了。 ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/221/6f08fec0-6905-4309-8e7e-efeabf82768c.png) ## 3、springmvc中异步处理 主要有3个大的步骤。 ### step1:servlet开启异步处理支持 > web.xml中开启servlet异步支持 ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/221/4d31ded7-a9ff-4205-b334-49d8a1fe388b.png) ### step2:Filter中添加异步支持 > 如果我们的异步请求需要经过Filter的,那么需要在web.xml对这个Filter添加异步支持. ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/221/47fa9778-f496-4d89-addd-3b26d3239f0d.png) ### step3:接口返回值为DeferredResult > 这个步骤中细节比较多,当需要异步响应请求的时候,返回值需要为DeferredResult,具体参考下面案例代码,详细信息都在注释中了,大家注意看注释。 > > - 第1步:创建DeferredResult<返回值类型>(超时时间[毫秒],超时回调的代码) > - 第2步:在子线程中异步处理业务,调用DeferredResult的setResult方法,设置最终返回到客户端的结果,此方法调用以后,客户端将接收到返回值,然后响应过程请求就结束了 > - 第3步:将DefaultResult作为方法返回值 ```java /** * 使用springmvc的异步功能,业务处理放在异步线程中执行 * * @param timeout 异步处理超时时间(毫秒) * @return */ @ResponseBody @RequestMapping("/async/m2/{timeout}.do") public DeferredResult<String> m2(@PathVariable("timeout") long timeout) { long st = System.currentTimeMillis(); System.out.println("主线程:" + Thread.currentThread() + "," + st + ",开始"); /** * 1、创建DeferredResult<返回值类型>(超时时间[毫秒],超时回调的代码) */ DeferredResult<String> result = new DeferredResult<String>(timeout, () -> { System.out.println("超时了"); return "timeout"; }); //2、异步处理业务, new Thread(() -> { //开启一个异步线程,在异步线程中进行业务处理操作 try { TimeUnit.SECONDS.sleep(3); //3、调用DeferredResult的setResult方法,设置最终返回到客户端的结果,此方法调用以后,客户端将接收到返回值 result.setResult("ok"); } catch (InterruptedException e) { result.setResult("发生异常了:" + e.getMessage()); } }).start(); long et = System.currentTimeMillis(); System.out.println("主线程:" + Thread.currentThread() + "," + st + ",结束,耗时(ms):" + (et - st)); //3、将DefaultResult作为方法返回值 return result; } ``` > 上面的m2方法个timeout参数,调用者通过这个参数来指定接口的超时时间,未超时的情况下,也就是说timeout大于3秒的时候,此时会输出ok,否则将出现超时,此时会将DeferredResult构造器第2个参数的执行结果作为最终的响应结果,即会向客户端输出timeout。 > > 使用建议:案例开启了一个新的子线程来执行业务操作,生产环境中,建议大家采用线程池的方式,效率更高。 > > 下面我们来通过2个case来模拟下这个接口超时和正常的结果。 ## 4、模拟非超时请求 当timeout大于3秒时,才不会出现超时,此时我们传递4000毫秒来试试 ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/221/b0500e95-7a9c-46d9-9b47-c2194380e5be.png) 控制台输出如下,可以看到主线程瞬间就结束了。 ``` 主线程:Thread[http-nio-8080-exec-6,5,main],1624891886020,开始 主线程:Thread[http-nio-8080-exec-6,5,main],1624891886020,结束,耗时(ms):0 ``` ## 5、模拟超时请求 当timeout小于3秒会出现超时,此时我们传递1000毫秒来试试 ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/221/e75f6a08-bb19-408a-b68c-0795ad40a048.png) 控制台输出如下,输出了超时信息,且通过前两行输出看出主线程瞬间就结束了,不会被请求阻塞。 ``` 主线程:Thread[http-nio-8080-exec-1,5,main],1624892109695,开始 主线程:Thread[http-nio-8080-exec-1,5,main],1624892109695,结束,耗时(ms):0 超时了 ``` ## 6、总结 当接口中有大量的耗时的操作,且这些耗时的操作让线程处于等待状态的时候,此时为了提升系统的性能,可以将接口调整为异步处理请求的方式。 ## 7、案例代码 ```html git地址:https://gitee.com/javacode2018/springmvc-series ``` ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/221/6f6e75ee-9163-48a8-b027-4d617da20b8e.png) <a style="display:none" target="_blank" href="https://mp.weixin.qq.com/s/_S1DD2JADnXvpexxaBwLLg" style="color:red; font-size:20px; font-weight:bold">继续收门徒,亲手带,月薪 4W 以下的可以来找我</a> ## 最新资料 1. <a href="https://mp.weixin.qq.com/s?__biz=MzkzOTI3Nzc0Mg==&mid=2247484964&idx=2&sn=c81bce2f26015ee0f9632ddc6c67df03&scene=21#wechat_redirect" target="_blank">尚硅谷 Java 学科全套教程(总 207.77GB)</a> 2. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247484192&idx=1&sn=505f2faaa4cc911f553850667749bcbb&scene=21#wechat_redirect" target="_blank">2021 最新版 Java 微服务学习线路图 + 视频</a> 3. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247484573&idx=1&sn=7f3d83892186c16c57bc0b99f03f1ffd&scene=21#wechat_redirect" target="_blank">阿里技术大佬整理的《Spring 学习笔记.pdf》</a> 4. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247484544&idx=2&sn=c1dfe907cfaa5b9ae8e66fc247ccbe84&scene=21#wechat_redirect" target="_blank">阿里大佬的《MySQL 学习笔记高清.pdf》</a> 5. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247485167&idx=1&sn=48d75c8e93e748235a3547f34921dfb7&scene=21#wechat_redirect" target="_blank">2021 版 java 高并发常见面试题汇总.pdf</a> 6. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247485664&idx=1&sn=435f9f515a8f881642820d7790ad20ce&scene=21#wechat_redirect" target="_blank">Idea 快捷键大全.pdf</a> ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/1/2883e86e-3eff-404a-8943-0066e5e2b454.png)
#custom-toc-container