有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Spring 4:MappingJackson2HttpMessageConverter不支持jsonp的应用程序/javascript

使用弹簧4.1.6。发行版和Jackson库v2。5.4

希望使用Spring4在我的REST服务中使用JSONP; Spring4支持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将以XML格式提供数据

     /contextRoot/info/1?formatType=xml
    
  • 点击下面的URL会出现406异常

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

观察结果

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

对此感到惊讶,因为Spring4声称支持JSONP开箱即用

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

问题

我是否在配置中遗漏了一些东西,这些配置一旦添加,将使我能够使用Spring4forJSONP的内容类型应用程序/javascript开箱即用

编辑

这是我的ControllerAdvice配置:

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

这是控制员的建议

 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

共 (1) 个答案

  1. # 1 楼答案

    是的,Spring4.1+支持JSONP,但它本身不是一种转换格式

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

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

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