SpringBoot中监听器、过滤器、拦截器和AOP详解
在构建 Spring Boot 应用程序时,监听器(Listener)、过滤器(Filter)、拦截器(Interceptor)和面向切面编程(AOP)是四种常用的机制,它们各自有不同的用途和执行时机。本文将详细介绍这四种技术的执行时机和区别,并附上示例代码帮助理解。
1. 监听器(Listener)
定义与特点
- 定义:监听器用于监听特定事件的发生,并在这些事件发生时执行相应的逻辑。
- 特点:
- 事件驱动:监听器通过订阅特定的事件,在事件发生时执行预定的逻辑。
- 解耦:监听器将事件处理逻辑从业务逻辑中分离出来,提高了代码的模块化和可维护性。
- 灵活性:可以通过配置文件或注解的方式轻松地添加或移除监听器。
常见的监听器
- ServletContextListener:监听整个 Web 应用程序的启动和关闭。
- ServletRequestListener:监听每个 HTTP 请求的开始和结束。
- HttpSessionListener:监听会话的创建和销毁。
- SpringApplicationRunListener:监听 Spring Boot 应用程序的启动过程。
示例代码
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;@WebListener
public class MyContextListener implements ServletContextListener {@Overridepublic void contextInitialized(ServletContextEvent sce) {System.out.println("Application started");// 初始化操作,例如加载配置文件}@Overridepublic void contextDestroyed(ServletContextEvent sce) {System.out.println("Application stopped");// 清理操作,例如释放资源}
}
2. 过滤器(Filter)
定义与特点
- 定义:过滤器是 Java Servlet API 的一部分,用于在请求到达目标资源(如 Servlet 或 JSP 页面)之前或在响应从目标资源返回到客户端之后进行预处理或后处理。
- 特点:
- 生命周期管理:过滤器具有初始化(
init
)、过滤(doFilter
)和销毁(destroy
)的方法,这些方法分别在过滤器创建、每次请求处理和服务器关闭时调用。 - 执行顺序:过滤器的执行顺序是由部署描述符(如
web.xml
)或等效的 Java 配置类中定义的过滤器映射所决定的。 - 跨容器:过滤器可以在任何实现了 Servlet 规范的容器中工作,这意味着它们可以用于任何基于 Servlet 的 Web 应用程序,而不仅仅是 Spring Boot 应用。
- 生命周期管理:过滤器具有初始化(
使用场景
- 安全性:实现身份验证和授权逻辑,确保只有经过验证的用户才能访问某些资源。
- 编码转换:在请求和响应中进行字符集转换,以支持国际化。
- 日志记录:记录每个请求的信息,用于调试和监控应用程序行为。
- 性能监控:测量请求处理时间,以便进行性能分析和优化。
- 资源限制:限制请求频率,防止资源滥用,例如通过实现速率限制功能。
- 响应头添加:自动添加 HTTP 响应头,如 CORS 支持或安全相关的头部信息。
示例代码
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;@WebFilter(urlPatterns = "/*")
public class MyFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("Filter initialized");// 初始化操作}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println("Request received at filter");// 在请求处理之前进行预处理chain.doFilter(request, response);System.out.println("Response leaving filter");// 在响应发送之前进行后处理}@Overridepublic void destroy() {System.out.println("Filter destroyed");// 销毁操作}
}
3. 拦截器(Interceptor)
定义与特点
- 定义:拦截器是 Spring 框架中的一部分,主要用于在 Web 应用的 MVC 框架中拦截请求和响应,并在控制器方法调用前后以及请求处理完成后执行自定义的逻辑。
- 特点:
- 生命周期钩子:拦截器提供了多个钩子方法,如
preHandle
、postHandle
和afterCompletion
,分别在请求处理的开始、结束和完成后调用。 - 动态性:可以通过配置来决定哪些请求会被拦截器处理,而无需修改具体的控制器代码。
- 非侵入性:拦截器的设计使得业务逻辑与横切关注点分离,使得代码更加模块化和可维护。
- 可插拔性:可以根据需要轻松地添加、移除或更改拦截器,而不会影响到现有的业务逻辑。
- 生命周期钩子:拦截器提供了多个钩子方法,如
使用场景
- 权限认证与授权:在请求到达控制器之前检查用户的身份和权限,以确定是否允许访问相应的资源。
- 日志记录:记录请求和响应的信息,用于调试和监控应用程序行为。
- 请求参数修改:在请求到达控制器之前修改请求参数。
- 响应结果修改:在响应发送之前修改响应结果。
示例代码
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;@Component
public class MyInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("Request received at interceptor preHandle");// 在请求处理之前进行预处理return true; // 返回 true 表示放行,false 表示拦截}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("Request handled at interceptor postHandle");// 在请求处理之后,但在视图渲染之前进行处理}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("Response sent at interceptor afterCompletion");// 在请求处理完成之后进行处理}
}
注册拦截器
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class WebConfig implements WebMvcConfigurer {@Autowiredprivate MyInterceptor myInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(myInterceptor).addPathPatterns("/**") // 拦截所有请求.excludePathPatterns("/login", "/logout"); // 排除登录和登出请求}
}
4. 面向切面编程(AOP)
定义与特点
- 定义:AOP 是一种编程范式,它允许你在不修改源代码的情况下,对程序的特定部分添加额外的功能。
- 特点:
- 横切关注点:AOP 将横切关注点(如日志记录、事务管理等)从业务逻辑中分离出来,使得代码更加模块化和可维护。
- 动态代理:Spring AOP 通过动态代理机制实现,可以在运行时织入切面(Aspect)到目标对象中。
- 灵活的通知类型:Spring AOP 提供了多种通知类型,如
@Before
、@After
、@Around
、@AfterReturning
和@AfterThrowing
,分别在方法执行前、后、环绕、返回后和抛出异常时执行。
使用场景
- 事务管理:在方法执行前后管理事务的开启、提交和回滚。
- 日志记录:记录方法的调用信息,用于调试和监控应用程序行为。
- 性能监控:测量方法的执行时间,以便进行性能分析和优化。
- 安全控制:在方法调用前检查用户的权限,以确保安全。
示例代码
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;@Aspect
@Component
public class LoggingAspect {@Before("execution(* com.example.demo.controller.*.*(..))")public void logBefore(JoinPoint joinPoint) {System.out.println("Before method: " + joinPoint.getSignature().getName());// 在方法执行前记录日志}@After("execution(* com.example.demo.controller.*.*(..))")public void logAfter(JoinPoint joinPoint) {System.out.println("After method: " + joinPoint.getSignature().getName());// 在方法执行后记录日志}
}
总结
- 监听器(Listener):用于监听特定事件的发生,并在这些事件发生时执行相应的逻辑。适用于应用程序的生命周期管理和事件驱动的场景。
- 过滤器(Filter):用于在请求到达目标资源之前或在响应从目标资源返回到客户端之后进行预处理或后处理。适用于安全性、编码转换、日志记录等场景。
- 拦截器(Interceptor):用于在 Web 应用的 MVC 框架中拦截请求和响应,并在控制器方法调用前后以及请求处理完成后执行自定义的逻辑。适用于权限认证、日志记录、请求参数修改等场景。
- 面向切面编程(AOP):用于在不修改源代码的情况下,对程序的特定部分添加额外的功能。适用于事务管理、日志记录、性能监控等场景。
通过本文的介绍和示例代码,希望读者能够更好地理解和使用这些机制,提高 Spring Boot 应用程序的开发效率和代码质量。