Spring Boot Interceptor 拦截器配置

Spring Interceptor拦截所有@Controller注解的类,而对@ResponseBody和ResponseEntity后置处理却无能为力,得借助ResponseBodyAdvice。

DispatcherServlet在调用Controller之前,会先调用拦截器的preHandle方法,并在Controller返回后调用postHandle方法。

Spring Interceptor接口

拦截器需实现的接口

org.springframework.web.servlet.HandlerInterceptor

preHandle(..) - 前置处理。

postHandle(..) - 后置处理,位于视图渲染之前,可以向ModelAndView中添加数据。

afterCompletion(..) - 前置条件返回false或拦截处理完成时调用。能获取请求和响应数据及异常信息。

HandlerInterceptor负责将拦截器应用到,所有加了@Controller注解的类上,类上的方法在被调用前后会被拦截处理。

Spring Boot Interceptor拦截器配置

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LocaleChangeInterceptor());
        registry.addInterceptor(new ThemeChangeInterceptor()).addPathPatterns("/**").excludePathPatterns("/admin/**");
        registry.addInterceptor(new SecurityInterceptor()).addPathPatterns("/secure/*");
    }
}

或者

<mvc:interceptors>
  <bean id="loggerInterceptor" class="org.springframework.web.servlet.theme.ThemeChangeInterceptor"/>
</mvc:interceptors>

ResponseBodyAdvice

Interceptor无法处理@ResponseBody和ResponseEntity返回值的方法。此时,可使用ResponseBodyAdvice,在beforeBodyWrite中进行后置处理。

org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice<T>

实现接口方法,通过注解把拦截应用到具体的Controller上。

//针对@RestController注解
@ControllerAdvice(annotations = RestController.class)
public class ExampleAdvice1 {}

//针对packages
@ControllerAdvice("org.example.controllers")
public class ExampleAdvice2 {}

//针对具体类
@ControllerAdvice(assignableTypes = {ControllerInterface.class, AbstractController.class})
public class ExampleAdvice3 {}

默认情况下,@ControllerAdvice针对所有@Controller注解类的方法,可将其声明为Spring bean或包含在自动检测扫描的类路径中。所有的bean都基于@Order语义进行排序。对于异常的处理,@ExceptionHandler将在具有匹配异常处理方法的advice中选择第一个。对于ModelAttribute和InitBinder初始化,@ModelAttribute和@InitBinder方法也将遵循@ControllerAdvice顺序。

 @RestControllerAdvice
 public class WebRestControllerAdvice {
   
  @ExceptionHandler(CustomNotFoundException.class)
  public ResponseMsg handleNotFoundException(CustomNotFoundException ex) {
   ResponseMsg responseMsg = new ResponseMsg(ex.getMessage());
   return responseMsg;
  }
 }