java - springboot 添加自定义拦截器

stone
某天深夜, 尼古拉斯.李四 突发奇想: 给自己白天写的10个接口都打印下请求日志, 日志内容也很简单, 就打印下接口地址和请求参数就行了
但是这个打印请求日志的代码又不想在10个接口里都写上一遍, 咋办呢?
尼古拉斯.李四开始冥思苦想,左思右想 springmvc的拦截器不就可以嘛

1. 自定义拦截器

实现HandlerInteceptor接口

HandlerInterceptor接口中有三个方法

preHandle : 在进入Controller之前执行。返回值为Boolean类型,如果返回false,表示拦截请求,不再向下执行,如果返回true,表示放行,程序继续向下执行(如果后面没有其他Interceptor,就会执行controller方法)。所以此方法可对请求进行判断,决定程序是否继续执行,或者进行一些初始化操作及对请求进行预处理
postHandle: 在Controller方法调用完后, 在DispatcherServlet 进行视图返回渲染之前被调用, 可以在这个方法中对Controller 处理之后的ModelAndView 对象进行操作,比如说设置cookie,返回给前端
afterCompletion: 在整个请求结束之后执行,也就是在DispatcherServlet 渲染了对应的视图之后执行, 所以该方法适合进行一些资源清理

@Component
@Slf4j
public class LogRequestUriInterceptor implements HandlerInterceptor {

     @Override
     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
         String requestURI = request.getRequestURI();
         Map<String, String[]> parameterMap = request.getParameterMap();
         log.info("==收到请求, requestURI: {} , queryString: {} ==", requestURI, JsonUtil.toJsonDisableHtmlEscaping(parameterMap));
         return true;
    }

}

2. 添加拦截器 (有两种方式, 这里选择第二种)

一. extends WebMvcConfigurerAdapter (spring5.0开始废弃)

WebMvcConfigurerAdapter

@Configuration
public class TestMvcConfigure extends WebMvcConfigurerAdapter {

    @Resource
    private LogRequestUriInterceptor logRequestUriInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(logRequestUriInterceptor);
    }
}

二. implements WebMvcConfigurer

@Configuration
public class WebMvcConfigure implements WebMvcConfigurer {

    @Resource
    private LogRequestUriInterceptor logRequestUriInterceptor;


    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(logRequestUriInterceptor);
    }

3. 启动项目, 测试请求

image.png


那如果需要添加多个拦截器呢
当然是再定义一个拦截器,添加进去

自定义第二个拦截器

@Component
@Slf4j
public class RecordLogInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("==自义定拦截器2, uri: {} ,queryString: {} ==", request.getRequestURI(), JsonUtil.toJsonDisableHtmlEscaping(request.getParameterMap()));
        return true;
    }
}

添加第二个拦截器

@Configuration
public class WebMvcConfigure implements WebMvcConfigurer {

    @Resource
    private LogRequestUriInterceptor logRequestUriInterceptor;
    @Resource
    private RecordLogInterceptor recordLogInterceptor;


    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(logRequestUriInterceptor);
        registry.addInterceptor(recordLogInterceptor);
    }
}

启动项目, 测试请求

image.png

从打印的日志可以看出, 此时拦截器生效的顺序是和添加的顺序一致的


又一个风雨交加的深夜, 尼古拉斯.李四 夜不能寐, 觉得上面添加多个拦截器的方式可以调整一下, 方便隔壁老王.王五再新增自定义拦截器时, 只需要定义拦截器 不在需要需要去手动添加了
改造开始

新建一个带排序方法的抽象公共拦截器

public abstract class AbstractHandlerInterceptor implements HandlerInterceptor {
     /**
     * 有了这个方法, 就可以按顺序自动添加拦截器
     * @return
     */
    abstract Integer sort();

}

拦截器1 改实现为继承

@Component
@Slf4j
public class LogRequestUriInterceptor extends AbstractHandlerInterceptor {



     @Override
     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
         String requestURI = request.getRequestURI();
         Map<String, String[]> parameterMap = request.getParameterMap();
         log.info("==自定义拦截器1, requestURI: {} , queryString: {} ==", requestURI, JsonUtil.toJsonDisableHtmlEscaping(parameterMap));
         return true;
    }

    @Override
    Integer sort() {
        return 1;
    }
}

拦截器2改实现为继承

@Component
@Slf4j
public class RecordLogInterceptor extends AbstractHandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("==自义定拦截器2, uri: {} ,queryString: {} ==", request.getRequestURI(), JsonUtil.toJsonDisableHtmlEscaping(request.getParameterMap()));
        return true;
    }

    @Override
    Integer sort() {
        return 2;
    }
}

添加拦截器的逻辑进行调整

@Configuration
public class WebMvcConfigure implements WebMvcConfigurer {

    @Resource
    private ApplicationContext applicationContext;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        Map<String, AbstractHandlerInterceptor> interceptorMap = applicationContext.getBeansOfType(AbstractHandlerInterceptor.class);
        Set<AbstractHandlerInterceptor> treeSet = new TreeSet<AbstractHandlerInterceptor>((o1, o2) -> o1.sort() - o1.sort());
        treeSet.addAll(interceptorMap.values());
        for (AbstractHandlerInterceptor interceptor : treeSet) {
            registry.addInterceptor(interceptor);
        }
    }
}

启动项目, 测试请求

image.png

未完待续...
阅读 153
56 声望
0 粉丝
0 条评论
你知道吗?

56 声望
0 粉丝
文章目录
宣传栏