0

我们的 Spring 3.1 应用程序以下列方式使用消息转换器:

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
     ....
     ....
    <property name="messageConverters">
        <list>
            <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <property name="writeAcceptCharset" value="false"/>
            </bean>
            <bean class="org.springframework.http.converter.ResourceHttpMessageConverter"/>
            <bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"/>
            <bean class="org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter"/>
            <bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"/>
            <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
            <bean class="org.springframework.http.converter.feed.AtomFeedHttpMessageConverter"/>
        </list>
    </property>
</bean>
<bean class="org.codehaus.jackson.map.ObjectMapper" name="objectMapper"/>

在我的一个控制器中,我有一个 RequestMapping :

@RequestMapping(value = "pathFoo", produces = MediaType.APPLICATION_ATOM_XML_VALUE)
public @ResponseBody Feed getFooAtomXML(HttpServletRequest request, HttpServletResponse response){

但似乎除非我指定请求标头 Accept=application/atom+xml,否则响应会以 JSON 而不是 XML 的形式返回。无论请求标头是否存在,如何配置应用程序以便在此映射中使用 AtomFeedHttpMessageConverter?

我需要依赖 ViewResolver 吗?

4

1 回答 1

3

这里的问题是bean 按照声明的顺序AnnotationMethodHandlerAdapter遍历您的 bean 列表。HttpMessageConverter

它首先调用canWrite(Class, MediaType)每个方法HttpMessageConverter并使用第一个返回的方法true

如果不提供Accept标头 as application/atom+xml,则将在有机会之前先MappingJacksonHttpMessageConverter返回。发生这种情况有两个原因。trueAtomFeedHttpMessageConverter

  1. 如果没有Accept提供 header,Spring 认为所有MediaType的 s 都是可以接受的。
  2. MappingJacksonHttpMessageConverter接受application/json内容类型

这是因为MappingJacksonHttpMessageConverter实现为

@Override
public boolean canWrite(Class<?> clazz, MediaType mediaType) {
    return (this.objectMapper.canSerialize(clazz) && canWrite(mediaType));
         // ^ will pretty much always return true    ^ application/json
}

因此,由于可接受的媒体类型包括所有内容,因此MappingJacksonHttpMessageConverter将能够产生响应,而 Spring 将选择它。

要改变这一点,要么改变 bean 的顺序

<property name="messageConverters">
    <list>
        <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
        <bean class="org.springframework.http.converter.StringHttpMessageConverter">
            <property name="writeAcceptCharset" value="false"/>
        </bean>
        <bean class="org.springframework.http.converter.ResourceHttpMessageConverter"/>
        <bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"/>
        <bean class="org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter"/>
        <bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"/>
        <bean class="org.springframework.http.converter.feed.AtomFeedHttpMessageConverter"/>
        <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
    </list>
</property>

或者提供AcceptHTTP 规范指定的标头。

或移至使用RequestMappingHandlerAdapter代替AnnotationMethodHandlerAdapter(已弃用)的 Spring 3.2,但默认情况下也会注册AtomFeedHttpMessageConverter之前的MappingJacksonHttpMessageConverter

于 2013-10-16T19:55:14.213 回答