某天深夜, 尼古拉斯.李四 突发奇想: 给自己白天写的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. 启动项目, 测试请求
那如果需要添加多个拦截器呢
当然是再定义一个拦截器,添加进去
自定义第二个拦截器
@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);
}
}
启动项目, 测试请求
从打印的日志可以看出, 此时拦截器生效的顺序是和添加的顺序一致的
又一个风雨交加的深夜, 尼古拉斯.李四 夜不能寐, 觉得上面添加多个拦截器的方式可以调整一下, 方便隔壁老王.王五再新增自定义拦截器时, 只需要定义拦截器 不在需要需要去手动添加了
改造开始
新建一个带排序方法的抽象公共拦截器
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);
}
}
}
启动项目, 测试请求
未完待续...