JSONP 和自定义过滤器在 Spring MVC 中返回 XML
我正在使用 JSONP 调用 Spring MVC 中的控制器服务。我有一个自定义过滤器,它返回封装在回调中的结果。我使用了这个例子, http://jpgmr.wordpress.com/2010/07/28/tutorial-implementing-a-servlet-filter-for-jsonp-callback-with-springs-delegatingfilterproxy/。我也在使用 ContentNegotiatingViewResolver 但我的结果在回调中不断返回 XML。为什么它会一直这样做?
jQuery1509349652162468509_1300839533498(<?xml version="1.0" encoding="UTF-8" standalone="yes"?><followResponse><id>0</id></followResponse>);
servlet-context.xml
<beans:bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<beans:property name="order" value="1"/>
<beans:property name="mediaTypes">
<beans:map>
<beans:entry key="json" value="application/x-json"/>
<beans:entry key="json" value="text/json"/>
<beans:entry key="json" value="text/x-json"/>
<beans:entry key="json" value="application/json"/>
<beans:entry key="xml" value="text/xml"/>
<beans:entry key="xml" value="application/xml"/>
</beans:map>
</beans:property>
<beans:property name="defaultViews">
<beans:list>
<beans:bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"/>
<beans:bean class="org.springframework.web.servlet.view.xml.MarshallingView">
<beans:property name="marshaller">
<beans:bean class="org.springframework.oxm.xstream.XStreamMarshaller" />
</beans:property>
</beans:bean>
</beans:list>
</beans:property>
</beans:bean>
I am using JSONP to call a controller service in Spring MVC. I have a custom filter that returns the result wrapped in the callback. I used this example, http://jpgmr.wordpress.com/2010/07/28/tutorial-implementing-a-servlet-filter-for-jsonp-callback-with-springs-delegatingfilterproxy/. I am also using ContentNegotiatingViewResolver but my result keeps returning XML in the callback. Why would it keep doing that?
jQuery1509349652162468509_1300839533498(<?xml version="1.0" encoding="UTF-8" standalone="yes"?><followResponse><id>0</id></followResponse>);
servlet-context.xml
<beans:bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<beans:property name="order" value="1"/>
<beans:property name="mediaTypes">
<beans:map>
<beans:entry key="json" value="application/x-json"/>
<beans:entry key="json" value="text/json"/>
<beans:entry key="json" value="text/x-json"/>
<beans:entry key="json" value="application/json"/>
<beans:entry key="xml" value="text/xml"/>
<beans:entry key="xml" value="application/xml"/>
</beans:map>
</beans:property>
<beans:property name="defaultViews">
<beans:list>
<beans:bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"/>
<beans:bean class="org.springframework.web.servlet.view.xml.MarshallingView">
<beans:property name="marshaller">
<beans:bean class="org.springframework.oxm.xstream.XStreamMarshaller" />
</beans:property>
</beans:bean>
</beans:list>
</beans:property>
</beans:bean>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我的猜测是,您的控制器方法正在使用 @ResponseBody,并且您返回的模型对象是用 Jaxb2 注释(特别是 @XmlRootElement)标记的。
我遇到了和你一样的问题。问题是,@ResponseBody 绕过了 ContentNegotiatingViewResolver。您可以通过向 ContentNegotiatingViewResolver 的方法添加一些断点(例如“resolveViewName”)来确认这一点,并查看它是否确实被命中(不会)。
我当前使用的解决方法是实际声明一个 json 视图并专门使用它。
您必须将类似这样的内容添加到您的 xml 中:
然后您可以将列表项更改为如下所示:
然后您的控制器方法将返回一个 ModelAndView,如下所示:
或者,您可以将视图作为字符串返回,并在方法签名中添加声明 ModelMap:
希望这会有所帮助。
(注意:从内存中输入此内容,因此可能会出现语法错误等)
我还没有找到解决此问题的更优雅的解决方案,但如果找到了,我会将其发布在这里。
编辑:
尝试删除@ResponseBody。如果这样做,MessageConverters 将不会被激活,并且 ContentNegotiatingViewResolver 将被触发。此时,应该是扩展决定视图(根据您的设置)。
除了删除 @ResponseBody 之外,您不必更改任何内容,返回类型可以保持不变。
My guess is that you're controller method is using @ResponseBody and that the model objects your're returning are marked up with Jaxb2 annotations (specifically @XmlRootElement).
I had the same issue that you are having. The problem is, @ResponseBody bypasses the ContentNegotiatingViewResolver. You can confirm this by adding some break points to methods of the ContentNegotiatingViewResolver like "resolveViewName" and see if it actually gets hit (it won't).
The current work around I am using is to actually declare a json view and specifically use it.
You would have to add something like this to your xml:
You can then change your list item to look something like this as well:
Your controller method would then return a ModelAndView like so:
Or, you can just return the view as a string, and add declare a ModelMap in your method signature:
Hope this helps.
(Note: typing this out from memory, so there's potential for syntax errors, etc)
I haven't found a more elegant solution to this problem yet, but if I do, I'll post it here.
EDIT:
Try removing @ResponseBody. If you do this, the MessageConverters will not be activated, and the ContentNegotiatingViewResolver will be triggered. At this point, it should be the extension that determines the view (based on your setup).
You shouldn't have to change anything other than removing @ResponseBody, the return type can stay the same.
检查请求的 Accept 标头。
Check the Accept header of your request.
很高兴看到我的博客文章给了你灵感! :-D
您是否已将 Jackson 映射器 API 添加到您的依赖项中?创建 Spring MVC 应用程序时,默认情况下它不会存在。您必须自己添加它,然后它应该将响应编组为 JSON。
Nice to see my blog post was your inspiration! :-D
Have you added the Jackson mapper API to your dependencies? It won't be there by default when creating a Spring MVC app. You have to add it yourself and then it should marshall the response to JSON.
我的临时解决方案是使用 JSON 解析器,暂时将 XML 转换为 JSON。是的,将其解析为 XML 然后再解析回 JSON 很糟糕,但现在这必须起作用。
My temp solution was to use a JSON parser that takes XML and converts it to JSON for the time being. Yea it sucks to have it parsed to XML then back to JSON, but for now this is going to have to work.