springMVC自定义拦截器、ThreadLocal

SpringMVC执行流程

  1. 用户发起请求到dispatchServlet
  2. dispatchServlet根据请求路径到HandleMapping(映射器)中查询具体的handler(处理器)
  3. handlerMapping返回handleExecutionchain(具体的handler和拦截器集合)
  4. dispatchServlet根据handler的实现方式调用对应的handlerAdapter(适配器)
  5. handlerAdapter调用具体的handler(处理业务逻辑)
  6. handler返回处理结果(modelandview:数据模型和视图名称)给handlerAdapter
  7. 返回modelandview给dispatchservlet
  8. dispatchservlert根据视图名称到viewresolver(视图解析器)
  9. 返回具体的视图给dispatcherservlet
  10. 渲染视图
  11. 返回渲染后的视图给dispatcherservlet
  12. dispatcherservlet响应用户请求

自定义拦截器

此拦截器的功能为:拦截用户请求,从请求中获取cookie中的token,对token进行解析,获取token中用户的信息,对获得的信息通过ThreadLocal进行传递,保证线程安全,并在拦截器的后置处理中释放线程

1.编写拦截器类,继承HandlerInterceptorAdapter类,重写preHandle(),并加入到Spring容器中

@Component
public class LoginInterceptor extends HandlerInterceptorAdapter {
	
    private static final ThreadLocal<UserInfo> THREAD_LOCAL = new ThreadLocal<>();
    @Autowired
    private JwtProperties jwtProperties;
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 获取cookie信息
        String token = CookieUtils.getCookieValue(request, jwtProperties.getCookieName());
        String userKey = CookieUtils.getCookieValue(request, jwtProperties.getUserKeyName());

        // 如果都为空,设置userKey。
        if (StringUtils.isBlank(token) && StringUtils.isBlank(userKey)){
            userKey = UUID.randomUUID().toString();
            CookieUtils.setCookie(request, response, jwtProperties.getUserKeyName(), userKey, jwtProperties.getExpire());
        }

        // 不管有没有登录都要设置userKey
        UserInfo userInfo = new UserInfo();
        userInfo.setUserKey(userKey);

        // token不为空,解析token
        if (StringUtils.isNotBlank(token)){
            Map<String, Object> map = JwtUtils.getInfoFromToken(token, jwtProperties.getPublicKey());
            if (!CollectionUtils.isEmpty(map)) {
                userInfo.setId(new Long(map.get("id").toString()));
            }
        }
        // 保存到threadlocal
        THREAD_LOCAL.set(userInfo);
        // 如果token不为空,
        return true;
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        THREAD_LOCAL.remove();
    }
    //对外提供静态方法,获取ThreadLocal
    public static UserInfo getUserInfo(){
        return THREAD_LOCAL.get();
    }
}

注意:

  • 这里我们使用了ThreadLocal来存储查询到的用户信息,线程内共享,对外提供get方法,因此请求到达Controller后可以共享User
  • 并且对外提供了静态的方法:getUserInfo()来获取User信息
  • 在完成逻辑任务后,要进行释放,否则会内存泄漏

2.配置拦截器

@Configuration
public class MvcConfig implements WebMvcConfigurer {

    @Autowired
    private LoginInterceptor loginInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor).addPathPatterns("/**");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值