原文链接:千万不要把 Request 传递到异步线程里面!有坑!
一、post接口
接口参数:
后端代码:
@PostMapping("/postTest") public String postTest(HttpServletRequest request, HttpServletResponse response) { // AsyncContext asyncContext = request.startAsync(request, response); String age1 = request.getParameter("age"); String name1 = request.getParameter("name"); System.out.println("age1=" + age1 + ",name1=" + name1); new Thread(new Runnable() { @Override public void run() { String age2 = request.getParameter("age"); String name2 = request.getParameter("name"); System.out.println("age2=" + age2 + ",name2=" + name2); //模拟业务请求 try { Thread.sleep(10000); } catch (InterruptedException e) { throw new RuntimeException(e); } age2 = request.getParameter("age"); name2 = request.getParameter("name"); System.out.println("age2=" + age2 + ",name2=" + name2); // asyncContext.complete(); } }).start(); return "post success"; }
执行结果:
注:多次请求,打印结果不变
原因:
因为request 在 Tomcat 中是循环使用的,第一次和第二次获取参数时,request还没有被回收,sleep设置为10秒,第三次获取参数前,request已经被回收。
二、get接口
接口参数:
http://127.0.0.1:18086/finger-print/asyncRequestController/getTest?age=18
后端代码:
@GetMapping("/getTest") public String getTest(HttpServletRequest request, HttpServletResponse response) { // AsyncContext asyncContext = request.startAsync(request, response); String age = request.getParameter("age"); System.out.println("age=" + age); new Thread(() -> { try { Thread.sleep(2000); } catch (InterruptedException e) { throw new RuntimeException(e); } String age1 = request.getParameter("age"); System.out.println("age1=" + age1); // asyncContext.complete(); }).start(); return "success"; }
执行结果:
注:两次请求结果不一致,第二次请求两次获取参数都为空
原因:
第一次请求,获取参数为空原因和post请求一样,第二次请求获取参数都为空的原因,与获取参数的原理有关,详细建议打开原文链接学习,这里只简单说明。
请求第一次获取参数时,会把所有入参解析到一个map中,并给出一个标识(didQueryParameters = true),表明参数已解析,后面获取参数都到map中获取,所以第一次打印age正常。
而第一次打印age1时,是在 sleep 2秒后,这时request已被回收利用,且 didQueryParameters 也被赋值为 false,map也被清空,所以获取为null,并且第一次打印age1,会导致 didQueryParameters 又被赋值为 true,但是异步线程的调用已经超出了request的生命周期,不会再被回收,所以 didQueryParameters 不会再改为 false。
因此第二次打印age时,不会重新进行解析参数到map中的操作,打印结果依然为null。
第二次打印age1,步骤同第一次打印age1。
标签:String,age,request,getParameter,age1,参数,线程,null From: https://www.cnblogs.com/YeHuan/p/18029739