WebMvcConfigurerAdapter配置類是spring提供的一種配置方式,采用JavaBean的方式替代傳統的基於xml的配置來對spring框架進行自定義的配置。因此,在spring boot提倡的基於注解的配置,采用“約定大於配置”的風格下,當需要進行自定義的配置時,便可以繼承WebMvcConfigurerAdapter這個抽象類,通過JavaBean來實現需要的配置。
WebMvcConfigurerAdapter是一個抽象類,它只提供了一些空的接口讓用戶去重寫,比如如果想添加攔截器的時候,需要去重寫一下addInterceptors()這個方法,去配置自定義的攔截器。我們可以看一下WebMvcConfigurerAdapter提供了哪些接口來供我們使用。
1 public abstract class WebMvcConfigurerAdapter implements WebMvcConfigurer { 2 /*配置路徑匹配參數*/ 3 public void configurePathMatch(PathMatchConfigurer configurer) {} 4 /*配置Web Service或REST API設計中內容協商,即根據客戶端的支持內容格式情況來封裝響應消息體,如xml,json*/ 5 public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {} 6 /*配置路徑匹配參數*/ 7 public void configureAsyncSupport(AsyncSupportConfigurer configurer) {} 8 /* 使得springmvc在接口層支持異步*/ 9 public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {} 10 /* 注冊參數轉換和格式化器*/ 11 public void addFormatters(FormatterRegistry registry) {} 12 /* 注冊配置的攔截器*/ 13 public void addInterceptors(InterceptorRegistry registry) {} 14 /* 自定義靜態資源映射*/ 15 public void addResourceHandlers(ResourceHandlerRegistry registry) {} 16 /* cors跨域訪問*/ 17 public void addCorsMappings(CorsRegistry registry) {} 18 /* 配置頁面直接訪問,不走接口*/ 19 public void addViewControllers(ViewControllerRegistry registry) {} 20 /* 注冊自定義的視圖解析器*/ 21 public void configureViewResolvers(ViewResolverRegistry registry) {} 22 /* 注冊自定義控制器(controller)方法參數類型*/ 23 public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {} 24 /* 注冊自定義控制器(controller)方法返回類型*/ 25 public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {} 26 /* 重載會覆蓋掉spring mvc默認注冊的多個HttpMessageConverter*/ 27 public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {} 28 /* 僅添加一個自定義的HttpMessageConverter,不覆蓋默認注冊的HttpMessageConverter*/ 29 public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {} 30 /* 注冊異常處理*/ 31 public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {} 32 /* 多個異常處理,可以重寫次方法指定處理順序等*/ 33 public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {} 34 }
WebMvcConfigurerAdapter提供了很多的接口供用戶去實現自定義的配置項。下面挑幾個比較重要的介紹一下如何使用這些接口來自定義配置。
1.注冊攔截器
首先,編寫攔截器的代碼:
1 public class LoginInterceptor extends HandlerInterceptorAdapter { 2 3 private static final Logger logger = LoggerFactory.getLogger(LoginInterceptor.class); 4 5 @Override 6 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 7 logger.info("-----------------------------"); 8 logger.info(request.getRequestedSessionId()); 9 logger.info("-----------------------------"); 10 return true; 11 } 12 }
這里只打印相關信息,然后,需要寫一個config類去配置這個攔截器:
1 @Configuration 2 public class WebConfig extends WebMvcConfigurerAdapter { 3 /* 4 * 攔截器配置*/ 5 @Override 6 public void addInterceptors(InterceptorRegistry registry) { 7 registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**"); 8 }
配置類繼承了WebMvcConfigurerAdapter這個類,並且重寫了addInterceptors這個方法,在方法中,注冊了上面編寫的攔截器,並且為此攔截器配置了攔截路徑,這樣一來就算是配置好了這個攔截器。
2.配置CORS跨域
只需要在上面的webConfig里重寫WebMvcConfigurerAdapter的addCorsMappings方法就可以獲得基於spring的跨域支持。
1 /** 2 * 跨域CORS配置 3 * @param registry 4 */ 5 @Override 6 public void addCorsMappings(CorsRegistry registry) { 7 super.addCorsMappings(registry); 8 registry.addMapping("/**") 9 .allowedHeaders("*") 10 .allowedMethods("POST","GET") 11 .allowedOrigins("http://...") 12 .allowCredentials(true); 13 }
3.配置ViewController
當首頁或者登陸頁的頁面對外暴露,不需要加載任何的配置的時候,這些頁面將不通過接口層,而是直接訪問,這時,就需要配置ViewController指定請求路徑直接到頁面。
1 /** 2 * 視圖控制器配置 3 * @param registry 4 */ 5 @Override 6 public void addViewControllers(ViewControllerRegistry registry) { 7 super.addViewControllers(registry); 8 registry.addViewController("/").setViewName("forward:/index.html"); 9 }
4.配置ViewResolver
通常在使用jsp的項目中,會基於spring mvc配置的文件去配置視圖解析器,通過重寫WebMvcConfigurerAdapter里的configureViewResolvers也可以將自己定義的InternalResourceViewResolver配置整合進spring中。
1 /** 2 * 配置請求視圖映射 3 * 4 * @return 5 */ 6 @Bean 7 public InternalResourceViewResolver resourceViewResolver() { 8 InternalResourceViewResolver internalResourceViewResolver = new InternalResourceViewResolver(); 9 //請求視圖文件的前綴地址 10 internalResourceViewResolver.setPrefix("/WEB-INF/jsp/"); 11 //請求視圖文件的后綴 12 internalResourceViewResolver.setSuffix(".jsp"); 13 return internalResourceViewResolver; 14 } 15 16 @Override 17 public void configureViewResolvers(ViewResolverRegistry registry) { 18 super.configureViewResolvers(registry); 19 registry.viewResolver(resourceViewResolver()); 20 }
可以看一下ViewResolverRegistry中的代碼:
1 public UrlBasedViewResolverRegistration jsp() { 2 return this.jsp("/WEB-INF/", ".jsp"); 3 } 4 5 public UrlBasedViewResolverRegistration jsp(String prefix, String suffix) { 6 InternalResourceViewResolver resolver = new InternalResourceViewResolver(); 7 resolver.setPrefix(prefix); 8 resolver.setSuffix(suffix); 9 this.viewResolvers.add(resolver); 10 return new UrlBasedViewResolverRegistration(resolver); 11 }
可以看到,即使不去配置,spring也會新建一個默認的視圖解析器。十分方便。
5.配置Formatter
當請求的參數中帶有日期的參數的時候,可以在此配置formatter使得接收到日期參數格式統一。
1 @Override 2 public void addFormatters(FormatterRegistry registry) { 3 registry.addFormatter(new Formatter<Date>() { 4 @Override 5 public Date parse(String date, Locale locale) { 6 return new Date(Long.parseLong(date)); 7 } 8 9 @Override 10 public String print(Date date, Locale locale) { 11 return Long.valueOf(date.getTime()).toString(); 12 } 13 }); 14 }
總結一下,本文主要講了如何通過JavaBean替代xml為springmvc做出自定義的配置,比較符合spring boot的去xml配置的風格。