目录
spring中拦截器
过滤器跟拦截器的区别
HandlerInterceptor拦截器
拦截器工作原理
拦截器使用场景
定义拦截器
LoginInterceptor
注册拦截器
MethodInterceptor拦截器
方式一:继承 MethodInterceptor
方式二:基于注解的AspectJ方式
HandlerInterceptor拦截器与MethodInterceptor拦截器总结
spring中拦截器
在说拦截器之前,不得不说一下过滤器,有时候往往被这两个词搞的头大。
其实我们最先接触的就是过滤器;
你应该知道spring mvc的拦截器是只拦截controller而不拦截jsp,html 页面文件的,如果想要拦截那怎么办?
这就用到过滤器filter了,filter是在servlet前执行的,你也可以理解成过滤器中包含拦截器,一个请求过来 ,先进行过滤器处理,看程序是否受理该请求 。 过滤器放过后 , 程序中的拦截器进行处理 。
过滤器跟拦截器的区别
1、拦截器是基于java的反射机制的,而过滤器是基于函数回调(职责链)
2、过滤器依赖与servlet容器,而拦截器不依赖与servlet容器
3、拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用
4、拦截器可以访问action上下文、值栈里的对象,而过滤器不能
5、在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次
6、拦截器可以获取IOC容器中的各个bean,而过滤器不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。
7、过滤器属于Servlet,而拦截器属于springmvc
8、过滤器可以拦截所有请求,包括访问静态资源的请求,拦截器只能拦截action请求,即访问controller的请求。
(1)过滤器(Filter):当你有一堆东西的时候,你只希望选择符合你要求的某一些东西。定义这些要求的工具,就是过滤器。(理解:就是一堆字母中取一个B)
(2)拦截器(Interceptor):在一个流程正在进行的时候,你希望干预它的进展,甚至终止它进行,这是拦截器做的事情。(理解:就是一堆字母中,干预他,通过验证的少点,顺便干点别的东西)。
HandlerInterceptor拦截器
HandlerInterceptor是springMVC项目中的拦截器,它拦截的目标是请求的地址,比MethodInterceptor先执行。
实现一个HandlerInterceptor拦截器可以直接实现HandlerInterceptor接口,也可以继承HandlerInterceptorAdapter类。
这两种方法殊途同归,其实HandlerInterceptorAdapter也就是声明了HandlerInterceptor接口中所有方法的默认实现,而我们在继承他之后只需要重写必要的方法。
拦截器主要应用于登陆校验、权限验证、乱码解决、性能监控和异常处理等功能,Spring Boot 同样提供了拦截器功能
拦截器工作原理
一个拦截器,只有 preHandle 方法返回 true , postHandle 、 afterCompletion 才有可能被执行;如果 preHandle 方法返回 false ,则该拦截器的 postHandle 、 afterCompletion 必然不会被执行。拦截器不是Filter,却实现了Filter的功能,其原理在于:
所有的拦截器 (Interceptor) 和处理器 (Handler) 都注册在 HandlerMapping 中。
Spring MVC 中所有的请求都是由 DispatcherServlet 分发的。
当请求进入 DispatcherServlet.doDispatch() 时候,首先会得到处理该请求的 Handler (即 Controller 中对应的方法)以及所有拦截该请求的拦截器。拦截器就是在这里被调用开始工作的。
拦截器使用场景
拦截器本质上是面向切面编程(AOP),符合横切关注点的功能都可以放在拦截器中来实现,主要的应用场景包括:
-登录验证,判断用户是否登录。
-权限验证,判断用户是否有权限访问资源,如校验token
- 日志记录,记录请求操作日志(用户ip,访问时间等),以便统计请求访问量。
-处理cookie、本地化、国际化、主题等。
-性能监控,监控请求处理时长等。
定义拦截器
在 Spring Boot 中定义拦截器十分的简单,只需要创建一个拦截器类,并实现 HandlerInterceptor 接口即可。
HandlerInterceptor 接口中定义以下 3 个方法,如下表。
返回值类型 | 方法声明 | 描述 |
boolean | preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) | 该方法在控制器处理请求方法前执行,其返回值表示是否中断后续操作,返回 true 表示继续向下执行,返回 false 表示中断后续操作。 |
void | postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) | 该方法在控制器处理请求方法调用之后、解析视图之前执行,可以通过此方法对请求域中的模型和视图做进一步修改。 |
void | afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) | 该方法在视图渲染结束后执行,可以通过此方法实现资源清理、记录日志信息等工作。 |
LoginInterceptor
public class LoginInterceptor implements HandlerInterceptor {private final Logger logger = LoggerFactory.getLogger(LoginInterceptor.class);@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String requestURI = request.getRequestURI();log.info("请求的URI:",requestURI);String token = request.getParameter("token");if(StrUtil.isEmpty(token)){response.sendRedirect("/login");}return true;}
}
注册拦截器
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {......@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**") //拦截所有请求,包括静态资源文件.excludePathPatterns("/register", "/login", "/css/**", "/images/**", "/js/**"); //放行登录页,登陆操作,静态资源}
}
在指定拦截器拦截规则时,调用了两个方法,这两个方法的说明如下:
-
addPathPatterns:该方法用于指定拦截路径,例如拦截路径为“/**”,表示拦截所有请求,包括对静态资源的请求。
-
excludePathPatterns:该方法用于排除拦截路径,即指定不需要被拦截器拦截的请求。
MethodInterceptor拦截器
MethodInterceptor是AOP项目中的拦截器,它拦截的目标是方法,即使不是controller中的方法。实现MethodInterceptor拦截器大致也分为两种,一种是实现MethodInterceptor接口,另一种利用AspectJ的注解或配置。
方式一:继承 MethodInterceptor
public class MethodInvokeInterceptor implements MethodInterceptor { @Override public Object invoke(MethodInvocation methodInvocation) throws Throwable { System.out.println("before method invoke"); Object object = methodInvocation.proceed(); System.out.println("after method invoke"); return object; }
}
方式二:基于注解的AspectJ方式
@Component
@Aspect
public class AutoAspectJInterceptor { @Around("execution (* com.test.controller..*.*(..))") public Object around(ProceedingJoinPoint point) throws Throwable{ System.out.println("AutoAspectJInterceptor begin around"); Object object = point.proceed(); System.out.println("AutoAspectJInterceptor end around"); return object; } }
HandlerInterceptor拦截器与MethodInterceptor拦截器总结
HandlerInterceptor拦截的是请求地址,所以针对请求地址做一些验证、预处理等操作比较合适。当你需要统计请求的响应时间时MethodInterceptor将不太容易做到,因为它可能跨越很多方法或者只涉及到已经定义好的方法中一部分代码。MethodInterceptor利用的是AOP的实现机制,在对一些普通的方法上的拦截HandlerInterceptoer就无能为力了,这时候只能利用AOP的MethodInterceptor。