1

我有一个相当老的 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)我在配置中看不到任何错误已经改变。我想知道这是否是我当时没有注意到的依赖关系的变化?

4

0 回答 0