前言:
Spring Boot 中的过滤器(Filter)、拦截器(Interceptor)和 AOP(面向切面编程)都是处理请求的常用技术,但它们在处理请求的时机、范围和方式上有所不同。下面详解分别介绍:
执行顺序:过滤器->拦截器->aop
1. 过滤器(Filter)
过滤器是一个标准的Java规范,它在请求进入Servlet之前或者响应离开Servlet之后对请求或响应进行拦截处理。过滤器可以应用于整个Web应用程序,并且可以对请求和响应进行预处理或后处理;例如可以提前过滤一些信息或者提前设置一些参数,再或者过滤一些非法url,过滤敏感词。
原理:依赖Servlet容器,基于函数回调实现。
应用场景:
-
日志记录
-
登录校验,权限校验
-
防御XSS攻击
-
请求内容修改
-
响应内容修改
使用步骤:
@Component
@WebFilter
public class TestFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("TestFilter过滤器------>初始化先执行");}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {// 在请求处理之前进行调用(如登录检查)System.out.println("TestFilter过滤器------>进入web容器之前");// 继续过滤器链中的下一个过滤器chain.doFilter(request, response);// 在请求处理之后进行调用(如日志记录)System.out.println("TestFilter过滤器------>进入web容器之前");}@Overridepublic void destroy() {System.out.println("TestFilter过滤器------>最后执行");}
}
2. 拦截器(Interceptor)
拦截器是基于Spring框架,用于在请求的前后进行拦截处理。拦截器只作用于Spring管理的Bean,因此它不能拦截静态资源或者非Spring MVC处理的请求。
原理:依赖于Spring框架,是aop的一种表现,基于Java的动态代理实现的。
应用场景:
-
登录校验,权限验证,签名验证
-
日志记录
-
请求参数修改
-
响应结果修改
使用步骤:
- 声明拦截器的类:1.通过实现 HandlerInterceptor接口;2,继承HandlerInterceptorAdapter类; 实现preHandle、postHandle和afterCompletion方法。
@Component
public class TestInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {// 在请求处理之前进行调用(如权限检查)System.out.println("TestInterceptor拦截器在请求处理之前进行调用");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {// 请求处理之后进行调用,但在视图被渲染之前(如修改模型和视图)System.out.println("TestInterceptor拦截器请求处理之后进行调用");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {// 在整个请求结束之后被调用(如日志记录)System.out.println("TestInterceptor拦截器在整个请求结束之后被调用");}
}
- 通过配置类配置拦截器:通过实现WebMvcConfigurer接口,实现addInterceptors方法
@Configuration
public class TestWebConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new TestInterceptor()).addPathPatterns("/**");}}
3. AOP(面向切面编程)
AOP是一种编程范式,它允许你在不修改源代码的情况下,对程序的特定部分添加额外的功能。在Spring中,AOP是通过动态代理机制实现的。
不懂的可以看看这篇:掌握SpringBoot之AOP如此简单-CSDN博客
应用场景:
- 事务管理
- 日志记录
- 性能监控
- 安全控制
使用步骤:
日志记录:
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {//标题String title() default "";//业务类型int businessType() default 0;//操作类型int operatorType() default 0;}
@Aspect
@Component
public class LogAspect {@Before("@annotation(controllerLog)")public void boBefore(JoinPoint joinPoint, Log controllerLog) {// 在方法执行之前进行调用System.out.println("在controller方法执行之前进行调用: " + joinPoint.getSignature());}@AfterReturning(pointcut = "@annotation(controllerLog)",returning = "result")public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object result) {// 在方法正常返回之后进行调用System.out.println("在controller方法执行正常返回之后进行调用: " + result);}@AfterThrowing(value = "@annotation(controllerLog)",throwing = "e")public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e) {System.out.println("目标方法中抛出的异常: " + e);}
}
测试:
@RestController
@RequestMapping("/test")
public class TestController {@Log(title = "测试查询", operatorType = "query", businessType = "other")@GetMapping("/test")public String test() {return "hello";}
}
执行顺序:
简单理解:类似队列先进先出原则。
TestFilter过滤器------>初始化先执行(filter初始化)
应用程序启动完成
TestFilter过滤器------>进入web容器之前(filter)TestInterceptor拦截器在请求处理之前进行调用aop->在controller方法执行之前进行调用: String com.qzh.demo.filter.TestController.test()
aop->在controller方法执行正常返回之后进行调用: helloTestInterceptor拦截器请求处理之后进行调用TestInterceptor拦截器在整个请求结束之后被调用TestFilter过滤器------>进入web容器之前 (filter)
TestFilter过滤器------>最后执行(filter销毁)
区别:
- 范围:过滤器可以应用于整个Web应用程序,拦截器只作用于Spring MVC处理的请求,而AOP可以应用于整个Spring应用上下文。
- 时机:过滤器在请求进入Servlet之前或响应离开Servlet之后调用,拦截器在请求到达Controller前后调用,AOP可以在方法的多个不同点(如方法执行前后、抛出异常时)调用。
- 实现方式:过滤器是基于Java规范实现的,拦截器是基于Spring的拦截器接口实现的,而AOP是基于Spring的代理机制实现的。
在选择使用过滤器、拦截器还是AOP时,需要根据具体的业务需求和处理范围来决定。例如,如果需要对所有请求进行日志记录,可以使用过滤器;如果需要在请求处理前后进行权限检查,可以使用拦截器;如果需要在方法执行前后进行日志记录或事务管理,可以使用AOP。