Spring 4:MappingJackson2HttpMessageConverter 不支持 jsonp 的 application/javascript
Posted
技术标签:
【中文标题】Spring 4:MappingJackson2HttpMessageConverter 不支持 jsonp 的 application/javascript【英文标题】:Spring 4: MappingJackson2HttpMessageConverter does not support application/javascript for jsonp 【发布时间】:2015-09-19 03:13:43 【问题描述】:使用 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 会得到 xml 格式的数据
/contextRoot/info/1?formatType=xml
点击以下网址会出现 406 异常
/contextRoot/info/1?formatType=jsonp¶m1=callback1
观察
在做调查时,发现 MappingJackson2HttpMessageConverter 不支持应用程序/javascript。
对此感到惊讶,因为 Spring 4 声称支持开箱即用的 JSONP。
此外,MappingJackson2JsonView 确实支持开箱即用的 JSONP。
问题
我是否遗漏了配置中的某些内容,一旦添加后,我就可以通过 SPRING 4 开箱即用地使用内容类型 application/javascript 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 并返回 406 错误
/contextRoot/info/1?formatType=jsonp¶m1=callback1
它只会让我的应用程序理解如下请求 URL 并返回 JSONP 响应:
/contextRoot/info/1?param1=callback1
【问题讨论】:
【参考方案1】:是的,Spring 4.1+ 支持 JSONP,但它本身并不是一种转换格式。
MappingJackson2HttpMessageConverter
支持"application/json"
和"*+json"
媒体类型,但不支持"application/javascript"
。如果确实如此,那么您会希望它解析 javascript 代码,但事实并非如此。
在这里,我们只是将输出包装成"application/javascript"
,但实际上,它仍然是 JSON。
您当前的配置是禁用与 HTTP 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。
【讨论】:
嗨,Brian,我也在使用 controllerAdvice。但是,它仅在 URL 如下时支持 JSONP:/contextRoot/info/1?param1=callback1 相反,我希望 URL 的格式为:/contextRoot/info/1?formatType=jsonp¶m1=callback1; 当我们打算使用 JSONP 格式时,难道我们不是隐含地打算使用 application/javascript 媒体类型吗?甚至 MappingJackson2JsonView 也适用于 application/javascript。那么为什么启用它来处理 Javascript 代码呢? 转换器应该能够读取/写入内容 - Jackson 无法解析 javascript 源代码... MappingJackson2JsonView 也是一个单向过程:写入,而不是读取。 JSONP 只支持 GET 请求,不支持 PUT。所以不能通过 GET 请求发送数据(也不能以 JSONP 格式发送)。那么如何解析应用程序/javascript 或 JSONP 数据呢?是否有可能出现 Request 本身是 JSONP 格式的场景? 让我也向我解释一下这一点的重要性:我们正在迁移到 Spring 4,并且在我们为 JSONP 支持定制实现之前。我们使用的 URL 格式为 ----“contextRoot/info/12?format=jsonp&callback=value”。 ----我们需要在迁移到 Spring 4 时保持 REST URL 的向后兼容性。以上是关于Spring 4:MappingJackson2HttpMessageConverter 不支持 jsonp 的 application/javascript的主要内容,如果未能解决你的问题,请参考以下文章
Spring 框架 4.0 和 Spring security 3.2.4 上的 Spring Security SAML 扩展