切片Aspect
切片概述
相比过滤器,拦截器能够知道用户发出的请求最终被哪个控制器处理,但是拦截器还有一个明显的不足,即不能够获取request的参数以及控制器处理之后的response。所以就有了切片的用武之地了。
切片实现
切片的实现需要注意@Aspect,@Component以及@Around这三个注解的使用,详细查看官方文档:
docs.spring.io/spring/docs/5.0.12.RELEASE/spring-framework-reference/core.html#aop
@Aspect @Component public class TimeAspect { private static final Logger LOG = LoggerFactory.getLogger(TimeAspect.class); @Around("execution(* me.ifight.controller.*.*(..))") public Object handleControllerMethod(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{ LOG.info("切片开始。。。"); long startTime = System.currentTimeMillis(); // 获取请求入参 Object[] args = proceedingJoinPoint.getArgs(); Arrays.stream(args).forEach(arg -> LOG.info("arg is {}", arg)); // 获取相应 Object response = proceedingJoinPoint.proceed(); long endTime = System.currentTimeMillis(); LOG.info("请求:{}, 耗时{}ms", proceedingJoinPoint.getSignature(), (endTime - startTime)); LOG.info("切片结束。。。"); return null; } }
过滤器、拦截器以及切片的调用顺序
如下图,展示了三者的调用顺序Filter->Intercepto->Aspect->Controller。相反的是,当Controller抛出的异常的处理顺序则是从内到外的。因此我们总是定义一个注解@ControllerAdvice去统一处理控制器抛出的异常。如果一旦异常被@ControllerAdvice处理了,则调用拦截器的afterCompletion方法的参数Exception ex就为空了。
实际执行的调用栈也说明了这一点:
而对于过滤器和拦截器详细的调用顺序如下图:
过滤器和拦截器的区别
最后有必要再说说过滤器和拦截器二者之间的区别:除此之外,相比过滤器,拦截器能够“看到”用户的请求具体是被Spring框架的哪个控制器所处理。
参考
blog.csdn.net/xiaodanjava/article/details/32125687