org.springframework.core.ParameterizedTypeReference
是 Spring 3.2 之后新增的类,使用 RestTemplate
请求数据反序列化的时候,通过该类可以保留泛型。
Spring 对 Jackson 是默认支持的,当 classpath 下有 Jackson 的时候,Spring 会使用 Jackson 进行反序列化,但是配合 ParameterizedTypeReference
的时候有个”bug”,假如请求到的 json 数据里面的字段比 目标 bean 里面的字段多,就会报一下的异常:
1 | Caused by: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "..." |
这里只测试了 3.2.18.RELEASE
、4.0.7.RELEASE
、4.2.9.RELEASE
都存在该问题,到目前为止Spring4的最后一个版本4.3.9.RELEASE
则没有该问题。
如果公司的Spring 版本在 3.2 ~ 4.2 之间徘徊,并且不考虑升级Spring版本的话,接下来内容可能会对您有用。
默认的 Message Converters
通过 RestTemplate 的构造方法可以大致了解一下 其默认的 Message Converters。
1 | public RestTemplate() { |
Message Convert(消息格式转换) 的时候会从前到后,通过Content-Type
来匹配使用哪个转换器来转换
1 | for (HttpMessageConverter<?> messageConverter : this.messageConverters) { |
接下来会通过 new ParameterizedTypeReference<List<GithubGistVO>>() {};
来保留泛型,MappingJackson2HttpMessageConverter 前面的 Converter 都没有实现 GenericHttpMessageConverter,所以会通过 MappingJackson2HttpMessageConverter 来反序列化请求到的json数据。
自定义 Jackson 配置
json数据与Bean字段不一致报错,实际上是 Jackson 的配置问题,自定义 Jackson 配置,覆盖 Spring 的默认配置即可。
创建 MyObjectMapper 继承 ObjectMapper:
1 | package xyz.kail.blog.test.resttemplate; |
Spring 配置
1 | <bean id="mappingJackson2HttpMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> |
修改 RestTemplate Message Converters
1 | <bean id="restTemplate" class="org.springframework.web.client.RestTemplate"> |
上面这个配置(RestTemplate.setMessageConverters)实际上存在一个问题,除非把所默认的MessageConverters再配置一遍,否则setMessageConverters(List<HttpMessageConverter<?>> messageConverters)
实际上会覆盖掉所有默认MessageConverters。
如何添加自定义的 MessageConverter 而不清除默认的MessageConverters呢?这里创建 MyRestTemplate 继承 RestTemplate:
1 | package xyz.kail.blog.test.resttemplate; |
这里把新的自定义的 MessageConverters 放到默认的前面,如果Content-Type
是application/json
,会先匹配到自定的MessageConverters。
国产的 fastjson
如果确定了系统中的交互只是 json的形式,实际上覆盖掉默认的也未尝不可。这里使用 fastjson 作为 MessageConverter:
1 | <bean id="restTemplate" class="org.springframework.web.client.RestTemplate"> |
fastjson 的序列化配置这里就不说,相比 jackson 的配置要简单许多,实际上fastjson的默认配置已经很符合中国国情了。
RestTemplate 使用
1 | public class Main { |
1 | public class GithubGistVO { |