Spring 拦截器Interception 和 AOP 做全局处理的使用方式与使用场景分析

本文介绍了Spring框架中的Interceptor和AOP的使用方式与场景。Interceptor基于Java动态代理实现,用于Controller请求拦截,而AOP功能更强大,可用于Controller层内外的细节操作。拦截器的执行顺序在AOP之前。文章提供了Interceptor和AOP的配置及注解示例,并指出Interceptor适合做全局如权限校验,AOP适用于复杂业务逻辑如性能统计、日志服务。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介:

Interceptor和aop:依赖spring框架,基于java反射和动态代理实现,只能拦截controller的请求,可以获取ioc容器中的bean
拦截顺序:Interception > AOP > 具体执行的方法 > AOP > @ControllerAdvice > Interception

Interceptor

Interceptor是依赖于Spring框架,是aop的一种表现,基于Java的动态代理实现的。

使用步骤:

  1. 声明拦截器的类:通过实现 HandlerInterceptor接口,实现preHandle、postHandle和afterCompletion方法。
  2. 通过配置类配置拦截器:通过实现WebMvcConfigurer接口,实现addInterceptors方法。

举个栗子,上代码:
1.声明拦截器:MyInterceptor.java

public class MyInterceptor implements HandlerInterceptor{

    /**
     * 预处理回调方法,实现处理器的预处理(如检查登陆),第三个参数为响应的处理器
     * 返回值:true表示继续流程(如调用下一个拦截器或处理器);false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        String methodName = method.getName();
        System.out.println("====拦截到了方法:"+methodName+",preHandle====");
        return true;
    }

    /**
     * 后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
        System.out.println("====postHandle====");
    }

    /**
     *整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
        System.out.println("====afterCompletion====");
    }
}

1.通过配置类配置拦截器
MvcConfig.java

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import pers.kerry.demo.webfilter.interceptor.DemoInterceptor;

/**
 * spring 2.x 以前,通过继承 WebMvcConfigurerAdapter 类
 * spring 2.x 之后,实现 WebMvcConfigurer 接口
 */
@Configuration
public class MvcConfigimplements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new DemoInterceptor()).addPathPatterns("/**");
    }

}
## AOP

我在另外一篇文章中也使用到了AOP,也可以作为参考 : Spring Boot 自定义注解实现AOP切面织入.

相比较于拦截器,Spring 的aop则功能更强大,封装的更细致,需要单独引用 jar包。

先导入依赖pom.xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

在定义AOP的时候,非常简单,只需要通过注解,底层实现逻辑都通过IOC框架实现好了,涉及到的注解如下:

  • @Aspect:将一个 java 类定义为切面类。
  • @Pointcut:定义一个切入点,可以是一个规则表达式,比如下例中某个 package 下的所有函数,也可以是一个注解等。
  • @Before:在切入点开始前切入内容。
  • @After:在切入点结尾处切入内容,无论是否有异常,都会执行,类似于finally。
  • @AfterReturning:在切入点 return 内容之后处理逻辑,只有执行成功会执行,异常不会。
  • @Around:在切入点前后切入内容,并自己控制何时执行切入点自身的内容。原则上可以替代@Before和@After。
  • @AfterThrowing:用来处理当切入内容部分抛出异常之后的处理逻辑。
  • @Order(100):AOP 切面执行顺序, @Before 数值越小越先执行,@After 和 @AfterReturning 数值越大越先执行

举个栗子,上代码:

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
/**
 * @Aspect 注解 使之成为切面类
 * @Component 注解 把切面类加入到IOC容器中
 */
@Aspect
@Component
public class MyAspect {

	//表示匹配com.demo.webfilter.controller.DemoController中所有的公有方法,这里也可以是一个注解
    @Pointcut( "execution( public * com.demo.webfilter.controller.DemoController.*(..) )")
    public void doPointcut(){
    }

    @Before("doPointcut()")
    public void doBefore(){
        System.out.println("==doBefore==");
    }

    @After("doPointcut()")
    public void doAfter(){
        System.out.println("==doAfter==");
    }

    @AfterReturning("doPointcut()")
    public void doAfterReturning(){
        System.out.println("==doAfterReturning==");
    }

    /**
     * 返回值类型Object,对应所有被拦截方法的返回值类型,不能为void
     */
    @Around("doPointcut()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{
        System.out.println("==doAround.before==");
        Object ret = proceedingJoinPoint.proceed();
        System.out.println("==doAround.after==");
        return ret;
    }
}

Interception 和 AOP 使用场景分析:

拦截器只能在Controller层的前后使用,AOP可以在Controller层的前后以及Controller层内部的方法上使用,功能可以更细化。
所以在编写相对比较公用的代码时,优先考虑拦截器,比如权限校验,一般情况下,所有的请求都需要做登录权限校验,此时就应该使用拦截器。AOP针对具体的方法代码,能够实现更加复杂和细致的业务逻辑,比如对每个API接口的性能统计、日志服务等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值