异步线程中获取到的request为空怎么办
时间: 2024-02-19 19:57:49 浏览: 78
在异步线程中获取到的request为空,这是因为异步线程和原始的请求线程不在同一个线程中,异步线程无法直接访问原始的请求线程的request对象。解决这个问题的方法有两种:
1. 使用Callable接口:可以将异步任务封装成一个Callable对象,并将原始的request对象作为参数传递给Callable对象。在异步任务中,可以通过Future对象获取到Callable对象的返回值,从而获取到request对象。
代码示例:
```
@RestController
public class MyController {
@Autowired
private AsyncService asyncService;
@RequestMapping("/test")
public String test(HttpServletRequest request) throws Exception {
Callable<String> task = () -> {
// 异步任务中获取request对象
HttpServletRequest asyncRequest = AsyncRequestContextHolder.getRequest();
// 处理业务逻辑
return "success";
};
Future<String> future = asyncService.execute(task);
String result = future.get();
return result;
}
}
@Service
public class AsyncService {
@Autowired
private AsyncTaskExecutor taskExecutor;
public <T> Future<T> execute(Callable<T> task) {
AsyncRequestContextCallable<T> callable = new AsyncRequestContextCallable<>(task);
return taskExecutor.submit(callable);
}
}
public class AsyncRequestContextCallable<T> implements Callable<T> {
private final Callable<T> task;
private final HttpServletRequest request;
public AsyncRequestContextCallable(Callable<T> task) {
this.task = task;
this.request = AsyncRequestContextHolder.getRequest();
}
@Override
public T call() throws Exception {
AsyncRequestContextHolder.setRequest(request);
try {
return task.call();
} finally {
AsyncRequestContextHolder.resetRequest();
}
}
}
public class AsyncRequestContextHolder {
private static final ThreadLocal<HttpServletRequest> requestHolder = new ThreadLocal<>();
public static void setRequest(HttpServletRequest request) {
requestHolder.set(request);
}
public static HttpServletRequest getRequest() {
return requestHolder.get();
}
public static void resetRequest() {
requestHolder.remove();
}
}
```
2. 使用ServletRequestAttributes:可以使用Spring提供的ServletRequestAttributes类来获取request对象。这个类是一个请求属性的存储器,可以在任何线程中存储和获取请求属性。在异步任务中,可以通过ServletRequestAttributes来获取到原始的request对象。
代码示例:
```
@RestController
public class MyController {
@Autowired
private AsyncService asyncService;
@RequestMapping("/test")
public String test(HttpServletRequest request) throws Exception {
Callable<String> task = () -> {
// 异步任务中获取request对象
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest asyncRequest = attributes.getRequest();
// 处理业务逻辑
return "success";
};
Future<String> future = asyncService.execute(task);
String result = future.get();
return result;
}
}
@Service
public class AsyncService {
@Autowired
private AsyncTaskExecutor taskExecutor;
public <T> Future<T> execute(Callable<T> task) {
return taskExecutor.submit(() -> {
RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
try {
RequestContextHolder.setRequestAttributes(attributes, true);
return task.call();
} finally {
RequestContextHolder.resetRequestAttributes();
}
});
}
}
```
以上两种方法都可以解决异步线程中获取request对象为空的问题,具体选择哪种方法取决于具体的业务需求和开发习惯。
阅读全文