java.lang.IllegalStateException:在异步方面使用 RequestContextHolder.currentRequestAttributes() 时找不到线程绑定请求

2023-12-23

我有以下方面,出于某些原因,您可以看到here https://stackoverflow.com/questions/63115037/delay-in-spring-boot-aspect-cause-to-delay-in-joinpoint-method,不得不使用@EnableAsync and @Async通过方面方法,如下所示:

@Aspect
@Component
@EnableAsync
public class ApiCallLogAspect {

    @Async
    @AfterReturning(value = ("within(com.example..*.web.rest.api..*)"), returning = "returnValue")
    public void endpointAfterReturning(JoinPoint p, Object returnValue) throws InterruptedException {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
        System.out.println(request.getHeader("authorization"));
    }

}

现在,我得到这个异常:

java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
    at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at com.example.web.rest.api.ApiCallLogAspect.endpointAfterReturning(ApiCallLogAspect.java:40) ~[classes/:na]
    at com.example.web.rest.api.ApiCallLogAspect$$FastClassBySpringCGLIB$$f034ee12.invoke(<generated>) ~[classes/:na]
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771) ~[spring-aop-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) ~[spring-aop-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.aop.interceptor.AsyncExecutionInterceptor.lambda$invoke$0(AsyncExecutionInterceptor.java:115) ~[spring-aop-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_162]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_162]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_162]
    at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_162]

我该如何解决这个问题?有没有办法获取请求头


我通过以下这些更改和@M.Deinum 评论解决了这个问题:

public class ThreadContextHolder {
    private ThreadContextHolder() {
    }

    private static final ThreadLocal<Map<String, Object>> ctx = new ThreadLocal<>();

    public static Map<String, Object> getContext() {
        return ctx.get();
    }

    public static void setContext(Map<String, Object> attrs) {
        ctx.set(attrs);
    }

    public static void removeContext() {
        ctx.remove();
    }
}

然后注入taskExecutor to ApiCallLogAspect class:

@Bean
public Executor taskExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();

    executor.setTaskDecorator(
            runnable -> {
                HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();

                Map<String, Object> headers = new HashMap<>();
                for (String header : Collections.list(request.getHeaderNames())) {
                    headers.put(header, request.getHeader(header));
                }

                return () -> {
                    try {
                        ThreadContextHolder.setContext(headers);
                        runnable.run();
                    } finally {
                        ThreadContextHolder.removeContext();
                    }
                };
            });

    executor.initialize();
    return executor;
}

然后改变endpointAfterReturning方法:

@Async
@AfterReturning(value = ("within(com.example..*.web.rest.api..*)"), returning = "returnValue")
public void endpointAfterReturning(JoinPoint p, Object returnValue) throws InterruptedException {
    Map<String, String> headers = new HashMap<>();
    ThreadContextHolder.getContext().forEach((s, o) -> headers.put(s, o.toString()));
    System.out.println(headers.get("authorization"));
}

现在,一切正常。如果此解决方案有问题,请通知我。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java.lang.IllegalStateException:在异步方面使用 RequestContextHolder.currentRequestAttributes() 时找不到线程绑定请求 的相关文章

  • 在 th:href 链接中使用模型属性

    有没有办法在 th href 链接中引用模型属性 例如 a a Here 当前用户是控制器中指定的模型变量 这可以很容易地访问 如th text标签 但是 那th href百里香解析失败 如果有任何方法以这种方式引用模型属性 则在th hr
  • 将json URL导入到java并使用jackson库解析它

    我正在尝试读取 java 中的 json 链接并解析它 以便我可以将它用于其他事务 但问题是我收到错误 我真的不知道该如何处理它们 这是代码 package weather data import weather data import c
  • 在 Java 和 C 中在运行时调用名为“string”的方法

    我们如何调用名称为的方法string在运行时 谁能告诉我如何在 Java 和 C 中做到这一点 在java中可以通过反射api来完成 看一下Class getMethod String methodName Class parameterT
  • Eclipse 说“更新 Android Developer Toolkit”

    我不知何故弄乱了我的 Eclipse 和 Android 设置 我不知道如何修复它 问题症状如下 在 首选项 gt Android 中 我尝试选择 android sdk linux 的位置 选择时出现错误 此 Android SDK 需要
  • 将图像缩略图上传到服务器,而不上传整个图像

    据我所知 我在这里问的是不可能的 但我想无论如何我都会问 以防我遗漏了什么 假设您想让用户上传 JPG 图像 并且这些图像被缩放为较小的图标 并且原始图像始终被丢弃并且不再需要 有没有什么方法可以在大多数现代浏览器中普遍使用 让用户选择硬盘
  • 使用Optional作为类中的属性是一个好习惯吗? [复制]

    这个问题在这里已经有答案了 我读过一些关于目的的内容Optional 不幸的是我不记得在哪里 在Java 8中 我很惊讶作者没有提到使用Optional作为类中的属性 由于我在课堂上经常使用选项 我想知道这是否是一个好的做法 或者我可以更好
  • com.google.gwt.dev.jjs.InternalCompilerException:访问期间出现意外错误

    我在使用版本 2 6 0 编译 gwt 应用程序时遇到以下错误 最初我用 gwt 版本 2 6 1 的 maven 编译它 然后尝试通过版本 2 6 0 的 eclipse 编译它 跟版本兼容有关系吗 com google gwt dev
  • SwingWorker 在 Unsafe.park() 处挂起

    我有一个SwingWorker与后台服务器通信 然后更新JFrame 我正在调试我的应用程序并注意到即使在SwingWorker完成了它的工作 它的线程仍然存在 它挂在Unsafe park java lang Object 这是一个本机方
  • 找不到模块:javafx.controls

    我已经下载了JavaFX SDK 解压它并设置PATH TO FX系统变量 如下本说明 https openjfx io openjfx docs install javafx 我使用了以下代码示例 import javafx applic
  • 如何在Android Studio中关联.mp3文件

    我想根据列表视图项单击播放 mp3 文件 但是根据我的代码 我运行我的应用程序 出现此窗口 因此由于缺少音频选项 我真的不知道需要选择其中哪一个为了关联我的 mp3 文件 mainList setOnItemClickListener ne
  • Spring Boot 中的 Spring Security 配置

    我正在努力转换Spring 3项目到Spring 4 Spring 启动 我还不知道这样做是否正确 我转换Spring 安全 XML配置到一个基于Java的配置如下 Configuration EnableWebSecurity publi
  • 用 Java 捕获扬声器输出

    使用Java可以捕获扬声器输出吗 此输出不是由我的程序生成的 而是由其他正在运行的应用程序生成的 这可以用 Java 完成还是我需要求助于 C C 我有一个基于 Java 的应用程序 使用过的爪哇声音 https stackoverflow
  • 在java中将jpeg/png转换为像素数组

    如何将包含 jpeg 或 png 的字符串转换为像素数组 最好是一维 理想情况下使用java内置的类 原来你需要公共文件上传 http commons apache org fileupload 看着那 这用户指南 http commons
  • 如何告诉 Java SAX 解析器忽略无效字符引用?

    当尝试使用字符引用解析不正确的 XML 时 例如 x1 Java 的 SAX 解析器因致命错误而惨死 例如 org xml sax SAXParseException Character reference x1 is an invalid
  • Spark toLocalIterator 和迭代器方法之间的区别

    在编写 Spark 程序时我遇到了这个toLocalIterator 方法 之前我只使用iterator method 如果有人曾经使用过这种方法 请点亮 我在使用时遇到foreach and foreachPartitionSpark程序
  • 如何在 apache poi 中找到包含图片的单元格

    我尝试在 xls 文档中循环图像 我写下一个代码 HSSFPatriarch patriarch sheet getDrawingPatriarch if patriarch null Loop through the objects fo
  • 使用 colt java lib 时出现“矩阵太大”异常

    我正在使用 cern colt matrix lib 进行稀疏矩阵计算 但似乎我一直遇到此错误 线程 main 中的异常 java lang IllegalArgumentException 矩阵太大 我认为这是因为构造函数在 nrows
  • 如何避免连续“重置偏移量”和“寻找最新偏移量”?

    我正在尝试遵循本指南 https spark apache org docs latest structed streaming kafka integration html https spark apache org docs late
  • Jersey bean 验证 ParameterNameProvider

    我正在阅读关于泽西岛的文档Bean验证 https jersey java net documentation latest bean validation html The ParameterNameProvider示例显示如何定义方法的
  • 使用反射 API 填充 Proto 中的地图字段

    我正在尝试编写一个模块 该模块将获取 Message Builder 和从字段名称到值的映射 并将用值填充构建器 一切正常 直到我遇到地图字段 使用 Proto3 我收到一条特定消息 我知道我可以执行该消息的字段 builder b put

随机推荐