• Spring 单例 httprequest 线程安全


    @Autowired HttpServletRequest之所以线程安全是因为, httpsevletRequest 储存在 RequestContextHolder中。 

    • 每次http请求的doXXX 都会被FrameworkServlet拦截,通过 RequestContextHolder.setxxxxx  写入TheadLocal。
    • Autowired 获取request的时候,通过RequestContextHolder.getxxx 从ThreadLocal中获取。

    为什么Autowired HttpServletRequest是线程安全的,获取的方式

     1. 启动断点调试,查看request的来源是  WebApplicationContextUtils.RequestObjectFactory.

    2. 查看源码 WebApplicationContextUtils.RequestObjectFactory, request 来自于 RequestContextHolder.currentRequestAttributes() 方法

    class WebApplicationContextUtils {
        @SuppressWarnings("serial")
        private static class RequestObjectFactory implements ObjectFactory<ServletRequest>, Serializable {
    
            @Override
            public ServletRequest getObject() {
                return currentRequestAttributes().getRequest();
            }
    
            @Override
            public String toString() {
                return "Current HttpServletRequest";
            }
        }

        private static ServletRequestAttributes currentRequestAttributes() {
            RequestAttributes requestAttr = RequestContextHolder.currentRequestAttributes();
            if (!(requestAttr instanceof ServletRequestAttributes)) {
                throw new IllegalStateException("Current request is not a servlet request");
            }
            return (ServletRequestAttributes) requestAttr;
        }
    }

    3. 上述方法的attributes来自于线程安全的ThreadLocal中的当前线程的HttpServletRequest

    public abstract class RequestContextHolder  {
    
        private static final boolean jsfPresent =
                ClassUtils.isPresent("javax.faces.context.FacesContext", RequestContextHolder.class.getClassLoader());
    
        private static final ThreadLocal<RequestAttributes> requestAttributesHolder =
                new NamedThreadLocal<>("Request attributes");

        public static void setRequestAttributes(@Nullable RequestAttributes attributes, boolean inheritable) {
            if (attributes == null) {
                resetRequestAttributes();
            }
            else {
                if (inheritable) {
                    inheritableRequestAttributesHolder.set(attributes);
                    requestAttributesHolder.remove();
                }
                else {
                    requestAttributesHolder.set(attributes);
                    inheritableRequestAttributesHolder.remove();
                }
            }
        }

     

    设置的方式

    request是什么时候设置到threadlocal中去的呢? 是在Springmvc的dispatcherServlet的父类FrameworkServlet里操作的.。 doGet 、doPost 、doXXX方法都是委托processRequest方法去做的. 也就是说请求方法会被FrameworkServlet的processRequest拦截。

    class FrameworkServlet {
       protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
              .....
            initContextHolders(request, localeContext, requestAttributes);
       }
    
        private void initContextHolders(HttpServletRequest request,
                @Nullable LocaleContext localeContext, @Nullable RequestAttributes requestAttributes) {
    
            ......
            if (requestAttributes != null) {
                RequestContextHolder.setRequestAttributes(requestAttributes, this.threadContextInheritable);
            }
            ....
        }
    
    }

    参考  

    https://www.cnblogs.com/abcwt112/p/7777258.html

  • 相关阅读:
    各位AS3各种验证在这里,邮箱 身份证 ...
    各位同学还在为AS3在IE透明模式下弹出新窗口而烦恼吗?
    Flash As3 通过二进制[ByteArray]判断真实的文件类型
    【A8笔记1】Alternativa 8.5.0 在Flash、Fb、Fd中的配置
    超酷光带效果
    flash 墙
    A3D CoverFlow图片展示效果
    Windows8Metro模式IE10放弃Flash的支持
    html5 控件整理
    AS3中JSON的基本应用实例
  • 原文地址:https://www.cnblogs.com/webglcn/p/10659821.html
Copyright © 2020-2023  润新知