我有一个相当老的 Java 8 / Spring 应用程序,它提供了一个 REST API。响应以 JSON 或 XML 格式发送,具体取决于 Accept Header。
所以例如
- application/json-v1 将响应转换为响应对象版本 1 的 JSON
- application/json-v2 - 将响应转换为响应对象版本 1 的 JSON
- application/xml-v1 - 将响应转换为响应对象版本 1 的 XML
该应用程序现在在 Spring 5 中,但最初是在 Spring3 中,并且这方面从未转换为使用代码配置。
所以核心配置 XML 有这个
<!-- Enables the Spring MVC @Controller programming model, and set converters in use -->
<mvc:annotation-driven>
<message-converters>
<beans:bean class="com.packagpath.AppJaxb2RootElementHttpMessageConverter">
<beans:property name="supportedMediaTypes">
<beans:list>
<beans:bean class="org.springframework.http.MediaType">
<beans:constructor-arg index="0" value="application"/>
<beans:constructor-arg index="1" value="xml"/>
</beans:bean>
<beans:bean class="org.springframework.http.MediaType">
<beans:constructor-arg index="0" value="application"/>
<beans:constructor-arg index="1" value="xml-v1"/>
</beans:bean>
<beans:bean class="org.springframework.http.MediaType">
<beans:constructor-arg index="0" value="application"/>
<beans:constructor-arg index="1" value="xml-v2"/>
</beans:bean>
</beans:list>
</beans:property>
</beans:bean>
<beans:bean class="com.packagpath.AppMappingJackson2HttpMessageConverter">
<beans:property name="supportedMediaTypes">
<beans:list>
<beans:bean class="org.springframework.http.MediaType">
<beans:constructor-arg index="0" value="application"/>
<beans:constructor-arg index="1" value="json"/>
</beans:bean>
<beans:bean class="org.springframework.http.MediaType">
<beans:constructor-arg index="0" value="application"/>
<beans:constructor-arg index="1" value="json-v1"/>
</beans:bean>
<beans:bean class="org.springframework.http.MediaType">
<beans:constructor-arg index="0" value="application"/>
<beans:constructor-arg index="1" value="json-v2"/>
</beans:bean>
</beans:list>
</beans:property>
</beans:bean>
<beans:bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
</message-converters>
</mvc:annotation-driven>
<beans:bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
</beans:bean>
控制器具有沿着这些线设置的生产属性
@RequestMapping(method = RequestMethod.GET, value = AppController.RESOURCE_NAME + "/{id}", produces = {
XML_MIME_TYPE_DEFAULT, JSON_MIME_TYPE_DEFAULT, XML_MIME_TYPE_V1, JSON_MIME_TYPE_V1,
XML_MIME_TYPE_V2, JSON_MIME_TYPE_V2 })
@ResponseBody
public Person getAccount(@PathVariable(value = "id") String id, HttpServletRequest request) { ...
JSON处理程序的主要覆盖类是沿着这些线......
public class AppMappingJackson2HttpMessageConverter extends MappingJackson2HttpMessageConverter {
private Utils utils = new Utils();
/**
* Init method must be called to ensure the object mapper used by this converter ignores null fields.
*/
@PostConstruct
public void init() {
System.out.println("init 1");
getObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL);
System.out.println("init 2");
}
//
@Override
protected void writeInternal(Object responseObject, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
System.out.println("VersionConversion versionConversion");
...
所以设置了场景。XML 版本运行良好。
public class AppJaxb2RootElementHttpMessageConverter extends Jaxb2RootElementHttpMessageConverter {
private Utils utils = new Utils();
@Override
protected void writeToResult(Object responseObject, HttpHeaders headers, Result result) throws IOException {
VersionConversion versionConversion = AnnotationUtils.findAnnotation(responseObject.getClass(), VersionConversion.class);
...
基本配置似乎适用于 JSON 消息处理程序,就好像我将配置的 Mime 类型放在标头中一样,它会返回 JSON 文档,但如果我放置不存在的版本,则会引发错误。
但是 writeInternal 方法永远不会被调用,因此永远不会到达任何版本更改代码。我从几个角度看了这个,我不知道为什么。笨拙的 Init 1、init2 打印语句将输出到控制台。我确信它曾经可以工作,但我现在看不出有什么不同,而且因为它都是在 Spring 中连接的,所以除了查看错误代码之外,我不知道如何进一步调查!
如果有人知道问题可能是什么,那就太好了,尽管目前我不确定如何以及在哪里进行调查,因为a)代码肯定曾经工作过,b)我在配置中看不到任何错误已经改变。我想知道这是否是我当时没有注意到的依赖关系的变化?