我正在使用SpringBoot 1.5.2版本。我有一个异步REST调用,它产生单独的java线程来完成一个长时间运行的作业。长时间运行的作业需要更新数据库表,我将Spring审计bean配置为使用当前登录用户名更新表。我得到的问题是:通过调用setThreadContextInheritable(true)启用可继承标志后,传递给子线程的ServletRequestAttributes对象标记为"非活动"在子线程完成其工作之前,当审计bean尝试从RequestContextHolder中缓存的ServletRequestAttributes访问用户名时,最终会出错。
要启用可继承标记,请参阅Scope 'session' is not active for the current thread; IllegalStateException: No thread-bound request found
以下是获取目前为止的主要代码:
在 Application.java
中
@Override
public Executor getAsyncExecutor() {
SimpleAsyncTaskExecutor executor = new
SimpleAsyncTaskExecutor(appProperties.threadNamePrefix);
return executor;
}
@Bean
public ServletRegistrationBean registerAirportDispatchServlet() {
DispatcherServlet dispatcherServlet = new DispatcherServlet();
AnnotationConfigWebApplicationContext applicationContext =
new AnnotationConfigWebApplicationContext();
dispatcherServlet.setApplicationContext(applicationContext);
dispatcherServlet.setThreadContextInheritable(true);
ServletRegistrationBean servletRegistrationBean =
new ServletRegistrationBean(dispatcherServlet, "/*");
servletRegistrationBean.setName("AirportSCSDispacherServlet");
return servletRegistrationBean;
}
@Bean
@Scope(scopeName = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public AccessToken getAccessToken() {
RequestAttributes attribs =
RequestContextHolder.getRequestAttributes();
//do something with the attribs here...
return token;
}
是的,我必须注册我的DispatcherServlet并在那里设置标志,而不是使用RequestContextFilter和RequestContextListener,因为在请求过滤的路径下,DispatcherServlet将inheritable标志设置为false,这将覆盖链前面的RequestContextFilter和RequestContextListener的真实标志集。 从调试开始,我可以告诉FrameworkServlet的方法processRequest(),它是DispatcherServlet的超类,它在第989行调用 requestAttributes.requestCompleted(); ,并且 requestAttributes 对象在RequestContextHolder中保存为新生成的线程的继承属性,当新线程尝试获取AccessToken的这个属性时,Spring框架因为被标记为非活动而抛出错误。我已经尝试了SESSION范围,它没有工作,因为我的REST调用不在会话中,我使用Keycloak进行身份验证,因此请求属性包含字符串访问令牌。
我在这里问:无论如何我能保持这个继承的请求属性对象仍然有效吗?
答案 0 :(得分:0)
我被完全相同的问题震惊。我的应用程序正在启动一个异步线程,然后将HTTP响应立即发送回客户端。由于我在尝试获取异步线程中的属性时已经发送了响应,因此requestActive字段为false
。这就是此错误的原因。我们无法在外部设置requestActive
字段。 Spring将根据http请求状态处理此字段。