在不是请求线程的线程中使用RequestAttributes的寿命时,我遇到了问题。
我有一个应用程序,该应用程序在HTTP请求期间通过websockets(STOMP)连接执行一些操作。我使用StompFrameHandler实现了STOMP处理代码,当收到新帧时,该代码将在专用线程上调用handleFrame()方法。该方法中的代码(不在请求线程上运行)需要访问RequestAttributes。
public class DataFrameHandler implements StompFrameHandler{
@Override
public void handleFrame(StompHeaders headers, Object payload) {
RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
// The following line throws IllegalStateException when accessed during the second request...
Object attribute = attributes.getAttribute("attributeName", RequestAttributes.SCOPE_REQUEST);
...
}
...
}
在扩展HandlerInterceptorAdapter的类中设置属性(以便可以在请求的开始处设置它们,并在结束时删除它们)。
@Component
public class RequestInterceptor extends HandlerInterceptorAdapter {
private MyAttributeFactory myAttributeFactory;
@Autowired
public DbConnectionInterceptor(MyAttributeFactory myAttributeFactory) {
this.myAttributeFactory = myAttributeFactory;
}
/**
* Executed before request handler is executed
**/
@Override
public boolean preHandle(final HttpServletRequest request, final HttpServletResponse response, final Object handler) {
Object myAttribute = myAttributeFactory.build();
requestContextHolder.setAttribute("attributeName", myAttribute, true);
}
/**
* Executed after the whole request is finished
**/
@Override
public void afterCompletion(final HttpServletRequest request, final HttpServletResponse response, final Object handler, final Exception ex) {
requestContextHolder.removeAttribute("attributeName");
}
}
我通过RequestContextHolder检索RequestAttributes 由于RequestAttributes是线程绑定的,因此我看到当StompFrameHandler需要访问它们时,将创建RequestAttributes的新副本。
这在第一个HTTP请求上运行良好,但是当第二个HTTP请求进入并调用StompFrameHandler时,它仍在使用上一个HTTP请求中的RequestAttributes实例,该实例现在不再处于活动状态,并且在访问时引发以下异常:
java.lang.IllegalStateException: Cannot ask for request attribute - request is not active anymore!
如何确保在HTTP请求结束时清除STOMP处理线程中的RequestAttributes副本?
PS:我尝试使用registerDestructionCallback,但是仅针对请求的线程属性而不是与STOMP处理程序的线程绑定的属性调用回调,这表明确实没有按原样销毁它们。