java|java - springboot 添加自定义拦截器

某天深夜, 尼古拉斯.李四 突发奇想: 给自己白天写的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 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. 启动项目, 测试请求 java|java - springboot 添加自定义拦截器
文章图片

那如果需要添加多个拦截器呢
当然是再定义一个拦截器,添加进去
自定义第二个拦截器
@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); } }

启动项目, 测试请求 【java|java - springboot 添加自定义拦截器】java|java - springboot 添加自定义拦截器
文章图片

从打印的日志可以看出, 此时拦截器生效的顺序是和添加的顺序一致的
又一个风雨交加的深夜, 尼古拉斯.李四 夜不能寐, 觉得上面添加多个拦截器的方式可以调整一下, 方便隔壁老王.王五再新增自定义拦截器时, 只需要定义拦截器 不在需要需要去手动添加了
改造开始
新建一个带排序方法的抽象公共拦截器
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 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 interceptorMap = applicationContext.getBeansOfType(AbstractHandlerInterceptor.class); Set treeSet = new TreeSet((o1, o2) -> o1.sort() - o1.sort()); treeSet.addAll(interceptorMap.values()); for (AbstractHandlerInterceptor interceptor : treeSet) { registry.addInterceptor(interceptor); } } }

启动项目, 测试请求 java|java - springboot 添加自定义拦截器
文章图片

未完待续...

    推荐阅读