Spring Boot 學習筆記(二)—— WEB相關配置
一、前言
上次我們快速搭建了一個Spring Boot專案,我們只需新增業務邏輯就能直接執行訪問了,說明Spring Boot已經自動為我們做完了配置工作,這次我們就來看看具體是哪些工作,如果我們想接管配置又該怎麼做。
二、WEB相關配置
檢視WebMvcAutoConfiguration
和WebMvcProperties
的原始碼,可以發現Spring MVC全域性配置以spring.mvc
開頭,而Spring Boot提供瞭如下配置
1.自動配置的ViewResolver
1)ContentNegotiatingViewResolver
優先順序最高,自己不處理View,而是將View代理給其他ViewResolver處理
@Bean
@ConditionalOnBean(ViewResolver.class)
@ConditionalOnMissingBean(name = "viewResolver", value = ContentNegotiatingViewResolver.class)
public ContentNegotiatingViewResolver viewResolver(BeanFactory beanFactory) {
ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
resolver.setContentNegotiationManager(
beanFactory.getBean(ContentNegotiationManager.class));
// ContentNegotiatingViewResolver uses all the other view resolvers to locate
// a view so it should have a high precedence
resolver.setOrder(Ordered.HIGHEST_PRECEDENCE);
return resolver;
}
2)BeanNameViewResolver
根據Controller中方法的返回值來查詢ViewResolver處理View
@Bean
@ConditionalOnBean(View.class)
@ConditionalOnMissingBean
public BeanNameViewResolver beanNameViewResolver() {
BeanNameViewResolver resolver = new BeanNameViewResolver();
resolver.setOrder(Ordered.LOWEST_PRECEDENCE - 10);
return resolver;
}
3)InternalResourceViewResolver
這個很常見了,設定檢視路徑前後綴
@Bean
@ConditionalOnMissingBean
public InternalResourceViewResolver defaultViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix(this.mvcProperties.getView().getPrefix());
resolver.setSuffix(this.mvcProperties.getView().getSuffix());
return resolver;
}
上篇文章我們添加了Thymeleaf,就自動為我們配置了前後綴。
2.自動配置的靜態資源
在addResourceHandlers
方法中可以看到有以下靜態資源的配置
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
return;
}
Integer cachePeriod = this.resourceProperties.getCachePeriod();
if (!registry.hasMappingForPattern("/webjars/**")) {
//對映webjar路徑為 /webjars/**,可直接訪問,有關webjar的內容可訪問 www.webjars.org
customizeResourceHandlerRegistration(
registry.addResourceHandler("/webjars/**")
.addResourceLocations(
"classpath:/META-INF/resources/webjars/")
.setCachePeriod(cachePeriod));
}
String staticPathPattern = this.mvcProperties.getStaticPathPattern();
if (!registry.hasMappingForPattern(staticPathPattern)) {
//將"classpath:/META-INF/resources/", "classpath:/resources/","classpath:/static/", "classpath:/public/",統統對映為 "/**",可以直接訪問
customizeResourceHandlerRegistration(
registry.addResourceHandler(staticPathPattern)
.addResourceLocations(
this.resourceProperties.getStaticLocations())
.setCachePeriod(cachePeriod));
}
}
3.自動配置Formatter和Converter
檢視Formatter配置原始碼
@Override
public void addFormatters(FormatterRegistry registry) {
for (Converter<?, ?> converter : getBeansOfType(Converter.class)) {
registry.addConverter(converter);
}
for (GenericConverter converter : getBeansOfType(GenericConverter.class)) {
registry.addConverter(converter);
}
for (Formatter<?> formatter : getBeansOfType(Formatter.class)) {
registry.addFormatter(formatter);
}
}
可以看到只要我們定義了Converter
、GenericConverter
、Formatter
實現類的Bean,就會自動註冊到Spring MVC中。
4.自動配置的HttpMessageConverter
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.addAll(this.messageConverters.getConverters());
}
除了預設的StringHttpMessageConverter
、ByteArrayHttpMessageConverter
等,Spring MVC預設使用MappingJackson2HttpMessageConverter
和MappingJackson2XmlHttpMessageConverter
,如果要新增自定義的HttpMessageConverter
,只需定義一個HttpMessageConverters
的bean即可
5.靜態首頁支援
private WelcomePageHandlerMapping(Resource welcomePage,
String staticPathPattern) {
if (welcomePage != null && "/**".equals(staticPathPattern)) {
logger.info("Adding welcome page: " + welcomePage);
ParameterizableViewController controller = new ParameterizableViewController();
controller.setViewName("forward:index.html");
setRootHandler(controller);
setOrder(0);
}
}
在以下目錄放置index.html
會自動設為首頁
- classpath:/META-INF/resources/
- classpath:/resources/
- classpath:/static/
- classpath:/public/
三、接管Spring Boot的WEB配置
如果要完全接管Web配置,只需新建一個配置類(註解@Configuration
@EnableWebMvc
),然後就能實現自己完全控制的Spring MVC。如果要保留自動配置並新增額外配置的話也很簡單,定義一個配置類(註解@Configuration
,不需要 @EnableWebMvc
)繼承WebMvcConfigurerAdapter
,就能在保留自動配置的基礎上新增自己想要的配置了,以下是個小例子
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter{
@Override
public void addViewControllers(ViewControllerRegistry registry) {
//此方法不會覆蓋自動配置,而是額外新增
registry.addViewController("/login").setViewName("/login");
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
//配置fastjson替換jackson
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter ();
StringHttpMessageConverter stringConverter = new StringHttpMessageConverter();
stringConverter.setDefaultCharset(Charset.forName("UTF-8"));
FastJsonConfig config = new FastJsonConfig();
config.setSerializerFeatures(SerializerFeature.PrettyFormat,
SerializerFeature.DisableCircularReferenceDetect);
converter.setFastJsonConfig(config);
//新增字串解析器,防止返回字串時多出雙引號
converters.add(stringConverter);
converters.add(converter);
}
}
四、註冊Servlet、Filter、Listener
將Servlet
、Filter
、Listener
宣告為Bean,或者註冊ServletRegistrationBean
、FilterRegistrationBean
、ServletListenerRegistrationBean
的Bean
//直接註冊Bean
@Bean
public XxServlet xxServlet(){
return new XxServlet();
}
@Bean
public XxServlet xxServlet(){
return new XxServlet();
}
@Bean
public XxFilter xxFilter(){
return new XxFilter();
}
//通過RegistrationBean註冊
@Bean
public ServletRegistrationBean servletRegistrationBean(){
return new ServletRegistrationBean(new XxServlet(),"/xx/*");
}
@Bean
public FilterRegistrationBean filterRegistrationBean(){
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(new YyFilter());
registrationBean.setOrder(2);
return registrationBean;
}
@Bean
public ServletListenerRegistrationBean<ZzListener> zzListenerServletRegistrationBean(){
return new ServletListenerRegistrationBean<ZzListener>(new ZzListener());
}
五、總結
本文介紹了Spring Boot關於Spring MVC的自動配置項,這樣我們在開發時也能根據業務需要手動修改配置,以實現我們想要的功能。
參考文獻:
《javaee開發的顛覆者 Spring Boot實戰》