springboot的MVC配置原理
springboot现在是实现了mvc的自动配置,但是如果要修改/添加mvc的配置呢,比如上一篇的thymeleaf模板引擎,就自动配置了视图解析器,添加了前缀:classpath:/templates/
和后缀:.html
。这样 访问方法的映射路径时,就不用添加文件的路径和后缀名,但是如果访问的文件不在 tmplates文件夹下或者是你想要访问的文件后缀不是html,那么应该怎么重新修改mvc的配置呢?接下来进入官方文档看mvc扩展/修改的说明,如下图:
可以发现如果要扩展/修改 mvc配置 需要给自定义的mvc类添加 @Configuration注解 和 实现 WebMvcConfigurer接口,接下来用自定义视图解析器例子说明.
默认的视图解析器
springboot的自动装配的视图解析器是通过ContentNegotiatingViewResolver类
(上图的第一个)来实现的,如果要自定义视图解析器,就得进入这个类去了解,如下图:
可以发现该类实现了ViewResolver接口
,一般实现了视图解析器接口的类,都可以把它看作视图解析器,所以想要自定义视图解析器就需要实现该接口。ContentNegotiatingViewResolver类
是springboot自动装配的视图解析器,而且该类实现视图解析器的接口,所以关键是视图解析器的接口,所以进入到ViewResolver接口
可以发现里面包含一个resolveViewName()
方法,该方法的作用是解析视图。接下来返回ContentNegotiatingViewResolver
类中查看是怎么重写resolveViewName()
方法的,如下图:
核心是红框部分,getCandidateViews()
方法是获取所有的候选视图,该方法里面是循环所有的视图解析器,然后通过视图解析器去获取所有视图并添加到视图候选区;getBestView()
是从候选区中获取最好的视图,最后返回最好的视图,接下来实现自定义视图解析器。
自定义视图解析器
首先在自己创建的mvc配置类里面创建一个静态类去实现视图解析器的ViewResolver接口
,然后重写里面的方法,如下:
/**
* 扩展mvc,如果你想要diy一些定制化的功能,只要写这个组件,然后将它交给springboot,springboot会自动帮我们装配。
*/
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
//把视图解析器放入ioc容器中才会生效
@Bean
public ViewResolver myViewResolve(){
return new MyViewResolve();
}
//自定义一个自己的视图解析器,并重写里面的方法
public static class MyViewResolve implements ViewResolver{
@Override
public View resolveViewName(String viewName, Locale locale) throws Exception {
return null;
}
}
}
然后测试一下,自己自定义的视图解析器是否生效了,如下:
所有请求都会经过DispatcherServlet类
的doDispatch()
方法,所以在doDispatch()打断点,如下图:
可以发现是可以识别到自定义的视图解析器。
springboot的MVC扩展
要想扩展mvc,根据官方文档说明,如下图:
扩展mvc的配置类,必须实现WebMvcConfigurer接口
和添加@Configuration注解
,但是不能添加@EnableWebMvc
注解,因为添加该注解会让springboot的mvc自动配置失效,如下:
上图是springmvc自动配置的类,上面红框部分是一个条件,如果该WebMvcConfigurationSupport类
不存在则当前自动配置生效,这个类和@EnableWebMvc
注解有联系的,进入到@EnableWebMvc
注解里面,如下:
该注解导入了一个类,在进入到该类,如下:
可以发现该类继承了WebMvcConfigurationSupport
类,所以所以添加了@EnableWebMvc
注解就相当于添加了WebMvcConfigurationSupport
类,而mvc自动配置的类启动条件@ConditionalOnMissingBean
中,是规定不能存在WebMvcConfigurationSupport
类,存在则webMvc自动配置类失效。
所以官网 强调 自定义扩展mvc,不能添加@EnableWebMvc
注解。
上面的自定义视图解析器就是mvc扩展的一个例子,接下来在使用一个例子说明,mvc是如何扩展的,如下:
/**
* 扩展mvc
*/
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
//视图跳转
@Override
public void addViewControllers(ViewControllerRegistry registry) {
//返回/abc会跳转到test.html
registry.addViewController("/abc").setViewName("test");
}
}
访问结果如下:
访问abc映射路径,只有测试两字,而访问原来的test映射路径,多了一些值,是因为,该test映射路径里面添加了值。
该扩展是一个视图跳转,通常默认是浏览器访问是访问controller层的映射,但是这里添加了额外的映射,访问/abc会映射test.html视图。
总结
自定义配置类,必须实现WebMvcConfigurer接口
和添加@Configuration注解
和属性类xxProperties,并且配置类要添加一些配置类的启动条件@ConditionalXX
和添加@EnableConfigurationProperties注解启动对应的属性类xxProperties。