springboot下MVC的MessageConverters和静态资源位置的配置
文章目錄
- 1. WebMvcConfigurationSupport、WebMvcConfigurer 區(qū)別
- 2. 自定義消息轉(zhuǎn)換器MessageConverters
- 3. 靜態(tài)資源
- 3.1 靜態(tài)資源位置
- 3.2 錯誤頁面
1. WebMvcConfigurationSupport、WebMvcConfigurer 區(qū)別
? ? ? ?springboot中我們通過繼承WebMvcConfigurerAdapter進行springmvc相關(guān)的配置,如攔截器、消息轉(zhuǎn)換、視圖解析器等。在springboot2.0后,該接口被廢棄,官方推薦直接implements WebMvcConfigurer ,或者extends WebMvcConfigurationSupport。
查看源碼發(fā)現(xiàn)@EnableWebMvc實際上引入了一個繼承WebMvcConfigurationSupport的DelegatingWebMvcConfiguration。
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented @Import(DelegatingWebMvcConfiguration.class) public @interface EnableWebMvc { } @Configuration public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport然后查看WebMvcAutoConfiguration的源碼發(fā)現(xiàn):
@Configuration @ConditionalOnWebApplication @ConditionalOnClass({ Servlet.class, DispatcherServlet.class,WebMvcConfigurerAdapter.class }) @ConditionalOnMissingBean(WebMvcConfigurationSupport.class) @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10) @AutoConfigureAfter({ DispatcherServletAutoConfiguration.class,ValidationAutoConfiguration.class }) public class WebMvcAutoConfiguration { ... }? ? ? ?@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})意思是如果存在它修飾的類的bean,則不需要再創(chuàng)建這個bean。由此可得出結(jié)論:如果有bean繼承了DelegatingWebMvcConfiguration,WebMvcConfigurationSupport,或者開啟了@EnableWebMvc,那么 @EnableAutoConfiguration 中的WebMvcAutoConfiguration 將不會被自動配置,而是使用自定義的WebMvcConfigurationSupport的配置。
總結(jié)
推薦前兩種方式
-
implements WebMvcConfigurer : 不會覆蓋@EnableAutoConfiguration關(guān)于WebMvcAutoConfiguration的配置。
-
extends WebMvcConfigurationSupport :會覆蓋@EnableAutoConfiguration關(guān)于WebMvcAutoConfiguration的配置。注意:使用WebMvcConfigurationSupport類配置攔截器時一定要重寫addResourceHandlers來實現(xiàn)靜態(tài)資源的映射
-
@EnableWebMvc : 等于擴展了WebMvcConfigurationSupport但是沒有重寫任何方法。
-
extends WebMvcConfigurerAdapter spring2.0不再建議使用,被廢棄。 官方推薦直接實現(xiàn)WebMvcConfigurer 。
2. 自定義消息轉(zhuǎn)換器MessageConverters
? ? ? ?以下配置代碼用于使用LocalDate,LocalTime ,LocalDateTime屬性接收前端傳來的標準時間字符串,并返回指定的時間格式,LocalDate對應(yīng) yyyy-MM-dd,LocalDateTime對應(yīng)yyyy-MM-dd HH:mm:dd,LocalTime對應(yīng) HH:mm:dd,不論參數(shù)的形式傳遞如body、pathVariable、requestParam里,只要時間字符串滿足格式要求都可以轉(zhuǎn)為對應(yīng)的時間日期屬性。
import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer; import com.jun.cloud.common.util.DateUtil; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.convert.converter.Converter; import org.springframework.format.FormatterRegistry; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.util.ObjectUtils; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import java.nio.charset.Charset; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.List;/*** WebMvc配置:* 1.消息轉(zhuǎn)換器的配置,提供Jackson的支持*/ @Configuration public class WebMvcConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {//對外提供的api接口驗證及追蹤日志//registry.addInterceptor(new RestApiInterceptor()).addPathPatterns("/api/**");}@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {//添加對swagger-ui的處理registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");//registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/static/");registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");}/*** 注意這里使用的是extendMessageConverters,這個方法不會覆蓋springmvc已默認添加的HttpMessageConverter*/@Overridepublic void extendMessageConverters(List<HttpMessageConverter<?>> converters) {converters.add(customerMappingJackson2HttpMessageConverter());converters.add(stringHttpMessageConverter());}@Beanpublic MappingJackson2HttpMessageConverter customerMappingJackson2HttpMessageConverter(){MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();messageConverter.setObjectMapper(customDateObjectMapper());return messageConverter;}@Beanpublic StringHttpMessageConverter stringHttpMessageConverter(){StringHttpMessageConverter stringConvert = new StringHttpMessageConverter();List<MediaType> stringMediaTypes = new ArrayList<MediaType>(){{add(new MediaType("text","plain",Charset.forName("UTF-8")));}};stringConvert.setSupportedMediaTypes(stringMediaTypes);return stringConvert;}@Overridepublic void addFormatters(FormatterRegistry registry) {registry.addConverter(localDateTimeConverter());registry.addConverter(localDateConverter());registry.addConverter(localTimeConverter());}/*** Json序列化和反序列化轉(zhuǎn)換器,用于轉(zhuǎn)換Post請求體中的json以及將我們的對象序列化為返回響應(yīng)的json*/@Beanpublic ObjectMapper customDateObjectMapper(){ObjectMapper objectMapper = new ObjectMapper();objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);objectMapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);//LocalDateTime系列序列化和反序列化模塊,繼承自jsr310,這里修改了日期格式JavaTimeModule javaTimeModule = new JavaTimeModule();javaTimeModule.addSerializer(LocalDateTime.class,new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DateUtil.DATE_FORMAT_yyyy_MM_dd_HH_mm_ss)));javaTimeModule.addSerializer(LocalDate.class,new LocalDateSerializer(DateTimeFormatter.ofPattern(DateUtil.DATE_FORMAT_yyyy_MM_dd)));javaTimeModule.addSerializer(LocalTime.class,new LocalTimeSerializer(DateTimeFormatter.ofPattern(DateUtil.DATE_FORMAT_HH_mm_ss)));javaTimeModule.addDeserializer(LocalDateTime.class,new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DateUtil.DATE_FORMAT_yyyy_MM_dd_HH_mm_ss)));javaTimeModule.addDeserializer(LocalDate.class,new LocalDateDeserializer(DateTimeFormatter.ofPattern(DateUtil.DATE_FORMAT_yyyy_MM_dd)));javaTimeModule.addDeserializer(LocalTime.class,new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DateUtil.DATE_FORMAT_HH_mm_ss)));objectMapper.registerModule(javaTimeModule);return objectMapper;}/*** LocalDate轉(zhuǎn)換器,用于轉(zhuǎn)換RequestParam和PathVariable參數(shù)*/private Converter<String, LocalDate> localDateConverter() {return new Converter<String, LocalDate>() {@Overridepublic LocalDate convert(String source) {if(!ObjectUtils.isEmpty(source)){return LocalDate.parse(source, DateTimeFormatter.ofPattern(DateUtil.DATE_FORMAT_yyyy_MM_dd));}return null ;}};}/*** LocalDateTime轉(zhuǎn)換器,用于轉(zhuǎn)換RequestParam和PathVariable參數(shù)*/private Converter<String, LocalDateTime> localDateTimeConverter() {return new Converter<String, LocalDateTime>() {@Overridepublic LocalDateTime convert(String source) {if(!ObjectUtils.isEmpty(source)) {return LocalDateTime.parse(source, DateTimeFormatter.ofPattern(DateUtil.DATE_FORMAT_yyyy_MM_dd_HH_mm_ss));}return null ;}};}/*** LocalTime轉(zhuǎn)換器,用于轉(zhuǎn)換RequestParam和PathVariable參數(shù)*/private Converter<String, LocalTime> localTimeConverter() {return new Converter<String, LocalTime>() {@Overridepublic LocalTime convert(String source) {if(!ObjectUtils.isEmpty(source)) {return LocalTime.parse(source, DateTimeFormatter.ofPattern(DateUtil.DATE_FORMAT_HH_mm_ss));}return null;}};}}注意implements WebMvcConfigurer后,要使用extendMessageConverters方法,這里通過@Bean的方式注入,也可以直接new一個如:
@Overridepublic void extendMessageConverters(List<HttpMessageConverter<?>> converters) {MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();messageConverter.setObjectMapper(customDateObjectMapper());converters.add(messageConverter);converters.add(stringHttpMessageConverter());}3. 靜態(tài)資源
3.1 靜態(tài)資源位置
? ? ? ?默認情況下,Spring Boot從classpath下的/static(/public,/resources或/META-INF/resources)文件夾,或從ServletContext根目錄提供靜態(tài)內(nèi)容。這是通過Spring MVC的ResourceHttpRequestHandler實現(xiàn)的,你可以自定義WebMvcConfigurerAdapter并覆寫addResourceHandlers方法來改變該行為(加載靜態(tài)文件),即上面的
@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");//添加對swagger-ui的處理registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");super.addResourceHandlers(registry);}? ? ? ?你可以設(shè)置spring.resources.staticLocations屬性自定義靜態(tài)資源的位置(配置一系列目錄位置代替默認的值),如果你這樣做,默認的歡迎頁面將從自定義位置加載,所以只要這些路徑中的任何地方有一個index.html,它都會成為應(yīng)用的主頁。
? ? ? ?此外,除了上述標準的靜態(tài)資源位置,有個例外情況是Webjars內(nèi)容。任何在/webjars/**路徑下的資源都將從jar文件中提供,只要它們以Webjars的格式打包。
3.2 錯誤頁面
? ? ? ?如果想為某個給定的狀態(tài)碼展示一個自定義的HTML錯誤頁面,你需要將文件添加到/error文件夾下。錯誤頁面既可以是靜態(tài)HTML(比如任何靜態(tài)資源文件夾下添加的),也可以是使用模板構(gòu)建的,文件名必須是明確的狀態(tài)碼或一系列標簽。
例如,映射404到一個靜態(tài)HTML文件,你的目錄結(jié)構(gòu)可能如下:
使用FreeMarker模板映射所有5xx錯誤,你需要如下的目錄結(jié)構(gòu):
src/main/java/<source code>resources/templates/error/5xx.ftl<other templates>對于更復(fù)雜的映射,你可以添加實現(xiàn)ErrorViewResolver接口的beans:
public class MyErrorViewResolver implements ErrorViewResolver {@Overridepublic ModelAndView resolveErrorView(HttpServletRequest request,HttpStatus status, Map<String, Object> model) {// Use the request or status to optionally return a ModelAndViewreturn ...}}你也可以使用Spring MVC特性,比如@ExceptionHandler方法和@ControllerAdvice,ErrorController將處理所有未處理的異常。
總結(jié)
以上是生活随笔為你收集整理的springboot下MVC的MessageConverters和静态资源位置的配置的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: truncate、drop、delete
- 下一篇: Mybatis的如何根据下划线_,百分号