技术记录栈

记录点滴:java、datebase、linux、spring、javascript、nginx

2018/10/21

Spring Boot Interceptor 拦截器配置

Spring 所有HandlerMapping实现都支持拦截器处理,Spring Boot中也不例外,对特定请求应用特定功能(例如,检查主体)时,Interceptor拦截器功能就变得很有用了。

Spring mvc中的拦截器,需实现org.springframework.web.servlet包中HandlerInterceptor接口,在接口的三个方法中实现必要的业务处理:

preHandle(..) - 拦截器前置条件。

postHandle(..) - 执行实际处理逻辑。

afterCompletion(..) - 后置处理。

preHandle(..)方法返回一个布尔值,此方法作为中断/执行处理链的判断。方法返回时true,处理程序将执行拦截器,返回false时,DispatcherServlet会假定拦截器自身已经处理了请求(例如,渲染了适当的视图),不会继续执行处理链中的其他拦截器和目标程序。

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/*");
    }
}

Spring mvc中个别HandlerMapping的实现,支持通过setter直接注册拦截器。需要注意到postHandle,对于加入了@ResponseBody和ResponseEntity返回值的方法不太有用,这表示拦截器对响应进行的任何更改都太晚了,例如:需要对请求响应头(Response Headers)添加额外信息。通过实现ResponseBodyAdvice,并将其声明为“Controller Advice bean”来达成,或直接在RequestMappingHandlerAdapter上配置它。

// Target all Controllers annotated with @RestController
@ControllerAdvice(annotations = RestController.class)
public class ExampleAdvice1 {}

// Target all Controllers within specific packages
@ControllerAdvice("org.example.controllers")
public class ExampleAdvice2 {}

// Target all Controllers assignable to specific classes
@ControllerAdvice(assignableTypes = {ControllerInterface.class, AbstractController.class})
public class ExampleAdvice3 {}

上述选择器需根据运行时情况进行评估,如果大面积使用,可能对性能产生负面影响。

Spring boot 特定拦截器具体实现和应用场景

REST服务中一个常见需求,希望异常时能在响应正文中包含错误的详细信息。Spring Framework不会自动执行此类操作,因为,响应正文中的错误详情,是特定于应用程序的。但是,可以通过由@ExceptionHandler标记的类,来处理带有ResponseEntity返回值的@RestController,以此,来设置响应的状态和主体(body)。这种处理类需要引入@ControllerAdvice注解来声明,然后,在全局范围内应用它。

在异常处理中响应主体返回错误详情,全局性实现也可以通过实现ResponseEntityExceptionHandler接口做到,它提供对Spring MVC引发的异常,以及对定制响应主体的处理。具体做法是:创建一个实现了ResponseEntityExceptionHandler接口的类,并引入@ControllerAdvice注解,然后,在实现方法中去做相应的处理,并将其声明为Spring bean(如:使用@Component注解)。