基于HandlerInterceptorAdapter自定义springBoot拦截器

1.应用场景分析

自定义拦截器可以应用于多种场景,可以说是springBoot开发的必备技能

  • 日志记录: 可以记录接口的访问信息,访问监控
  • 权限检测: 比如在使用jwt作为权限认证的时候可以配置拦截器解析jwt信息
  • 多租户信息提取: 关于多租户后期会有相关文章,这里只说一下在请求时可以配置拦截器解析token中的租户信息封装到线程中或者session

2.结构分析

在分析HandlerInterceptorAdapter之前我们先来看一下HandlerInterceptorAdapter的类结构图

在这里插入图片描述
HandlerInterceptorAdapter的方法:
在这里插入图片描述

3.HandlerInterceptorAdapter中的方法作用

3.1 preHandle:

在方法被调用前执行。在该方法中可以做类似校验的功能。如果返回true,则继续调用下一个拦截器。如果返回false,则中断执行,也就是说我们想调用的方法 不会被执
方法中参数的含义:
HttpServletRequest request——包含所有请求的内容;

HttpServletResponse response——包含所有响应的内容;

Object handler——表示被拦截的请求的目标对象。

3.2 postHandle:

在方法执行后调用。

3.3 afterCompletion:

在整个请求处理完毕后进行回调,也就是说视图渲染完毕或者调用方已经拿到响应。

4. 实例应用

在此我们模拟一个场景,在多租户系统中,在请求到达后端的时候我们可以自定义一个拦截器,拿到此次请求中的jwt的租户信息。
在此我们先模拟封装一个租户信息存储容器:


/**
 *
 * @author jie
 */
public class BaseContextHandler {

    private static final ThreadLocal<Map<String, String>> THREAD_LOCAL = new ThreadLocal<>();

    public static void set(String key, Object value) {
        Map<String, String> map = getLocalMap();
        map.put(key, value == null ? "" : value.toString());
    }

    public static <T> T get(String key) {
        Map<String, String> map = getLocalMap();
        return  map.get(key);
    }
    
    public static void remove() {
        if (THREAD_LOCAL != null) {
            THREAD_LOCAL.remove();
        }
    }
}

租户信息拦截器:

/**
 * 租户信息解析器
 * 用于将请求头中的租户编码和数据库名 封装到当前请求的线程变量中
 *
 * @author jie
 * @date 2019-06-20 22:22
 */
@Slf4j
@AllArgsConstructor
public class TenantContextHandlerInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (!(handler instanceof HandlerMethod)) {
            return super.preHandle(request, response, handler);
        }
        BaseContextHandler.setTenant("Tenant"this.getHeader(request,"Tenant" ));
        return super.preHandle(request, response, handler);
    }

    private String getHeader(HttpServletRequest request, String name) {
        String value = request.getHeader(name);
        if (value == null || value .length() == 0) {
            value = request.getParameter(name);
        }
        if (value == null || value .length() == 0) {
            return "";
        }
        return value;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        BaseContextHandler.remove();
        super.afterCompletion(request, response, handler, ex);
    }
}

这里是在请求到达服务器后从请求头中获取前端设置好的租户信息,取出租户信息存入ThreadLocal中,在程序处理完请求后将ThreadLocal中的租户信息清除。在程序处理中如果要用到租户信息就从线程的ThreadLocal中获取租户信息。

/**
 * 
 * @author jie
 */
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new TenantContextHandlerInterceptor())
                //所有请求都被拦截
                .addPathPatterns("/**")

    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值