子线程获取不到主线程的request信息?
springboot项目下,控制层发起任务,在service层开启一个thread线程执行相关操作,当控制层返回之后,子线程就获取不到主线程的request的相关信息,这应该怎么解决?
@Undest
controller:
public class ControllerReportController { private static InheritableThreadLocal<HttpServletRequest> threadLocalData = new InheritableThreadLocal<>();
@Autowired
ControllerReportService controllerReportService;
@RequestMapping("/test")
public void test(HttpServletRequest request) {
String userId = request.getHeader("userId");
log.info(userId);
threadLocalData.set(request);
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
controllerReportService.test(threadLocalData);
}
});
thread.start();
log.info("主线程结束");
}
}
service:
public class ControllerReportServiceImpl implements ControllerReportService { @Override
public void test(InheritableThreadLocal<HttpServletRequest> threadLocalData) {
try {
Thread.sleep(5000);
} catch (Exception e) {
}
HttpServletRequest httpServletRequest = threadLocalData.get();
String userId = httpServletRequest.getHeader("userId");
log.info(String.valueOf(userId));
}
}
结果
[INFO ] [164] [2023-08-02 11:45:31] 293
[INFO ] [164] [2023-08-02 11:45:31] 主线程结束
[INFO ] [164] [2023-08-02 11:45:31] RequestId:1690947931271, 本次请求耗时SpeedTime:4ms
[INFO ] [745] [2023-08-02 11:45:36] null
回答:
更新:
下面的代码经过我个人测试可以跑通:
Controller:
package com.example2.demo.controller;import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping(value = "/test")
public class TestController {
private static InheritableThreadLocal<HttpServletRequest> threadLocalData = new InheritableThreadLocal<>();
@Autowired
TestService testService;
@RequestMapping("/check")
@ResponseBody
public void check(HttpServletRequest request) throws Exception {
threadLocalData.set(request);
System.out.println("父线程打印的id->" + request.getParameter("id"));
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
//服务层里写方法
testService.doSomeThing(threadLocalData);
}
});
thread.start();
System.out.println("父线程方法结束");
}
}
Service:
package com.example2.demo.controller;import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Service;
@Service("/testService")
public class TestService {
public void doSomeThing(InheritableThreadLocal<HttpServletRequest> threadLocalData) {
System.out.println("子线程打印的id->" +threadLocalData.get().getParameter("id"));
System.out.println("子线程方法结束");
}
}
请求:
结果:
可以看到在主线程返回后子线程依然能够拿到request里的值
回答:
在异步线程里不应该直接访问request对象本身。
可以把需要异步处理的信息从request对象中拿出来,传递给异步线程,但不要直接把request对象丢给异步线程访问。
以jetty的实现为例, 在Jetty中,request对象并不是每次请求都创建一个新对象,而是会被http线程复用的。所以,request对象如果被两个线程同时访问,会造成意想不到的错误。
我曾经因为这个问题排查了很久代码
其他web容器是否存在同样的限制和具体实现有关。
所以强烈不建议直接把request对象丢给异步线程持有。
以上是 子线程获取不到主线程的request信息? 的全部内容, 来源链接: utcz.com/p/945274.html