本文共 3984 字,大约阅读时间需要 13 分钟。
引入:
一提到获取用户信息,大部分人想到的都是通过session来获取用户信息,当要想获取到session,就需要获取对应的request,这样,就会增加代码的耦合性,基于以上缺陷,我们可以使用ThreadLocal来将当前的用户信息存入一个session,需要的时候,直接从全局的ThreadLocal中取出来即可
接下来我们实践操作一波:
创建一个RequestHolder类,定义相关的set和get用户信息的方法
/** * @author evan_qb * @date 2018/8/29 15:09 */public class RequestHolder { private static final ThreadLocaluserHolder = new ThreadLocal (); private static final ThreadLocal requestHolder = new ThreadLocal<>(); public static void add(SysUser sysUser){ userHolder.set(sysUser); } public static void add(HttpServletRequest request){ requestHolder.set(request); } public static SysUser getCurrentUser(){ return userHolder.get(); } public static HttpServletRequest getCurrentRequest(){ return requestHolder.get(); } public static void remove(){ userHolder.remove(); requestHolder.remove(); }}
然后定义一个拦截器用于移除对应的ThreadLocal对象,防止内存泄漏
public class HttpInterceptor extends HandlerInterceptorAdapter { private static final String START_TIME = "requestStartTime"; /** * 处理前 * @param request * @param response * @param handler * @return * @throws Exception */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String url = request.getRequestURI().toString(); Map parameterMap = request.getParameterMap(); log.info("request start url:{},params:{}",url,JsonMapper.object2String(parameterMap)); long startTime = System.currentTimeMillis(); request.setAttribute(START_TIME,startTime); return true; } /** * 处理后调用(正常) * @param request * @param response * @param handler * @param modelAndView * @throws Exception */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { /*String url = request.getRequestURI().toString(); Map parameterMap = request.getParameterMap(); log.info("request finish url:{},params:{}",url,JsonMapper.object2String(parameterMap));*/ } /** * 处理后调用(任何情况) * @param request * @param response * @param handler * @param ex * @throws Exception */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { String url = request.getRequestURI().toString(); long start = (long) request.getAttribute(START_TIME); long end = System.currentTimeMillis(); log.info("request exception url:{},cost:{}ms",url,end - start); removeThreadLocalInfo(); } /** * 移除信息 */ public void removeThreadLocalInfo(){ RequestHolder.remove(); }}
这时,我们需要利用一个过滤器LoginFilter,将每次的请求,和每次的用户信息存入ThreadLocal中
/** * @author evan_qb * @date 2018/8/29 15:29 */public class LoginFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse resp = (HttpServletResponse) response; String path = req.getServletPath(); SysUser sysUser = (SysUser) WebUtils.getSessionAttribute(req,"user"); if (sysUser == null){ resp.sendRedirect("/signin.jsp"); return; } RequestHolder.add(sysUser); RequestHolder.add(req); chain.doFilter(request,response); return; } @Override public void destroy() { }}
同时在web.xml中配置好LoginFilter
loginFilter cn.qblank.filter.LoginFilter loginFilter /sys/* /admin/*
当我们需要用户的信息时,我们可以直接通过RequestHolder的方法直接获取