引入:
一提到获取用户信息,大部分人想到的都是通过session来获取用户信息,当要想获取到session,就需要获取对应的request,这样,就会增加代码的耦合性,基于以上缺陷,我们可以使用ThreadLocal来将当前的用户信息存入一个session,需要的时候,直接从全局的ThreadLocal中取出来即可
接下来我们实践操作一波:
创建一个RequestHolder类,定义相关的set和get用户信息的方法
/**
* @author evan_qb
* @date 2018/8/29 15:09
*/
public class RequestHolder {
private static final ThreadLocal<SysUser> userHolder = new ThreadLocal<SysUser>();
private static final ThreadLocal<HttpServletRequest> 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
<filter>
<filter-name>loginFilter</filter-name>
<filter-class>cn.qblank.filter.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>loginFilter</filter-name>
<url-pattern>/sys/*</url-pattern>
<url-pattern>/admin/*</url-pattern>
</filter-mapping>
当我们需要用户的信息时,我们可以直接通过RequestHolder的方法直接获取