springboot的整合其實就是自動配置,springboot是如何實現自動配置springmvc的,先回顧springmvc是做什么的
springmvc
工作流程是:請求通過前端控制器將請求URL交給處理器映射器處理獲取Handler,並將獲取的handler交給處理器適配器執行,執行后返回ModelAndView對象,根據對象值進行頁面渲染。
具體做了什么?
1、處理請求(請求參數)
2、處理器映射器、處理器適配器的工作就沒有那么明顯了
3、視圖解析器
springboot
1、配置
自動配置:AutoConfiguration和Properties
2、注解
springboot和springmvc整合
1、自動配置springmvc
WebMvcAutoConfiguration、WebMvcProperties
2、增強springmvc
https://docs.spring.io/spring-boot/docs/2.3.9.RELEASE/reference/htmlsingle/#boot-features-spring-mvc-auto-configuration
自動配置在 Spring 的默認值之上添加了以下功能:
The auto-configuration adds the following features on top of Spring’s defaults:
包含ContentNegotiatingViewResolver和BeanNameViewResolver視圖解析器的bean
Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.
支持靜態資源和Webjars
Support for serving static resources, including support for WebJars (covered later in this document)).
自動注冊轉換器(Converter):頁面數據提交到后台轉換為對象,
通用轉換器(GenericConverter)
格式化器(Formatter):可以對日期格式的數據進行格式化,並轉換成對象
Automatic registration of Converter, GenericConverter, and Formatter beans.
HttpMessageConverters:轉換請求和響應message,比如對象轉換成json字符串
Support for HttpMessageConverters (covered later in this document).
自動注冊messagecodes解析器(MessageCodesResolver)
Automatic registration of MessageCodesResolver (covered later in this document).
支持首頁
Static index.html support.
支持圖標
Custom Favicon support (covered later in this document).
自動使用初始化數據綁定器:把請求數據綁定到JavaBean
Automatic use of a ConfigurableWebBindingInitializer bean (covered later in this document).
ContentNegotiatingViewResolver 內容協商視圖解析器
(兩次敲擊Shift)找到 WebMvcAutoConfiguration , 然后搜索ContentNegotiatingViewResolver,並進入此類中,此類是視圖解析,可以看看有沒有返回View的方法
@Nullable //運行參數為NULL public View resolveViewName(String viewName, Locale locale) throws Exception { RequestAttributes attrs = RequestContextHolder.getRequestAttributes(); Assert.state(attrs instanceof ServletRequestAttributes, "No current ServletRequestAttributes"); List<MediaType> requestedMediaTypes = this.getMediaTypes(((ServletRequestAttributes)attrs).getRequest()); if (requestedMediaTypes != null) { //根據viewName獲取View對象 List<View> candidateViews = this.getCandidateViews(viewName, locale, requestedMediaTypes); //獲取優先級高的View對象 View bestView = this.getBestView(candidateViews, requestedMediaTypes, attrs); if (bestView != null) { return bestView; } } ....... }
具體步驟:
1、獲取所有實現ViewResolver的視圖解析類
protected void initServletContext(ServletContext servletContext) { // 獲取實現ViewResolver接口對象 Collection<ViewResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(obtainApplicationContext(), ViewResolver.class).values(); if (this.viewResolvers == null) { this.viewResolvers = new ArrayList<>(matchingBeans.size()); for (ViewResolver viewResolver : matchingBeans) { if (this != viewResolver) { this.viewResolvers.add(viewResolver); } } } ... ... }
2、根據視圖名獲取View對象
3、根據優先級輸出最優View對象
總結:ContentNegotiatingViewResolver主要是將所有實現ViewResolver接口的類都組合起來,然后根據View Name 獲取最優先的返回
自定義視圖解析器
1、創建實現ViewResolver接口的MyViewResolver類,並交給Spring容器
@Component public class MyViewResolver implements ViewResolver { @Override public View resolveViewName(String s, Locale locale) throws Exception { return null; } }
2、編寫Controller
@RestController public class TestController { @GetMapping("/test") public String test(){ return "test"; } }
3、查找DispatcherServlet,並在doDispatch打斷點
4、debug,訪問Controller中的test方法
格式化轉換器
@Bean @Override public FormattingConversionService mvcConversionService() { WebConversionService conversionService = new WebConversionService(this.mvcProperties.getDateFormat()); addFormatters(conversionService); return conversionService; }
進入getDateFormat方法
public String getDateFormat() { return this.dateFormat; }
/** * Date format to use. For instance, `dd/MM/yyyy`. 默認的 */ private String dateFormat;
springboot已經做好日期格式的轉換了,但是這個日期格式和我們常規的不一樣,可以通過配置文件修改
怎么修改呢
1、查看WebMvcProperties
2、前綴加屬性
發現springboot不推薦使用它,找了一下替代它的
@Bean @Override public FormattingConversionService mvcConversionService() { Format format = this.mvcProperties.getFormat(); WebConversionService conversionService = new WebConversionService(new DateTimeFormatters() .dateFormat(format.getDate()).timeFormat(format.getTime()).dateTimeFormat(format.getDateTime())); addFormatters(conversionService); return conversionService; }
測試:
頁面傳date類型值(yyyy-MM-dd),
配置文件中spring.mvc.format.date=yyyy/MM/dd,
controller的方法參數
public String test(Date date){}
結果就會報String轉換Date類型失敗
springmvc在springboot框架下擴展
https://docs.spring.io/spring-boot/docs/2.3.9.RELEASE/reference/htmlsingle/#boot-features-spring-mvc-auto-configuration
If you want to keep those Spring Boot MVC customizations and make more MVC customizations (interceptors, formatters, view controllers, and other features), you can add your own @Configuration class of type WebMvcConfigurer but without@EnableWebMvc.
直譯:如果您想保留那些 Spring Boot MVC 自定義並進行更多 MVC 自定義(攔截器、格式化程序、視圖控制器和其他功能),您可以添加自己的 WebMvcConfigurer 類型的 @Configuration 類,但不添加 @EnableWebMvc。
自解:想在Spring Boot MVC基礎上擴展自定義MVC功能(攔截器、格式化程序、視圖控制器和其他功能),可以創建一個實現WebMvcConfigurer接口的類,此類必須標記為配置類(添加@Configuration注解),但是不能添加@EnableWebMvc注解

If you want to provide custom instances of RequestMappingHandlerMapping, RequestMappingHandlerAdapter, or ExceptionHandlerExceptionResolver, and still keep the Spring Boot MVC customizations, you can declare a bean of type WebMvcRegistrations and use it to provide custom instances of those components.
如果您想提供 RequestMappingHandlerMapping、RequestMappingHandlerAdapter 或 ExceptionHandlerExceptionResolver 的自定義實例,並且仍然保留 Spring Boot MVC 自定義,您可以聲明一個類型為 WebMvcRegistrations 的 bean 並使用它來提供這些組件的自定義實例。

WebMvcRegistrations需要依賴spring-boot-autoconfigure
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> </dependency>
If you want to take complete control of Spring MVC, you can add your own @Configuration annotated with @EnableWebMvc, or alternatively add your own @Configuration-annotated DelegatingWebMvcConfiguration as described in the Javadoc of @EnableWebMvc.
直譯:如果您想完全控制 Spring MVC,您可以添加您自己的帶有 @EnableWebMvc 注釋的 @Configuration,或者添加您自己的 @Configuration-annotated DelegatingWebMvcConfiguration
自解:想完全重寫Spring MVC,可以在自定義類上添加@EnableWebMvc注解

完全重寫Spring MVC的話SpringBoot對SpringMVC的自動配置會完全失效。所有Spring MVC配置都需要自己配置,不推薦使用
為什么添加@EnableWebMvc注解SpringBoot對SpringMVC的自動配置會完全失效
@Import(DelegatingWebMvcConfiguration.class) public @interface EnableWebMvc { }
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
@Configuration(proxyBeanMethods = false) @ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class }) @ConditionalOnMissingBean(WebMvcConfigurationSupport.class) @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10) @AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class }) public class WebMvcAutoConfiguration {
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class):容器中沒有這個組件的時候,自動配置類(WebMvcAutoConfiguration)才生效
