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 服务。
点击下面的 URL 给出 json 格式的数据
/contextRoot/info/1?formatType=json
点击以下 URL 给出 xml 格式的数据
/contextRoot/info/1?formatType=xml
点击以下 URL 给出 406 EXCEPTION
/contextRoot/info/1?formatType=jsonp¶m1=callback1
观察结果
调查发现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¶m1=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
对于你的情况,你应该:
- 从媒体类型映射中删除
"application/javascript"
,或者为了向后兼容,将 "jsonp"
与 "application/json"
媒体类型相关联。
- 使用
GET /contextRoot/info/1?formatType=json¶m1=callback1
有关实施的更多详细信息,请参阅 AbstractJsonpResponseBodyAdvice。
使用 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 服务。
点击下面的 URL 给出 json 格式的数据
/contextRoot/info/1?formatType=json
点击以下 URL 给出 xml 格式的数据
/contextRoot/info/1?formatType=xml
点击以下 URL 给出 406 EXCEPTION
/contextRoot/info/1?formatType=jsonp¶m1=callback1
观察结果
调查发现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¶m1=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
对于你的情况,你应该:
- 从媒体类型映射中删除
"application/javascript"
,或者为了向后兼容,将"jsonp"
与"application/json"
媒体类型相关联。 - 使用
GET /contextRoot/info/1?formatType=json¶m1=callback1
有关实施的更多详细信息,请参阅 AbstractJsonpResponseBodyAdvice。