Spring拦截顺序

请求进入: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 里面被包装进去的那个参数。

posted @ 2024-02-16 15:08  leviH  阅读(6)  评论(0编辑  收藏  举报