登录拦截器

文章介绍了如何在SpringMVC应用中使用登录拦截器进行token验证,并利用ThreadLocal处理线程间的数据。还涉及到了如何配置拦截器以拦截特定URL路径并排除某些操作。

目录

🎈1.登陆拦截器的使用

🎊2.ThreadLocal的简单使用

🎃3.登录拦截器拦截和放行配置 


1.登陆拦截器的使用

创建一个拦截器类,必须让其实现HandlerInterceptor接口

1.获取前端的token

2.判断token是否为空

3.若为空,返回json数据给前端

4.如不为空,校验解析token看是否与登陆者的一直,获取信息

5.将获取的信息,封装为UserDo对象

6.使用ThreadLocal传递信息

/**
 * 登录拦截器
 */
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {


    public static ThreadLocal<LoginUser> threadLocal=new ThreadLocal<>();

    /**
     * 登录校验
     *
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //获取前端的token
        String token = request.getHeader("token");
        if (token == null) {
            token = request.getParameter("token");
        }
        //判断token是否为空
        if (StringUtils.isNotBlank(token)) {
            //不为空,解密token
            Claims claims = JwtUtil.checkToken(token);
            if (claims == null) {
                //未登录,返回json数据
                CommonUtil.sendJsonMessage(response, CodeEnum.ACCOUNT_NO_LOGIN);
            }
            //解密登录对象的各种信息
            Long loginUserId = Long.valueOf(claims.get("id").toString());
            String loginUserHeadImage = String.valueOf(claims.get("head_image"));
            String loginUserMail = String.valueOf(claims.get("mail"));
            String loginUserName = String.valueOf(claims.get("name"));

            //将获取的登录对象的各种信息封装为loginUser,方便使用
            LoginUser loginUser = new LoginUser();
            loginUser.setName(loginUserName);
            loginUser.setMail(loginUserMail);
            loginUser.setHeadImg(loginUserHeadImage);
            loginUser.setId(loginUserId);

            //使用threadLocal传递用户信息
            threadLocal.set(loginUser);
            //返回true,
            return true;
        }

        CommonUtil.sendJsonMessage(response, CodeEnum.ACCOUNT_NO_LOGIN);
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}
  • 如果没有token,说明未登录,给前端返回json数据,调用指定的json转换方法
  /**
     * 返回json数据给前端
     *
     * @param response
     * @param object
     */
    public static void sendJsonMessage(HttpServletResponse response, Object object) {
        //Json序列化
        ObjectMapper objectMapper = new ObjectMapper();
        //设置HTTP响应的Content-Type头部
        response.setContentType("application/json; charset=utf-8");
        //获取获取输出流
        try (PrintWriter writer = response.getWriter()) {
            writer.print(objectMapper.writeValueAsString(object));
            response.flushBuffer();
            log.info("返回json成功");
        } catch (IOException e) {
            e.printStackTrace();
            log.warn("相应json数据异常:{}",e);
        }
    }
  • 思考了一个问题: threadLocal的使用属于单例模式中的饿汉式吗????

答案:不是的
大佬的回答:  在 LoginInterceptor 类中,threadLocal 被定义为一个静态变量,并且使用了饿汉式初始化,即在类加载的时候就完成了 ThreadLocal 对象的创建。然而,这并不意味着它是单例模式的实现。单例模式关注的是确保一个类只有一个实例,而 ThreadLocal 关注的是线程间的数据隔离。

2.ThreadLocal的简单使用

  • ThreadLocal 的主要目的是为每一个线程提供一个独立的变量副本,而不是确保整个应用程序只有一个实例。
  • ThreadLocal 的设计是为了解决多线程环境下的数据隔离问题。当多个线程共享同一个对象时,如果不加控制,线程间的数据可能会互相干扰。使用 ThreadLocal 可以让每个线程都拥有自己独立的数据副本,从而避免线程间的数据冲突。

总结:同个线程共享数据

3.登录拦截器拦截和放行配置 

  • 创建拦截器的配置类,一定要实现WebMvcConfiguer接口;
  • 重写addInterceptors()方法
  • 设置指定的拦截器,并添加相应的拦截路径即可
@Slf4j
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {

    /**
     * 创建loginInterceptor拦截器对象
     * @return
     */
    @Bean
    public LoginInterceptor loginInterceptor(){
        return new LoginInterceptor();
    }
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //指定拦截器
        registry.addInterceptor(loginInterceptor())
                //需要拦截的路径
                .addPathPatterns("/api/user/*/**","/api/address/*/**")
                //排除不需要拦截的路径
                .excludePathPatterns("/api/user/*/send_code","/api/user/*/captcha","/api/user/*/login","/api/user/*/register","/api/user/*/upload");
    }
}
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

会敲代码的小张

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值