1:Interceptor介绍
拦截器(Interceptor)同 Filter 过滤器一样,它俩都是面向切面编程——AOP 的具体实现
你可以使用 Interceptor 来执行某些任务,
例如在 Controller 处理请求之前编写日志,添加或更新配置......
在 Spring中,当请求发送到 Controller 时,在被Controller处理之前,它必须经过 Interceptors(0或更多)。
Spring Interceptor是一个非常类似于Servlet Filter 的概念 。
2:对于过滤器和拦截器 以及监听器 的区别(应用场景)
过滤器(Filter):当你有一堆东西的时候,你只希望选择符合你要求的某一些东西。
拦截器(Interceptor):在一个流程正在进行的时候,你希望干预它的进展,甚至终止它进行。
监听器(Listener):当一个事件发生的时候,你希望获得这个事件发生的详细信息,而并不想干预这个事件本身的进程。
过滤器:只想要在一堆黑白芝麻 里面 选红芝麻! (不应该改变对象,如把黑芝麻,白芝麻变红芝麻)
拦截器:把水流变小点!把鱼都拦住!顺便发个电!(改变对象,对这个对象有读写的权限)
监听器:上面是个水利工程,其实发电的原理是这样的。。(只是看看这个对象的过程,获取这个事件发生的详细信息)
3:对于过滤器和拦截器的区别(本质区别)
4:自定义 Interceptor
实现HandlerInterceptor类里面的三个方法即可
preHandle 返回为true或者false 如果为true则代码能继续往后走
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
@Nullable Object handler)
public void postHandle(HttpServletRequest request,
HttpServletResponse response,
@Nullable Object handler,
ModelAndView modelAndView)
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
@Nullable Object handler,
Exception ex)
5:拦截器的使用
分别实现了三个拦截器
1:LogInterceptor (日志拦截器)(打印日志)
2:OldLoginInterceptor(旧登录接口拦截器)(用于重定向旧登录接口)
3:AdminInterceptor(新登录接口拦截器)
日志 打印出 请求路径 请求开始与结束时间
重定向 废弃旧接口跳转到新接口
三个拦截器的逻辑图
6:如何配置拦截器
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// LogInterceptor apply to all URLs.
registry.addInterceptor(new LogInterceptor());
// Old Login url, no longer use.
// Use OldURLInterceptor to redirect to a new URL.
registry.addInterceptor(new OldLoginInterceptor())
.addPathPatterns("/admin/oldLogin");
// This interceptor apply to URL like /admin/*
// Exclude /admin/oldLogin
// 避免 /admin/* 再次打印 /admin/oldLogin的日志
registry.addInterceptor(new AdminInterceptor())
.addPathPatterns("/admin/*")
.excludePathPatterns("/admin/oldLogin");
}
}
7:单个流程总结
registry:配置进入哪个拦截器 哪个路径允许进入拦截器
拦截器:preHandle:进入拦截器先执行 (可能重定向) 返回ture 和 false
controller:1:preHandle 返回为true
2:接口请求路径(包括preHandle重定向)
满足这两个条件时执行
拦截器:postHandle:仅跟着 controller
view:拦截器的postHandle执行完后 会跳到一个前端页面(html)
拦截器:afterCompletion:最后 只要 preHandle返回为ture
不管 postHandle 和 controller response逻辑链是否执行
8:多个拦截器的执行顺序
registry.addInterceptor(new HandlerInterceptor1());
registry.addInterceptor(new HandlerInterceptor2());
HandlerInterceptor1 先注册
HandlerInterceptor2 后注册
1: preHandle执行顺序和拦截器放置顺序一致;
postHandle、afterCompletion执行顺序和拦截器放置顺序相反
2: 逻辑串行
HandlerInterceptor1 的 preHandle返回为 false 后续无法走下去
HandlerInterceptor2 的 preHandle返回为 false 后续无法走下去
9:返回处理
1:返回跳转到html 运用上述的方式即可
2:返回 JSONString 在Controller层的方法上添加 @RequestBody注解
10:配合拦截件配合自定义注解 存储请求日志
//1:自定义注解
@Target({ ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface InterceptorAnnotationLog {
boolean booleanValue() default true;
//2:在相关方法使用该注解
@InterceptorAnnotationLog(booleanValue=true)
//3:在拦截器添加以下代码 通过反射的方法 判断方法中是否存在该注解
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
System.out.println("\n-------- AnnotationLogInterceptor.preHandle --- ");
if (handler instanceof HandlerMethod) {
HandlerMethod method = (HandlerMethod) handler;
InterceptorAnnotationLog interceptorAnnotationLog = method.getMethodAnnotation(InterceptorAnnotationLog.class);
// 判断 存在interceptorIsStringResult注解 同时 注解的booleanValue值为true时 存放信息到MongoDB
if ((interceptorAnnotationLog != null && interceptorAnnotationLog.booleanValue())) {
try {
log.info("//待完成 从request获取信息 并存入 MongoDB");
} catch (Exception e) {
log.info("获取请求信息 并存入MongoDB异常 "+e.getMessage(),e);
}
}
}
return true;
}
项目连接
请配合项目代码食用效果更佳:
项目地址:
https://github.com/hesuijin/hesuijin-study-project
Git下载地址:
https://github.com.cnpmjs.org/hesuijin/hesuijin-study-project.git
springboot-filter-interceptor项目模块下 Interceptor包