SpringBoot 请求拦截

时间:2025-02-15 20:05:39

SpringBoot 请求拦截

  • 1 切片(Aspect)
    • 1.1 AOP中的相关概念
    • 1.2 Advice 的类型
  • 2 过滤器(Filter)
  • 3 拦截器(Interceptor)
    • 3.1 RequestConfig
    • 3.2 CustomerInterceptor

在 Spring Boot 中,请求拦截有如下三种方式
切片(Aspect)
过滤器(Filter)
拦截器(Interceptor)

1 切片(Aspect)

1.1 AOP中的相关概念

定义词 作用
Aspect(切面) Aspect 声明类似于 Java 中的类声明,在 Aspect 中会包含着一些 Pointcut 以及相应的 Advice。
Joint point(连接点) 表示在程序中明确定义的点,典型的包括方法调用,对类成员的访问以及异常处理程序块的执行等等,它自身还可以嵌套其它 joint point。
Pointcut(切点) 表示一组 joint point,这些 joint point 或是通过逻辑关系组合起来,或是通过通配、正则表达式等方式集中起来,它定义了相应的 Advice 将要发生的地方。
Advice(增强) Advice 定义了在 Pointcut 里面定义的程序点具体要做的操作,它通过 before、after 和 around 来区别是在每个 joint point 之前、之后还是代替执行的代码。
Target(目标对象) 织入 Advice 的目标对象.。
Weaving(织入) 将 Aspect 和其他对象连接起来, 并创建 Adviced object 的过程

1.2 Advice 的类型

方法 作用
@Before(“logPointCut()”) (前置建议),即在方法执行前 执行前置方法。
@AfterReturning(pointcut = “logPointCut()”, returning = “result”) (后置建议),即在方法正确执行后 才执行后置方法。
@AfterThrowing(“logPointCut()”) (后置返回建议),即在方法抛出异常时 执行该后置方法。
@After(“logPointCut()”) (后置抛出建议),即在方法执行后 执行后置方法。
@Around(“logPointCut()”) (环绕建议),即在方法执行前后 进行执行前后置方法。
@Aspect
@Component
public class CustomerAspect {

    @Pointcut("@annotation()")
    public void logPointCut() {

    }

    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        return point.proceed();
    }

    @Before("logPointCut()")
    public void before(JoinPoint point) throws Throwable {
        MethodSignature signature = (MethodSignature) point.getSignature();
    }

    @AfterReturning(pointcut = "logPointCut()", returning = "result")
    public void afterReturning(JoinPoint point, Object result) throws Throwable {
        MethodSignature signature = (MethodSignature) point.getSignature();
    }

}

2 过滤器(Filter)


import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;

public class CustomerFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("进入 CustomerFilter");
        filterChain.doFilter(request, response);
        System.out.println("离开 CustomerFilter");
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }

}

3 拦截器(Interceptor)

拦截器相比过滤器,能拿到控制器类和方法,但是依旧无法拿到请求的参数。

方法 作用
preHandle 是请求执行前执行。
postHandler 是请求成功执行,如果接口方法抛出异常不会执行,且只有 preHandle 方法返回 true 的时候才会执行。
afterCompletion 是请求结束才执行,无论请求成功或失败都会执行,同样需要 preHandle 返回 true,该方法通常用于清理资源等工作。

3.1 RequestConfig

@Configuration
public class RequestConfig extends WebMvcConfigurationSupport {

    @Autowired
    private CustomerInterceptor interceptor;

    @Override
    protected void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(interceptor).addPathPatterns("/**");
        super.addInterceptors(registry);
    }

}

3.2 CustomerInterceptor

@Slf4j
@Component
public class CustomerInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        request.setAttribute("StartTime", System.currentTimeMillis());
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        Long start = (Long) request.getAttribute("StartTime");
        log.info("请求执行完毕 总耗时:{}", (System.currentTimeMillis() - start));
    }

}