Spring promoting request scoped bean to child threads (HttpServletRequest)

前端 未结 2 957
不知归路
不知归路 2021-02-20 01:54

I tried a lot of things now but i seem to miss a piece of the puzzle. Here is the story: I have a request scoped bean that reads some SessionContext from the HttpServletRequest.

2条回答
  •  一整个雨季
    2021-02-20 02:26

    For any future adventurers:

    I took some time to dig through the Spring code and found RequestContextHolder that has a inheritableRequestAttributesHolder. If you look at the documentation of what that is (inheriting from: InheritableThreadLocal) one can read the following:

    Inheritable thread-local variables are used in preference to ordinary thread-local variables when the per-thread-attribute being maintained in the variable (e.g., User ID, Transaction ID) must be automatically transmitted to any child threads that are created.

    So the RequestContextHolder has a field for that and actually setRequestAttributes supports a flag to use inheritableRequestAttributesHolder. Furthermore if you look at RequestContextListener -> requestInitialized you find that it is called without the flag (= false). So what I ended up doing is this:

    public class InheritableRequestContextListener extends RequestContextListener {
        private static final String REQUEST_ATTRIBUTES_ATTRIBUTE =
            InheritableRequestContextListener.class.getName() + ".REQUEST_ATTRIBUTES";
    
        @Override
        public void requestInitialized(ServletRequestEvent requestEvent) {
            if (!(requestEvent.getServletRequest() instanceof HttpServletRequest)) {
                throw new IllegalArgumentException(
                        "Request is not an HttpServletRequest: " + requestEvent.getServletRequest());
            }
            HttpServletRequest request = (HttpServletRequest) requestEvent.getServletRequest();
            ServletRequestAttributes attributes = new ServletRequestAttributes(request);
            request.setAttribute(REQUEST_ATTRIBUTES_ATTRIBUTE, attributes);
            LocaleContextHolder.setLocale(request.getLocale());
            RequestContextHolder.setRequestAttributes(attributes, true);
        }
    }
    

    And voila, I can access SessionContextProvider in child threads.

提交回复
热议问题