访问绑定到非请求线程的RequestAttributes时发生IllegalStateException

时间:2018-12-12 13:27:57

标签: spring spring-boot spring-websocket

在不是请求线程的线程中使用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处理程序的线程绑定的属性调用回调,这表明确实没有按原样销毁它们。

0 个答案:

没有答案