Java Spring Boot 的过滤器(Filter),拦截器(Interceptor),切面(Aspect)
在 Java Spring Boot 中,过滤器(Filter),拦截器(Interceptor)和切面(Aspect)是用于处理请求和响应的关键组件。它们都提供了在请求处理过程中进行自定义处理的能力,但在使用方式和功能上有一些区别。
过滤器(Filter)
过滤器是 Java Servlet 规范中定义的组件,用于在请求进入 Servlet 容器之前或离开容器之后进行处理。过滤器可以对请求进行预处理或后处理,例如修改请求参数、处理请求头、校验身份等。在 Spring Boot 中,过滤器可以通过实现 javax.servlet.Filter
接口来创建。
以下是一个简单的过滤器示例,它记录了每个请求的执行时间:
import javax.servlet.*;
import java.io.IOException;
public class TimingFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
long startTime = System.currentTimeMillis();
// 执行过滤器链中的下一个过滤器或目标资源
chain.doFilter(request, response);
long endTime = System.currentTimeMillis();
long executionTime = endTime - startTime;
System.out.println("Request execution time: " + executionTime + "ms");
}
// 其他方法:init() 和 destroy()
}
要在 Spring Boot 中使用过滤器,需要将其注册为一个 Bean,并配置过滤器的 URL 匹配规则。
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<TimingFilter> timingFilterRegistrationBean() {
FilterRegistrationBean<TimingFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new TimingFilter());
registrationBean.addUrlPatterns("/*"); // 过滤所有请求
return registrationBean;
}
}
拦截器(Interceptor)
拦截器是 Spring 框架提供的组件,用于拦截请求并在处理程序执行前后进行自定义处理。拦截器可以在 Spring MVC 中使用,它更加高级和强大,能够访问 Spring 上下文和处理程序的详细信息。
以下是一个简单的拦截器示例,它在请求处理前后记录日志:
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoggingInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("Before handling the request");
return true; // 继续执行后续的拦截器和处理程序
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("After handling the request");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception ex) throws Exception {
System.out.println("After rendering the view");
}
}
要在 Spring Boot 中使用拦截器,需要注册拦截器并配置拦截的 URL 匹配规则。
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 InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoggingInterceptor())
.addPathPatterns("/**"); // 拦截所有请求
}
}
切面(Aspect)
切面是 Spring AOP(面向切面编程)的一部分,它可以捕获和处理系统中的切点(特定的方法调用或程序执行位置)。切面可以在方法调用前后执行自定义逻辑,如日志记录、性能测量、事务管理等。
以下是一个简单的切面示例,它记录了被注解 @LogExecutionTime
标记的方法的执行时间:
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
@Aspect
public class TimingAspect {
@Around("@annotation(LogExecutionTime)")
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
Object result = joinPoint.proceed();
long endTime = System.currentTimeMillis();
long executionTime = endTime - startTime;
System.out.println("Method execution time: " + executionTime + "ms");
return result;
}
}
// 定义一个自定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface LogExecutionTime {
}
要在 Spring Boot 中使用切面,需要将切面类定义为一个 Bean 并通过 @EnableAspectJAutoProxy
注解启用自动代理。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@EnableAspectJAutoProxy
public class AspectConfig {
@Bean
public TimingAspect timingAspect() {
return new TimingAspect();
}
}
区别与适用场景
- 过滤器(Filter)是 Servlet 规范中定义的组件,与 Servlet 容器紧密相关,可以用于对请求和响应进行预处理和后处理,但无法访问 Spring 上下文和处理程序的详细信息。适用于较底层的请求处理逻辑,例如修改请求参数、校验身份等。
- 拦截器(Interceptor)是 Spring MVC 提供的组件,能够在请求处理前后拦截并进行自定义处理,可以访问 Spring 上下文和处理程序的详细信息。适用于需要访问和修改处理程序上下文的高级处理逻辑,例如记录日志、权限检查等。
- 切面(Aspect)是 Spring AOP 的一部分,能够在系统中的特定位置(切点)捕获和处理方法调用,可以在方法执行前后插入自
定义逻辑。适用于横切关注点(如日志、事务)的处理,使得这些关注点能够与核心业务逻辑分离,提高代码的模块性和可重用性。
根据具体需求和场景的不同,可以选择适当的组件来实现所需的功能和处理逻辑。