在Spring Boot

时间:2017-05-22 20:31:00

标签: java spring-mvc spring-boot

我正在使用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

以下是获取目前为止的主要代码:

  1. 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; }

  2. 是的,我必须注册我的DispatcherServlet并在那里设置标志,而不是使用RequestContextFilter和RequestContextListener,因为在请求过滤的路径下,DispatcherServlet将inheritable标志设置为false,这将覆盖链前面的RequestContextFilter和RequestContextListener的真实标志集。 从调试开始,我可以告诉FrameworkServlet的方法processRequest(),它是DispatcherServlet的超类,它在第989行调用 requestAttributes.requestCompleted(); ,并且 requestAttributes 对象在RequestContextHolder中保存为新生成的线程的继承属性,当新线程尝试获取AccessToken的这个属性时,Spring框架因为被标记为非活动而抛出错误。我已经尝试了SESSION范围,它没有工作,因为我的REST调用不在会话中,我使用Keycloak进行身份验证,因此请求属性包含字符串访问令牌。

    我在这里问:无论如何我能保持这个继承的请求属性对象仍然有效吗?

1 个答案:

答案 0 :(得分:0)

我被完全相同的问题震惊。我的应用程序正在启动一个异步线程,然后将HTTP响应立即发送回客户端。由于我在尝试获取异步线程中的属性时已经发送了响应,因此requestActive字段为false。这就是此错误的原因。我们无法在外部设置requestActive字段。 Spring将根据http请求状态处理此字段。