• 通过实现HandlerInterceptor接口实现一个拦截器


    1. 简介

    web应用开发中,拦截器的应用场景非常广泛,主要用于:

    1. 登陆验证:提取request中请求头携带的token信息;
    2. 鉴权:判断该用户是否有权限访问某个资源
    3. 日志记录:记录该handler的入 和 出
    4. 性能监控、通用行为等等一些其它的操作。

    2. spring中使用拦截器的方式

    spring为我们提供了一个接口:HandlerInterceptor,该接口提供了三个方法:

    default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            return true;
    }
    
    default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
    }
    
    default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    通过名字不难理解每个方法其中的意思:
    preHandler() 方法是调用我们程序中写的controller之前执行的;
    postHander() 方法是controller执行完毕之后,spring会调用该框架;
    afterCompletion() 方法是视图渲染完毕之后被执行。

    preHander()方法返回true时,表示可以进入咱们开发的handler中,否则不能进入。例如,在preHander中进行鉴权案例:

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String authHeader = AuthHeaderUtils.getBearerToken();
        String tenantId = AuthHeaderUtils.getTenantId();
        String userId = AuthHeaderUtils.getUserId();
    
        // 未携带token
        if (StringUtils.isBlank(authHeader)) {
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, UNAUTHORIZED);
            return false;
        }
        AuthService authService = SpringUtil.getBean(AuthService.class);
        // 校验token
        TokenInfoDTO tokenInfoDTO = authService.checkToken(authHeader);
        if (Objects.isNull(tokenInfoDTO)) {
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, UNAUTHORIZED);
            return false;
        }
        // 是否需要刷新token
        if (tokenInfoDTO.getRefresh()) {
            authHeader = authService.refreshToken(tenantId, userId);
        }
        // 获取用户
        UserDTO user = authService.getUser(authHeader);
        if (Objects.isNull(user)) {
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, UNAUTHORIZED);
            return false;
        }
        // 将用户信息set到threadLocal中。
        VBPAppContext.setUserObj(user);
        
        response.setHeader(HEADER_AUTHORIZATION, authHeader);
        return HandlerInterceptor.super.preHandle(request, response, handler);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    上述代码中通过鉴权的用户将会被set到threadLocal中,虽然ThreadLocal中通过实现WeakReference接口进行弱引用防止内存泄漏,但是未被有效释放的对象仍然会占用内存,因此在一整个请求结束之后,最好及时remove一下,即:在拦截器的afterCompletion()方法中及时调用remove:

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        VBPAppContext.removeUserObj();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
  • 相关阅读:
    PaddleClas学习2——使用PPLCNet模型对车辆朝向进行识别(python)
    JavaScript-----运算符与流程控制
    python -pandas -处理excel合并单元格问题
    为什么在listview上只显示一行,不论list有几个数据,都只显示第一行的
    『忘了再学』Shell流程控制 — 34、if条件判断语句(二)
    Linux下的打包(tar)、压缩(gzip / bzip2)
    【探索C++】输入输出
    java计算机毕业设计基于springboot企业人事工资管理系统
    关于 HTTPS 和 SSL
    (附源码)php疫情上报管理系统 毕业设计 170948
  • 原文地址:https://blog.csdn.net/wangheng673/article/details/133170388