RequestContextHolder.getRequestAttributes()在@Async之后获取null的原因是因为@Async注解会开启一个新的线程来执行被注解的方法,而RequestContextHolder.getRequestAttributes()方法是通过ThreadLocal来获取当前线程的请求属性,由于新线程没有继承父线程的ThreadLocal变量,所以在新线程中调用该方法会返回null。
解决这个问题的方法是使用CompletableFuture或者自定义的ThreadLocal来传递请求属性。具体步骤如下:
ThreadLocal<ServletRequestAttributes> requestAttributesHolder = new ThreadLocal<>();
requestAttributesHolder.set((ServletRequestAttributes) RequestContextHolder.getRequestAttributes());
CompletableFuture.supplyAsync(() -> {
// 在异步任务中获取请求属性
ServletRequestAttributes requestAttributes = requestAttributesHolder.get();
// 执行异步任务的逻辑
// ...
return result;
});
通过这种方式,可以在异步任务中获取到正确的请求属性。
需要注意的是,使用自定义的ThreadLocal需要在异步任务执行完毕后手动清除ThreadLocal中的值,以避免内存泄漏。可以在异步任务执行完毕后,添加清除ThreadLocal的代码,例如:
CompletableFuture.supplyAsync(() -> {
// 在异步任务中获取请求属性
ServletRequestAttributes requestAttributes = requestAttributesHolder.get();
// 执行异步任务的逻辑
// ...
return result;
}).whenComplete((result, throwable) -> {
// 异步任务执行完毕后清除ThreadLocal
requestAttributesHolder.remove();
});
这样就可以解决在@Async之后调用RequestContextHolder.getRequestAttributes()获取null的问题。
领取专属 10元无门槛券
手把手带您无忧上云