這幾天的開發過程當中,須要修改原有同事寫的項目,原項目採用的是springboot寫的後端服務,json序列化使用原始jackson進行,並在配置文件的properties文件中聲明瞭jackson的一些基本配置html
# Json spring.jackson.time-zone=GMT+8 spring.jackson.date-format=yyyy-MM-dd HH:mm:ss spring.jackson.property-naming-strategy=SNAKE_CASE spring.jackson.deserialization.READ_UNKNOWN_ENUM_VALUES_AS_NULL=true
起初在沒有加入項目的攔截器LoginInterceptor的時候,按照項目配置文件的配置,postman請求時採用屬性爲下劃線的形式並不會報錯,並且在序列化時間類型的屬性時也不會出現時間格式化出問題的狀況。開始對項目進行改造以後增長了登錄驗證。並在springboot項目啓動的時候增長了Webconfig來向程序註冊攔截器java
@Configuration public class WebConfig extends WebMvcConfigurationSupport { // 關鍵,將攔截器做爲bean寫入配置中 @Autowired private LoginInterceptor loginInterceptor; @Override protected void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(loginInterceptor).addPathPatterns("/**"); // 上傳圖片的路徑除外 super.addInterceptors(registry); } }
作完這些以後,準備調試程序時發現,用原有的報文請求程序的接口的時候老是報錯。首先是時間類型轉換失敗,報錯信息以下:web
Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Can not deserialize value of type java.util.Date from String "2018-06-12 12:00:00": not a valid representation (error: Failed to parse Date value '2018-06-12 12:00:00': Can not parse date "2018-06-12 12:00:00": while it seems to fit format 'yyyy-MM-dd'T'HH:mm:ss.SSS', parsing fails (leniency? null)); nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Can not deserialize value of type java.util.Date from String "2018-06-12 12:00:00": not a valid representation (error: Failed to parse Date value '2018-06-12 12:00:00': Can not parse date "2018-06-12 12:00:00": while it seems to fit format 'yyyy-MM-dd'T'HH:mm:ss.SSS', parsing fails (leniency? null)) at [Source: java.io.PushbackInputStream@7688ebdb; line: 1, column: 281] (through reference chain: com.hlt.cloudoak.base.ForeignApplication["order"]->com.hlt.cloudoak.base.ForeignApplication$Order["notification"]->com.hlt.cloudoak.base.ForeignApplication$Order$Notification["date"]->com.hlt.cloudoak.base.ForeignApplication$Order$Notification$HappenDate["notify"])
而後經過一通查資料,最終在Model的屬性上增長了@JsonFormat註解得以解決了這個時間格式化錯誤的問題。spring
可是事情並無完,雖然解決了時間格式化報錯的問題。可是使用下劃線形式的Json請求接口依舊行不通,轉化失敗。程序拿不到對應屬性的值。因而又是一頓某度和某歌的翻找。json
最後在WebConfig類的實現中增長了代碼,才使得原有的項目依舊得以採用下劃線形式的Json,而且時間格式化時也並不會出錯,最終代碼以下:後端
@Configuration public class WebConfig extends WebMvcConfigurationSupport { // 關鍵,將攔截器做爲bean寫入配置中 @Autowired private LoginInterceptor loginInterceptor; @Override protected void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(loginInterceptor).addPathPatterns("/**"); // 上傳圖片的路徑除外 super.addInterceptors(registry); } @Bean public MappingJackson2HttpMessageConverter customJackson2HttpMessageConverter() { MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter(); ObjectMapper objectMapper = new ObjectMapper(); objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); objectMapper.configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL, true); objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE); objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8")); objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); jsonConverter.setObjectMapper(objectMapper); return jsonConverter; } @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { converters.add(customJackson2HttpMessageConverter()); super.addDefaultHttpMessageConverters(converters); } }
資料上講,自定義WebMvcConfigur以後,原有properties中的jackson配置會失效。因此必須在自定義實現類中再次對jackson的配置進行補充。查詢資料的過程當中,看到有的文章提到須要將註解@EnableWebMvc
去掉。可是咱們的項目中並不顯式的包含這個註解,相信可能有部分人跟我同樣在看到這個解決方案時並不知道如何對項目進行更改。下面貼一下官方的一段話來解釋一下WebMvcConfigurationSupport類:api
public class WebMvcConfigurationSupport
extends Object
implements ApplicationContextAware, ServletContextAware
@EnableWebMvc
to an application
@Configuration
class. An alternative more advanced option is to extend directly from this class and override methods as necessary remembering to add
@Configuration
to the subclass and
@Bean
to overridden
@Bean
methods. For more details see the Javadoc of
@EnableWebMvc
.
This class registers the following HandlerMapping
s:springboot
RequestMappingHandlerMapping
ordered at 0 for mapping requests to annotated controller methods.HandlerMapping
ordered at 1 to map URL paths directly to view names.BeanNameUrlHandlerMapping
ordered at 2 to map URL paths to controller bean names.HandlerMapping
ordered at Integer.MAX_VALUE-1
to serve static resource requests.HandlerMapping
ordered at Integer.MAX_VALUE
to forward requests to the default servlet.Registers these HandlerAdapter
s:mvc
RequestMappingHandlerAdapter
for processing requests with annotated controller methods.HttpRequestHandlerAdapter
for processing requests with HttpRequestHandler
s.SimpleControllerHandlerAdapter
for processing requests with interface-based Controller
s.Registers a HandlerExceptionResolverComposite
with this chain of exception resolvers:oracle
ExceptionHandlerExceptionResolver
for handling exceptions through @ExceptionHandler
methods.ResponseStatusExceptionResolver
for exceptions annotated with @ResponseStatus
.DefaultHandlerExceptionResolver
for resolving known Spring exception typesRegisters an AntPathMatcher
and a UrlPathHelper
to be used by:
RequestMappingHandlerMapping
,HandlerMapping
for ViewControllersHandlerMapping
for serving resourcesNote that those beans can be configured with a PathMatchConfigurer
.
Both the RequestMappingHandlerAdapter
and the ExceptionHandlerExceptionResolver
are configured with default instances of the following by default:
ContentNegotiationManager
DefaultFormattingConversionService
OptionalValidatorFactoryBean
if a JSR-303 implementation is available on the classpathHttpMessageConverter
s depending on the third-party libraries available on the classpath.