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

想要使用Spring 4在我的REST服务中使用JSONP;
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服务。


点击以下URL将以json格式提供数据

 /contextRoot/info/1?formatType=json

点击以下URL将以xmlformat格式提供数据

 /contextRoot/info/1?formatType=xml

点击以下网址可得到406 EXCEPTION

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



观察结果

在进行调查时,发现MappingJackson2HttpMessageConverter
不支持应用程序/ javascript。

由于Spring 4声称支持JSONP,因此对此感到惊讶。

此外,MappingJackson2JsonView确实支持JSONP。



我是否丢失了配置中的某些内容,一旦添加,它将使我可以在SPRING 4中为JSONP使用现成的内容类型application / javascript?

编辑

这是我的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并返回406错误

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


它只会使我的应用程序像下面那样理解请求URL并返回JSONP响应:

   /contextRoot/info/1?param1=callback1

最佳答案

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

MappingJackson2HttpMessageConverter支持"application/json""*+json"媒体类型,但不支持"application/javascript"。如果确实如此,那么您希望它能够解析javascript代码,事实并非如此。

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

您当前的配置正在禁用使用H​​TTP Accept标头的内容协商(为什么?)。为了支持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


就您而言,您应该:


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


有关实现的更多详细信息,请参见AbstractJsonpResponseBodyAdvice

07-24 09:46
查看更多