官方文檔
29.1.1 Spring MVC Auto-configuration
Spring Boot provides auto-configuration for Spring MVC that works well with most applications.
The auto-configuration adds the following features on top of Spring’s defaults:
- Inclusion of
ContentNegotiatingViewResolver
andBeanNameViewResolver
beans.- 自動配置ViewResolver(視圖解析器:根據方法的返回值獲得視圖對象(View),視圖對象決定如何渲染(轉發?重定向?))
- ContentNegotiatingViewResolver組合了所有的視圖解析器
- 如何定制?我們只需要給容器添加一個視圖解析器,自動回將其組合進來
- Support for serving static resources, including support for WebJars (covered later in this document)).
- Automatic registration of
Converter
,GenericConverter
, andFormatter
beans.- Converter:轉換器,比如public String test(User user);表單中傳入的數字,true/false等都是文本,這些文本需要映射到User中,需要轉換器,進行類型轉換,將text(數字)-->int/integer,text(true)-->bool
Formatter
:格式化,2017/0/101--->Date
- Support for
HttpMessageConverters
(covered later in this document).- HttpMessageConverters:是SpringMVC用來http請求和響應的,比如將User--->json返回
- HttpMessageConverters是從容器中確定的
- Automatic registration of
MessageCodesResolver
(covered later in this document). - Static
index.html
support. - Custom
Favicon
support (covered later in this document). - Automatic use of a
ConfigurableWebBindingInitializer
bean (covered later in this document).
Spring Boot擴展 SpringMVC功能
在spring MVC中,我們可以編寫xml來配置我們需要的一些功能,比如攔截器等等。
you can add your own @Configuration
class of type WebMvcConfigurer
but without @EnableWebMvc
我們可以在類型是WebMvcConfigurer的類上使用@Configuration注解,並且實現我們需要的方法;
class MyInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("test"); return false; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } } @Configuration public class MyMvcConfig implements WebMvcConfigurer{ //不需要實現WebMvcConfigurer了 @Bean public WebMvcConfigurer webMvcConfigurer(){ WebMvcConfigurer webMvcConfigurer = new WebMvcConfigurer(){ @Override public void addInterceptors(InterceptorRegistry registry) { //攔截所有的請求,springboot幫我們已經做好了靜態資源映射,所以我們可以不加excludePathPatterns("/static/**"),但是如果出現被攔截了,那就手動放行 registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**").excludePathPatterns("/login").excludePathPatterns("/static/**"); } }; return webMvcConfigurer; } }
測試的時候,直接實現方法也是可以的。所以上面的 MyMvcConfig就不需要實現 WebMvcConfigurer 方法了
@Configuration public class MyMvcConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new MyInterceptor()).addPathPatterns("/xx"); } }
Spring Boot全面接管SpringMVC功能
@EnableWebMvc @Configuration public class MyMvcConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { } }
為什么加上@EnableWebMvc注解后spring mvc就是失效了呢?
1、導入DelegatingWebMvcConfiguration
@Import(DelegatingWebMvcConfiguration.class) public @interface EnableWebMvc { }
2、DelegatingWebMvcConfiguration 繼承了 WebMvcConfigurationSupport
@Configuration public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
3、查看 WebMvcAutoConfiguration 源碼
@Configuration @ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class }) //條件判斷,組件中有沒有WebMvcConfigurationSupport,沒有才自動配置 @ConditionalOnMissingBean(WebMvcConfigurationSupport.class) @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10) @AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class }) public class WebMvcAutoConfiguration {
不需要經過controller
@Configuration public class MvcConfig implements WebMvcConfigurer { public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/home").setViewName("home"); registry.addViewController("/").setViewName("home"); registry.addViewController("/hello").setViewName("hello"); registry.addViewController("/login").setViewName("login"); } }