使用 Camunda-REST 依赖项时 RequestContextHolder null
RequestContextHolder null when using Camunda-REST dependency
简介
我最近在我的 Camunda/Spring 启动应用程序中偶然发现了一个问题。我只想公开 Camunda REST-API,从而让 Maven 合并 camunda-bpm-spring-boot-starter-rest 依赖项。不幸的是,这似乎与我已经为非 Camunda API 端点准备的 Spring 启动配置相混淆。
具体问题描述
我有一个 class 类型的 AccessDecisionVoter,其中 RequestContextHolder 用于获取当前请求的详细信息,同时查询自制的 REST 端点。该决策投票者 class 涉及方法安全性,基本上决定用户是否有权使用该端点。虽然这种方法适用于各种其他 Camunda 依赖项,但上述依赖项以某种方式扭曲了我自己 API 的请求处理(Camunda REST-API 工作正常)。结果是 returns null 的 RequestContextHolder,最终导致 AccessDeniedException。
使用 RequestContextHolder:
HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
解释和可能的解决方案
看来问题可能与请求信息未传递到某个子线程的线程问题有关。但这需要依赖性来扰乱 DispatcherServlet 或其他东西 and/or 产生一个新线程来处理对非 Camunda API 的请求。看起来很奇怪,但另一方面,生成 RequestContextListener (Spring) 类型的 Bean 确实解决了问题。
@Bean
public RequestContextListener requestContextListener() {
return new RequestContextListener();
}
如果能理解这个问题以及依赖性如何扰乱我的端点,那就太好了。最终我正在寻找一些修改(也许是一些 属性?)这有助于我摆脱 RequestContextListener bean。虽然作为解决方法似乎不错。
有什么好的解释吗?
巴克尔迪霍干杯
幸运的是,我能够回答我自己的问题。
1.) 在原始 Spring 引导环境中,DispatcherServlet 将 属性 setThreadContextInheritable
设置为 false
。这表明没有请求详细信息与处理特定请求的父线程的可能子线程共享。上述问题的一个可能解决方案当然是将此 属性 设置为 true
。但是在使用线程池的环境中,这种修改会将请求信息暴露给所有包含的线程,因此不应该是首选解决方案 (Ref)。
2.) 在调试时我发现 Camunda REST 依赖项生成了一个类型为 FilterRegistrationBean 的 bean,它被命名为 requestContextFilter
并因此替换了类型的原始 bean OrderedRequestContextFilter 由 Spring 自动维护和生成。原始 bean 将请求详细信息公开给当前线程。由于缺少详细信息,子线程之间不共享,因此 RequestContextHolder 保持为空。
因此,使用 RequestContextListener 类型的新 bean 似乎是将请求详细信息公开给当前子线程而不会弄乱 DispatcherServlet 属性的正确方法:
@Bean
public RequestContextListener requestContextListener() {
return new RequestContextListener();
}
简介
我最近在我的 Camunda/Spring 启动应用程序中偶然发现了一个问题。我只想公开 Camunda REST-API,从而让 Maven 合并 camunda-bpm-spring-boot-starter-rest 依赖项。不幸的是,这似乎与我已经为非 Camunda API 端点准备的 Spring 启动配置相混淆。
具体问题描述
我有一个 class 类型的 AccessDecisionVoter,其中 RequestContextHolder 用于获取当前请求的详细信息,同时查询自制的 REST 端点。该决策投票者 class 涉及方法安全性,基本上决定用户是否有权使用该端点。虽然这种方法适用于各种其他 Camunda 依赖项,但上述依赖项以某种方式扭曲了我自己 API 的请求处理(Camunda REST-API 工作正常)。结果是 returns null 的 RequestContextHolder,最终导致 AccessDeniedException。
使用 RequestContextHolder:
HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
解释和可能的解决方案
看来问题可能与请求信息未传递到某个子线程的线程问题有关。但这需要依赖性来扰乱 DispatcherServlet 或其他东西 and/or 产生一个新线程来处理对非 Camunda API 的请求。看起来很奇怪,但另一方面,生成 RequestContextListener (Spring) 类型的 Bean 确实解决了问题。
@Bean
public RequestContextListener requestContextListener() {
return new RequestContextListener();
}
如果能理解这个问题以及依赖性如何扰乱我的端点,那就太好了。最终我正在寻找一些修改(也许是一些 属性?)这有助于我摆脱 RequestContextListener bean。虽然作为解决方法似乎不错。
有什么好的解释吗?
巴克尔迪霍干杯
幸运的是,我能够回答我自己的问题。
1.) 在原始 Spring 引导环境中,DispatcherServlet 将 属性 setThreadContextInheritable
设置为 false
。这表明没有请求详细信息与处理特定请求的父线程的可能子线程共享。上述问题的一个可能解决方案当然是将此 属性 设置为 true
。但是在使用线程池的环境中,这种修改会将请求信息暴露给所有包含的线程,因此不应该是首选解决方案 (Ref)。
2.) 在调试时我发现 Camunda REST 依赖项生成了一个类型为 FilterRegistrationBean 的 bean,它被命名为 requestContextFilter
并因此替换了类型的原始 bean OrderedRequestContextFilter 由 Spring 自动维护和生成。原始 bean 将请求详细信息公开给当前线程。由于缺少详细信息,子线程之间不共享,因此 RequestContextHolder 保持为空。
因此,使用 RequestContextListener 类型的新 bean 似乎是将请求详细信息公开给当前子线程而不会弄乱 DispatcherServlet 属性的正确方法:
@Bean
public RequestContextListener requestContextListener() {
return new RequestContextListener();
}