SringBoot拦截器和aop自定义过滤实现

    |     2017年6月17日   |   springboot   |     0 条评论   |    2959

Spring Boot 里自定义拦截器的写法和 SpringMVC 很接近:实现 HandlerInterceptor,再在 WebMvcConfigurerAdapter 的 addInterceptors 里挂到拦截器链。和 Filter 不同,拦截器能碰到 Handler 和 ModelAndView,更适合 Controller 层的横切。

另一条横切路径是 AOP:用 @Aspect 切 Controller 方法,打 URL、IP、参数和返回值日志。拦截器管请求链,切面管方法调用,可以一起用。

一、拦截器:三步挂到 SpringMVC

  • 创建拦截器类,实现 HandlerInterceptor。
  • 再写一个配置类继承 WebMvcConfigurerAdapter,重写 addInterceptors。
  • 实例化自定义拦截器,在 addInterceptors 里手动加入拦截器链。

1. 定义拦截器

@Component("myInterceptor1")
public class MyInterceptor1 implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        System.out.println(">>>MyInterceptor1>>>>>>>在请求处理之前进行调用(Controller方法调用之前)");
        return true; // 只有返回 true 才会继续向下执行,返回 false 取消当前请求
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        System.out.println(">>>MyInterceptor1>>>>>>>请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        System.out.println(">>>MyInterceptor1>>>>>>>在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)");
    }
}

2. 继承 WebMvcConfigurerAdapter 注册

@Configuration
public class MyWebAppConfigurer extends WebMvcConfigurerAdapter {
    @Autowired
    private MyInterceptor1 myInterceptor1;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 多个拦截器组成一个拦截器链
        // addPathPatterns 用于添加拦截规则
        // excludePathPatterns 用于排除拦截
        registry.addInterceptor(myInterceptor1).addPathPatterns("/**");
        // registry.addInterceptor(new MyInterceptor2()).addPathPatterns("/**");
        super.addInterceptors(registry);
    }
}
回调 时机 常见用途
preHandle Controller 之前 登录校验;返回 false 中断
postHandle Controller 之后、渲染视图前 改 ModelAndView
afterCompletion 视图渲染完 资源清理

二、用 AOP 打访问日志

切 com.ittx.java1608.springbootdemo1.controller 包下的所有方法,记录 url、method、ip、类方法名和参数:

@Aspect
@Component
public class HttpAspect {

    private final static Logger logger = LoggerFactory.getLogger(HttpAspect.class);

    @Pointcut("execution(public * com.ittx.java1608.springbootdemo1.controller.*.*(..))")
    public void log() {
    }

    @Before("log()")
    public void doBefore(JoinPoint joinPoint) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        logger.info("url={}", request.getRequestURL());
        logger.info("method={}", request.getMethod());
        logger.info("ip={}", request.getRemoteAddr());
        logger.info("class_method={}", joinPoint.getSignature().getDeclaringTypeName() + "."
                + joinPoint.getSignature().getName());
        logger.info("args={}", joinPoint.getArgs());
    }

    @After("log()")
    public void doAfter() {
        logger.info("doAfter 222222222222");
    }

    @AfterReturning(returning = "object", pointcut = "log()")
    public void doAfterReturning(Object object) {
        logger.info("response={}", object.toString());
    }
}

记得在 pom.xml 引入 AOP starter:

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

一句话总结:拦截器挂在 SpringMVC 链上拦请求,AOP 切在方法上记日志;两者都要显式注册(addInterceptors / starter-aop),空依赖不会自动生效。

转载请注明来源:SringBoot拦截器和aop自定义过滤实现
本文链接地址:https://ai.zhousir.top/?p=2025
回复 取消