A-A+

使用ThreadLocal共享HttpSession

2016年06月15日 技术, 默认 暂无评论 阅读 5,824 次

之前在使用.NET进行Web开发时,可以通过HttpContext.User在应用的任何层面获取当前登录的用户信息,而在使用Java进行Web开发时,最开始接触的就是SpringMVC,可是看到的都是形如下面的代码去获取Session中的用户信息。

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

上面的代码没什么错误,只是看起来很别扭。最开始我以为没什么比较简单的办法来进行封装,直到前些日子开发权限管理系统的时候在这里卡壳了,逼着我去翻阅资料解决这个问题,于是找了几个开源的项目看了看源码,在搜索引擎上大海捞了个针,最后发现其实Java是有解决办法的,只不过需要自己封装一下,同样可以达到.NET下的那种效果。

首先,需要一个封装类。

  1. import javax.servlet.ServletContext;
  2. import javax.servlet.http.Cookie;
  3. import javax.servlet.http.HttpServletRequest;
  4. import javax.servlet.http.HttpServletResponse;
  5. import javax.servlet.http.HttpSession;
  6. import java.util.HashMap;
  7. import java.util.Map;
  8. public class HttpContext {
  9.     private HttpServletRequest request;
  10.     private HttpServletResponse response;
  11.     private final static ThreadLocal<HttpContext> contextContainer = new ThreadLocal<HttpContext>();
  12.     /**
  13.      * 初始化
  14.      */
  15.     public static HttpContext begin(HttpServletRequest req, HttpServletResponse res) {
  16.         HttpContext context = new HttpContext();
  17.         context.request = req;
  18.         context.response = res;
  19.         contextContainer.set(context);
  20.         return context;
  21.     }
  22.     public static HttpContext get(){
  23.         return contextContainer.get();
  24.     }
  25.     /**
  26.      * 销毁
  27.      */
  28.     public void end() {
  29.         this.request = null;
  30.         this.response = null;
  31.         contextContainer.remove();
  32.     }
  33.     public ServletContext getContext() {
  34.         return this.request.getServletContext();
  35.     }
  36.     public HttpSession getSession() {
  37.         return this.request.getSession(false);
  38.     }
  39.     public HttpServletRequest getRequest() {
  40.         return this.request;
  41.     }
  42.     public HttpServletResponse getResponse() {
  43.         return this.response;
  44.     }
  45.     public Map<String, Cookie> getCookies() {
  46.         Map<String, Cookie> map = new HashMap<String, Cookie>();
  47.         Cookie[] cookies = this.request.getCookies();
  48.         if(cookies != null)
  49.             for(Cookie ck : cookies) {
  50.                 map.put(ck.getName(), ck);
  51.             }
  52.         return map;
  53.     }
  54. }

然后,需要一个Filter。

  1. import javax.servlet.*;
  2. import javax.servlet.http.HttpServletRequest;
  3. import javax.servlet.http.HttpServletResponse;
  4. import java.io.IOException;
  5. /**
  6.  * HttpContext全局过滤器
  7.  */
  8. public class ContextFilter implements Filter{
  9.     public void init(FilterConfig filterConfig) throws ServletException {
  10.     }
  11.     public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  12.         HttpServletRequest req = (HttpServletRequest)servletRequest;
  13.         HttpServletResponse res = (HttpServletResponse)servletResponse;
  14.         HttpContext.begin(req, res);
  15.         filterChain.doFilter(servletRequest, servletResponse);
  16.     }
  17.     public void destroy() {
  18.         HttpContext.get().end();
  19.     }
  20. }

最后,就可以直接使用了,比如获取Session内的人员ID。

  1. /**
  2. * 获得当前登录人员的凭证信息
  3. */
  4. public static String getId(){
  5.     HttpSession session = HttpContext.get().getSession();
  6.     Object obj = null;
  7.     if (null != session){
  8.         obj = session.getAttribute("USERID");
  9.     }
  10.     if (null == obj) {
  11.         return null;
  12.    }
  13.    return obj.toString();
  14. }

这个方法可以在任何位置调用,比如我在做权限管理系统时,就在自定义FileSqlManager时就获取了当前登录人员的ID,然后通过该人员的权限过滤出了SQL语句的条件,进而完成了SQL语句的构造,可以参见基于Nutz.Dao的数据权限管理的实现2

相关的资料可以查看:

OSChina 中一个非常重要的类——RequestContext

ThreadLocal 那点事儿

给我留言

Copyright © 字痕随行 保留所有权利.   Theme  Ality

用户登录

分享到: