请求进入:filter -> interceptor ->controllerAdvice -> aspect -> controller
响应返回:controller -> aspect -> controllerAdvice -> interceptor -> filter
场景:
1、全局日志切面:
通过aspect切面实现(类上有Aspect注解,Order注解value为1来规定在aspect切面中当前类被优先注册),增强类型为around环绕型(也就是切面的方法上注解为@Around),切入点为实现Controller注解和RestController注解的类里面的方法(Around注解的value为@within RestController || @within Controller),方法内部的逻辑就是通过切面的参数point(around切面的参数为ProceedingJoinPoint)获取你要切入的那个controller方法的入参(point.getArgs()),然后将这个入参塞入request的attribute中 ,request是通过RequestContextHolder(request 容器)获取的,然后执行point的proceed方法去执行相应的业务逻辑,获取返回的参数,将这个返回参数和之前的获取的输入参数经过一系列处理,最后Json序列化之后打印出来。
2、 ControllerAdvice 的应用:
之前写了一个接口,接口正常上线,后面相关功能做改造,要求这个接口在原来的基础上再多返回一个字段,这个字段跟具体的业务没有关系,相当于在原来的接口上做了一个扩展,那么这个功能后端是怎么改造的呢,是写了一个拦截类,这个类标注了RestControllerAdvice注解,并且实现了ResponseBodyAdvice接口(通过这样就把这个类写成了一个controllerAdvice),在这个类中会重写两个方法,一个是supports方法,这个方法代表包装的开启与否,return为true就是开启,还有个方法是beforeBodyWrite,在这个方法里实现就是相应接口的扩展功能,但是这里有一个问题,就是通过这样实现的controllerAdvice,会拦截所有的controller,所以在包装方法里第一件事就是过滤,通过request的getServletPath来过滤,对符合要求的请求返回体进行修改,这个请求的方法体是写在beforeBodyWrite的参数里的,修改完之后return。
问题:
上面的通过实现一个ControllerAdvice 来扩展接口的功能,功能本身是没问题的,前端能收到正确的相应数据,但是有一个问题就是全局日志是通过aspect实现的,aspect的执行顺序在ControllerAdvice 之前,也就是说,全局日志所打印的这个接口的日志文件,是错误的,少一个参数,少了那个在ControllerAdvice 里面被包装进去的那个参数。
标签:顺序,Spring,接口,参数,切面,aspect,注解,拦截,方法 From: https://www.cnblogs.com/zeevy/p/18017186