我們可以通過實現 WebMvcConfigurer
接口來自定義 Spring MVC (尤其是在 Spring Boot 環境中) 的配置。
以下是通過實現 WebMvcConfigurer
接口的配置方法:
核心:創建一個 @Configuration
類并實現 WebMvcConfigurer
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.config.annotation.*; // 關鍵導入import java.util.List;@Configuration
// 在Spring Boot中不需要 @EnableWebMvc,除非你想完全禁用Spring Boot的MVC自動配置
public class MyCustomWebMvcConfigurer implements WebMvcConfigurer {// 具體配置方法如下:
}
可以定制的方面:
-
攔截器 (Interceptors):
- 方法:
addInterceptors(InterceptorRegistry registry)
- 用途: 添加自定義攔截器,用于在請求處理之前、之后或完成時執行通用邏輯,如日志記錄、權限校驗、事務管理等。
- 示例:
@Override public void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new MyAuthInterceptor()).addPathPatterns("/secure/**") // 攔截以 /secure/ 開頭的路徑.excludePathPatterns("/secure/login", "/secure/public/**"); // 排除某些路徑 }
- 方法:
-
格式化器和轉換器 (Formatters and Converters):
- 方法:
addFormatters(FormatterRegistry registry)
- 用途: 注冊自定義的
Formatter
(用于特定類型的格式化,如日期) 和Converter
(用于類型之間的轉換),這些在數據綁定時非常有用。 - 示例:
@Override public void addFormatters(FormatterRegistry registry) {registry.addConverter(new StringToMyCustomObjectConverter());registry.addFormatter(new MyCustomDateFormatter()); }
- 方法:
-
HTTP 消息轉換器 (HttpMessageConverters):
- 方法:
configureMessageConverters(List<HttpMessageConverter<?>> converters)
: 完全替換默認的轉換器列表。extendMessageConverters(List<HttpMessageConverter<?>> converters)
: 在默認轉換器列表的基礎上添加或修改。推薦使用這個,因為它保留了Spring Boot的自動配置轉換器。
- 用途: 配置 Spring MVC 如何將請求體轉換為Java對象,以及如何將Java對象轉換為響應體 (例如,處理JSON、XML、Protobuf等)。
- 示例 (使用
extendMessageConverters
):@Override public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {// 添加一個自定義的 Protobuf 消息轉換器// converters.add(0, new ProtobufHttpMessageConverter()); // 添加到列表開頭// 或者移除/修改已有的轉換器,例如配置Jackson// for (HttpMessageConverter<?> converter : converters) {// if (converter instanceof MappingJackson2HttpMessageConverter) {// ObjectMapper objectMapper = ((MappingJackson2HttpMessageConverter) converter).getObjectMapper();// // 自定義 Jackson ObjectMapper 的配置// objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);// }// } }
- 方法:
-
靜態資源處理 (Static Resource Handling):
- 方法:
addResourceHandlers(ResourceHandlerRegistry registry)
- 用途: 配置靜態資源(如CSS, JavaScript, 圖片)的URL映射和物理位置。Spring Boot 自動配置了一些默認位置,但可以通過此方法添加更多或覆蓋。
- 示例:
@Override public void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/my-assets/**") // 對外暴露的URL模式.addResourceLocations("classpath:/custom-static/", "file:/var/www/my-app-assets/") // 實際資源位置.setCachePeriod(3600 * 24); // 緩存周期 (秒) }
- 方法:
-
跨域資源共享 (CORS) 配置:
- 方法:
addCorsMappings(CorsRegistry registry)
- 用途: 全局配置CORS,允許或限制來自不同源的跨域請求。
- 示例:
@Override public void addCorsMappings(CorsRegistry registry) {registry.addMapping("/api/**") // 對 /api/ 下的所有路徑生效.allowedOrigins("http://example.com", "https://trusted.client.com") // 允許的源.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") // 允許的方法.allowedHeaders("*") // 允許所有請求頭.allowCredentials(true) // 是否允許發送Cookie.maxAge(3600); // 預檢請求的緩存時間 (秒) }
- 方法:
-
視圖控制器 (View Controllers):
- 方法:
addViewControllers(ViewControllerRegistry registry)
- 用途: 為那些不需要任何業務邏輯、僅將URL路徑直接映射到視圖名稱的簡單情況提供快捷配置。
- 示例:
@Override public void addViewControllers(ViewControllerRegistry registry) {registry.addViewController("/").setViewName("home"); // 訪問根路徑時顯示 home 視圖registry.addViewController("/about").setViewName("aboutPage");registry.addRedirectViewController("/old-path", "/new-path"); // 重定向 }
- 方法:
-
內容協商 (Content Negotiation) 策略:
- 方法:
configureContentNegotiation(ContentNegotiationConfigurer configurer)
- 用途: 配置 Spring MVC 如何根據客戶端請求(如
Accept
頭、URL參數、路徑擴展名)來決定響應的內容類型(如JSON, XML)。 - 示例:
@Override public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {configurer.favorParameter(true) // 啟用基于URL參數的協商 (如 ?format=json).parameterName("mediaType") // 自定義參數名,默認為 "format".ignoreAcceptHeader(false) // 是否忽略 Accept 請求頭 (默認為 false).defaultContentType(MediaType.APPLICATION_JSON) // 默認返回JSON.mediaType("xml", MediaType.APPLICATION_XML) // 將 "xml" 映射到 application/xml.mediaType("json", MediaType.APPLICATION_JSON); // 將 "json" 映射到 application/json }
- 方法:
-
自定義參數解析器 (Argument Resolvers):
- 方法:
addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers)
- 用途: 注冊自定義的參數解析器,用于將請求中的特定信息解析并注入到Controller方法的參數中。
- 示例:
// @Override // public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) { // resolvers.add(new CurrentUserArgumentResolver()); // 假設有一個解析當前用戶的解析器 // }
- 方法:
-
自定義返回值處理器 (Return Value Handlers):
- 方法:
addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers)
- 用途: 注冊自定義的返回值處理器,用于處理Controller方法返回的特定類型的值。
- 示例:
// @Override // public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) { // handlers.add(new MyCustomReturnValueHandler()); // }
- 方法:
-
路徑匹配配置 (Path Matching):
- 方法:
configurePathMatch(PathMatchConfigurer configurer)
- 用途: 配置URL路徑匹配的細節,例如是否使用后綴模式匹配 (
.json
,.xml
),是否匹配URL末尾的斜杠。 - 示例:
@Override public void configurePathMatch(PathMatchConfigurer configurer) {configurer.setUseSuffixPatternMatch(false); // 推薦禁用后綴匹配configurer.setUseTrailingSlashMatch(true); // 路徑末尾的 / 是否視為與沒有 / 相同 }
- 方法:
-
異步請求處理配置 (Async Support):
- 方法:
configureAsyncSupport(AsyncSupportConfigurer configurer)
- 用途: 配置異步請求處理的相關參數,如默認超時時間、任務執行器等。
- 示例:
@Override public void configureAsyncSupport(AsyncSupportConfigurer configurer) {configurer.setDefaultTimeout(60 * 1000L); // 設置默認超時時間為60秒// configurer.setTaskExecutor(myAsyncTaskExecutor()); // 配置自定義的異步任務執行器 }
- 方法:
-
視圖解析器 (View Resolvers):
- 方法:
configureViewResolvers(ViewResolverRegistry registry)
- 用途: 配置視圖解析器。在Spring Boot中,常見的模板引擎(如Thymeleaf, FreeMarker)通常會自動配置其視圖解析器。如果你需要自定義或添加額外的視圖解析器(如JSP),可以在這里進行。
- 示例 (配置JSP視圖解析器):
// @Override // public void configureViewResolvers(ViewResolverRegistry registry) { // InternalResourceViewResolver resolver = new InternalResourceViewResolver(); // resolver.setPrefix("/WEB-INF/jsp/"); // resolver.setSuffix(".jsp"); // registry.viewResolver(resolver); // }
- 方法:
-
異常處理器 (Exception Resolvers):
- 方法:
configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers)
或extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers)
- 用途: 配置如何處理在請求處理過程中發生的異常。Spring Boot提供了默認的錯誤處理機制,但你可以通過此方法添加自定義的
HandlerExceptionResolver
。 - 示例 (使用
extendHandlerExceptionResolvers
):// @Override // public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) { // resolvers.add(0, new MyCustomGlobalExceptionResolver()); // }
- 方法:
-
獲取Validator實例 (Validator):
- 方法:
getValidator()
- 用途: 返回一個用于數據綁定的全局
Validator
實例。你可以覆蓋此方法以提供自定義的Validator
。 - 示例:
// @Override // public Validator getValidator() { // // return new MyCustomValidator(); // 返回你自定義的Validator // return WebMvcConfigurer.super.getValidator(); // 或調用父類方法獲取默認 // }
- 方法:
-
獲取消息代碼解析器 (MessageCodesResolver):
- 方法:
getMessageCodesResolver()
- 用途: 返回一個用于從數據綁定錯誤中生成錯誤消息代碼的
MessageCodesResolver
。 - 示例:
// @Override // public MessageCodesResolver getMessageCodesResolver() { // // return new MyCustomMessageCodesResolver(); // return WebMvcConfigurer.super.getMessageCodesResolver(); // }
- 方法:
通過實現 WebMvcConfigurer
并覆蓋這些方法,可以靈活的定制Spring MVC的行為,同時還能充分利用Spring Boot的自動配置帶來的便利。