子线程获取不到主线程的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

回到顶部