鍍金池/ 教程/ Java/ Spring Boot:定制攔截器
通過JMX監(jiān)控Spring Boot應用
Spring Boot:定制PropertyEditors
配置是否初始化Bean的方法
Spring Boot的自動配置、Command-line Runner
Spring Boot:定制URL匹配規(guī)則
Spring Boot的自動配置、Command-line Runner
利用Mockito模擬DB
Spring Boot應用的打包和部署
了解Spring Boot的自動配置
Spring Boot應用的健康監(jiān)控
了解Spring Boot的自動配置
初始化數(shù)據(jù)庫和導入數(shù)據(jù)
Spring Boot應用的健康監(jiān)控
Docker with Spring Boot
RESTful by Spring Boot with MySQL
Spring Boot:定制攔截器
Spring Boot:定制static path mappings
Spring Boot with Mysql
Spring Boot:定制自己的starter
在測試中使用內存數(shù)據(jù)庫
Restful: Spring Boot with Mongodb
Spring Boot with Redis
Spring Boot:定制HTTP消息轉換器
Spring Boot: Data Rest Service
Spring Boot:定制type Formatters
在Spring Boot項目中使用Spock框架
選擇Spring Boot項目的內嵌容器
通過EmbeddedServletContainerCustomizer接口調優(yōu)Tomcat
Spring Boot應用的打包和部署
Spring Boot Admin的使用
讓你的Spring Boot工程支持HTTP和HTTPS
Spring Boot:定制servlet filters
Spring Boot:定制URL匹配規(guī)則
Spring Boot應用的測試——Mockito
Spring Boot應用的測試——Mockito
Spring Boot:定制servlet filters
通過@Enable*注解觸發(fā)Spring Boot配置

Spring Boot:定制攔截器

Servlet 過濾器屬于Servlet API,和Spring關系不大。除了使用過濾器包裝web請求,Spring MVC還提供HandlerInterceptor(攔截器)工具。根據(jù)文檔,HandlerInterceptor的功能跟過濾器類似,但攔截器提供更精細的控制能力:在request被響應之前、request被響應之后、視圖渲染之前以及request全部結束之后。我們不能通過攔截器修改request內容,但是可以通過拋出異常(或者返回false)來暫停request的執(zhí)行。

Spring MVC中常用的攔截器有:LocaleChangeInterceptor(用于國際化配置)ThemeChangeInterceptor。我們也可以增加自己定義的攔截器,可以參考這篇文章中提供的demo

How Do

添加攔截器不僅是在WebConfiguration中定義bean,Spring Boot提供了基礎類WebMvcConfigurerAdapter,我們項目中的WebConfiguration類需要繼承這個類。

  1. 繼承WebMvcConfigurerAdapter;
  2. 為LocaleChangeInterceptor添加@Bean定義,這僅僅是定義了一個interceptor spring bean,但是Spring boot不會自動將它加入到調用鏈中。
  3. 攔截器需要手動加入調用鏈。

修改后完整的WebConfiguration代碼如下:

package com.test.bookpub;

import org.apache.catalina.filters.RemoteIpFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;

@Configuration
public class WebConfiguration extends WebMvcConfigurerAdapter {
    @Bean    public RemoteIpFilter remoteIpFilter() {
        return new RemoteIpFilter();
    }

    @Bean    public LocaleChangeInterceptor localeChangeInterceptor() {
        return new LocaleChangeInterceptor();
    }
    @Override    public void addInterceptors(InterceptorRegistry registry {
        registry.addInterceptor(localeChangeInterceptor());
    }
}

使用mvn spring-boot:run運行程序,然后通過httpie訪問http://localhost:8080/books?locale=foo,在終端看到如下錯誤信息。

Servlet.service() for servlet [dispatcherServlet] in context with path [] 
threw exception [Request processing failed; nested exception is 
java.lang.UnsupportedOperationException: Cannot change HTTP accept 
header - use a different locale resolution strategy] with root cause

PS:這里發(fā)生錯誤并不是因為我們輸入的locale是錯誤的,而是因為默認的locale修改策略不允許來自瀏覽器的請求修改。發(fā)生這樣的錯誤說明我們之前定義的攔截器起作用了。

分析

在我們的示例項目中,覆蓋并重寫了addInterceptors(InterceptorRegistory registory)方法,這是典型的回調函數(shù)——利用該函數(shù)的參數(shù)registry來添加自定義的攔截器。

在Spring Boot的自動配置階段,Spring Boot會掃描所有WebMvcConfigurer的實例,并順序調用其中的回調函數(shù),這表示:如果我們想對配置信息做邏輯上的隔離,可以在Spring Boot項目中定義多個WebMvcConfigurer的實例。