Spring 4: MappingJackson2HttpMessageConverter 不支持 jsonp application/javascript

Spring 4: MappingJackson2HttpMessageConverter does not support application/javascript for jsonp

使用 Spring 4.1.6.RELEASE 和 Jackson 库 v2.5.4

想在我的 REST 服务中使用 JSONP Spring 4; Spring 4 开箱即用地支持 JSONP。

配置

<mvc:annotation-driven
    content-negotiation-manager="contentNegotiationManager">
...
</mvc:annotation-driven>

按以下方式使用 contentNegotiationManager

<bean id="contentNegotiationManager"
    class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">

    <property name="defaultContentType" value="application/json" />


    <!-- Configuration of Path Extension Based ContentNegotiationStrategy -->
    <property name="favorPathExtension" value="false" />

    <!-- Configuration of Request Parameter Based ContentNegotiationStrategy -->
    <property name="favorParameter" value="true" />
    <property name="parameterName" value="formatType" />
    <property name="mediaTypes" ref="mediaTypesMapping" />
    <!-- Configuration of HTTP ACCEPT Header Based ContentNegotiationStrategy -->
    <property name="ignoreAcceptHeader" value="true" />

</bean>

这是 MediaTypeMapping

<util:map id="mediaTypesMapping">
    <entry key="json" value="application/json" />
    <entry key="xml" value="application/xml" />
    <entry key="jsonp" value="application/javascript" />
</util:map>

这里是 jsonpParameterNames

<util:set id="jsonpParameterNames">
    <value>param1</value>
    <value>param2</value>
    <value>param3</value>
</util:set>

部署了我的 REST 服务。

观察结果

调查发现MappingJackson2HttpMessageConverter 不支持 application/javascript.

对此感到惊讶,因为 Spring 4 声称支持开箱即用的 JSONP。

此外,MappingJackson2JsonView 确实支持开箱即用的 JSONP。

问题

我是否遗漏了配置中的某些内容,一旦添加,我就可以使用开箱即用的内容类型 application/javascript 和 SPRING 4 for JSONP?

编辑

这是我的 ControllerAdvice 配置:

<bean id="jsonpAdvice"
    class="com.advice.AccountServiceControllerJsonpAdvice">
    <constructor-arg ref="jsonpParameterNames" />
</bean>

这里是 ControllerAdvice

 public class AccountServiceControllerJsonpAdvice extends
    AbstractJsonpResponseBodyAdvice {

private String[] callbackList = {"callback"};

public String[] getCallbackList() {
    return callbackList;
}

public void setCallbackList(String[] callbackList) {
    this.callbackList = callbackList;
}

public AccountServiceControllerJsonpAdvice(String... callbackList) {
    super(callbackList);
}
}

但是,这并不能使我的应用程序理解 URL 和 return 406 错误

   /contextRoot/info/1?formatType=jsonp&param1=callback1

它只会让我的应用程序理解如下请求 URL 和 return JSONP 响应:

   /contextRoot/info/1?param1=callback1

是的,Spring 4.1+支持JSONP,但它本身并不是一种转换格式。

MappingJackson2HttpMessageConverter支持"application/json""*+json"媒体类型,但不支持"application/javascript"。如果是这样,那么您会期望它 解析 javascript 代码,但事实并非如此.

在这里,我们只是包装输出以使其成为 "application/javascript",但实际上,它仍然是 JSON。

您当前的配置正在禁用与 HTTP Accept headers 的内容协商(为什么?)。为了支持 JSONP,你只需要在你的 MVC 配置中这样:

<mvc:annotation-driven/>

还有一个像这样的 ControllerAdvice (see reference documentation):

@ControllerAdvice
public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice {

    public JsonpAdvice() {
        super("callback");
    }
}

就是这样。

现在您将获得:

GET /contextRoot/info/1
// will return what's best depending on the Accept header sent by the client

GET /contextRoot/info/1.xml
// will return XML

GET /contextRoot/info/1.json
// will return JSON

GET /contextRoot/info/1.json?callback=myFunction
// will return JSONP wrapped in a "myFunction" call

对于你的情况,你应该:

  1. 从媒体类型映射中删除 "application/javascript",或者为了向后兼容,将 "jsonp""application/json" 媒体类型相关联。
  2. 使用GET /contextRoot/info/1?formatType=json&param1=callback1

有关实施的更多详细信息,请参阅 AbstractJsonpResponseBodyAdvice