zoukankan      html  css  js  c++  java
  • SpringMVC:学习笔记(12)——ThreadLocal实现会话共享

    SpringMVC:学习笔记(12)——ThreadLocal实现会话共享

    ThreadLocal

      ThreadLocal,被称为线程局部变量。在并发编程的情况下,使用ThreadLocal创建的变量只能被当前线程访问,其他线程则无法访问和修改。每个Thread对象内部都维护了一个ThreadLocalMap它可以存放若干个ThreadLocal。如下为Thread源码部分:

    /* ThreadLocal values pertaining to this thread. This map is maintained
     * by the ThreadLocal class. */
    ThreadLocal.ThreadLocalMap threadLocals = null;
    

      当我们对ThreadLocal执行set方法时,他首先做的是取当前线程的ThreadLocalMap,所以可以保证每个线程可以独享自己的ThreadLocal对象。如下为ThreadLocal源码部分:

        /**
         * Sets the current thread's copy of this thread-local variable
         * to the specified value.  Most subclasses will have no need to
         * override this method, relying solely on the {@link #initialValue}
         * method to set the values of thread-locals.
         *
         * @param value the value to be stored in the current thread's copy of
         *        this thread-local.
         */
        public void set(T value) {
            Thread t = Thread.currentThread();
            ThreadLocalMap map = getMap(t);
            if (map != null)
                map.set(this, value);
            else
                createMap(t, value);
        }
    

      那这样一来ThreadLocal就具有了一些高级特性:

    • 全局性,在当前线程中,任何一个点都可以访问到ThreadLocal的值。
    • 独立性,该线程的ThreadLocal只能被该线程访问,一般情况下其他线程访问不到。

     

    实现会话共享

    通用的思路

      在SpringMVC中,@Action方法接受了Request对象,我们可以从中取出HttpSession会话数据

    public ModelAndView getTest(HttpServletRequest request, HttpServletResponse response){
         String userId = request.getSession().getAttribute("user").toString();
    }
    

      但要是我们在一个普通的方法中想访问到HttpSession对象就会很难了,如果我们在请求到来时用Filter把HttpSession保存到ThreadLocal中,利用ThreadLocal的全局性,不是就可以在普通方法中使用了吗?当然我们最好将其封装一个类,来方便以后随时调用和迭代更新。

    HttpContext 

      我们创建一个HttpContext类,来将Request、Response、Session、Cookies等对象进行封装,方便以后直接使用。

    public class HttpContext {
        private HttpServletRequest request;
        private HttpServletResponse response;
        private final static ThreadLocal<HttpContext> contextContainer = new ThreadLocal<HttpContext>();
        /**
         * 初始化
         */
        public static HttpContext begin(HttpServletRequest req, HttpServletResponse res) {
            HttpContext context = new HttpContext();
            context.request = req;
            context.response = res;
            contextContainer.set(context);
            return context;
        }
        public static HttpContext get(){
            return contextContainer.get();
        }
        /**
         * 销毁
         */
        public void end() {
            this.request = null;
            this.response = null;
            contextContainer.remove();
        }
        public ServletContext getContext() {
            return this.request.getServletContext();
        }
        public HttpSession getSession() {
            return this.request.getSession(false);
        }
        public HttpServletRequest getRequest() {
            return this.request;
        }
        public HttpServletResponse getResponse() {
            return this.response;
        }
        public Map<String, Cookie> getCookies() {
            Map<String, Cookie> map = new HashMap<String, Cookie>();
            Cookie[] cookies = this.request.getCookies();
            if(cookies != null)
                for(Cookie ck : cookies) {
                    map.put(ck.getName(), ck);
                }
            return map;
        }
    }

    WebFilter

      过滤器是实现会话共享的前提,我们在里面只是绑定一下请求对象。

    /**
     * HttpContext全局过滤器
     */
    public class ContextFilter implements Filter{
        public void init(FilterConfig filterConfig) throws ServletException {
        }
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            HttpServletRequest req = (HttpServletRequest)servletRequest;
            HttpServletResponse res = (HttpServletResponse)servletResponse;
            HttpContext.begin(req, res);
            filterChain.doFilter(servletRequest, servletResponse);
        }
        public void destroy() {
            HttpContext.get().end();
        }
    }

    使用

      现在,我们可以在一个普通的Java方法中,使用会话对象,如果我们做一个简单的Dispatcher,然后使用Response对象,那么一个后端框架便横空出世了!

    /**
    * 获得当前登录人员的凭证信息
    */
    public static String getId(){
        HttpSession session = HttpContext.get().getSession();
        Object obj = null;
        if (null != session){
            obj = session.getAttribute("USERID");
        }
        if (null == obj) {
            return null;
       }
       return obj.toString();
    }
    

     

    参考链接

    http://www.blackzs.com/archives/740

  • 相关阅读:
    HDU1164_Eddy's research I_素数筛选法
    HDU1213_How Many Tables
    HDU1049_数学水题
    HDU1286_找新朋友_筛选法
    HDU1128_Self Numbers_筛选法
    HDU3199_Hamming Problem_类似丑数
    HDU1297_Children’s Queue_递推题
    HDU1856_More is better
    HDU1397_Goldbach's Conjecture_素数筛选法
    HDU1272_并查集
  • 原文地址:https://www.cnblogs.com/MrSaver/p/11191028.html
Copyright © 2011-2022 走看看