我们使用Spring MVC开发标准Java Web应用程序,并且最近尝试从3.0.6升级到3.2.0。几乎所有的servlet响应都是JSP或Json视图,但有一些是pdf请求,扩展名为“pdf”。
在Spring 3.0.6中 我们有这个设置,取自Spring MVC文档。
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="mediaTypes">
<map>
<entry key="pdf" value="application/pdf"/>
<entry key="html" value="text/html"/>
<entry key="json" value="application/json"/>
</map>
与XMLViewResolver结合使用效果很好。
更新到3.2.0后,出现故障:
Error creating bean with name' org.springframework.web.servlet.view.ContentNegotiatingViewResolver#0' defined in class path resource [dispatcher-test-servlet.xml]: Invocation of init method failed; nested exception is
java.lang.ClassCastException: java.lang.String cannot be cast to org.springframework.http.MediaType'
在调查了文档和一些博客之后,这种配置似乎有效:
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="contentNegotiationManager">
<bean class="org.springframework.web.accept.ContentNegotiationManager">
<constructor-arg>
<list>
<!-- These are evaluated in order -->
<!-- Is there a media type based on suffix? -->
<bean class="org.springframework.web.accept.PathExtensionContentNegotiationStrategy">
<constructor-arg>
<map>
<entry key="html" value="text/html" />
<entry key="json" value="application/json" />
<entry key="pdf" value="application/pdf" />
</map>
</constructor-arg>
</bean>
<!-- Else use request header -->
<bean
class="org.springframework.web.accept.HeaderContentNegotiationStrategy">
</bean>
</list>
</constructor-arg>
</bean>
</property>
但是,我们尝试使用此配置运行新的Spring MVC测试框架,并再次获得ClassCast异常,因此测试框架似乎没有像应用程序运行时那样初始化bean ... 有没有人清楚地解释如何以健壮的方式配置Spring 3,2中的ContentNegotiatingViewResolver? 谢谢
理查德
答案 0 :(得分:12)
我通过删除重复修复了问题
来自xml-configuration的<mvc:annotation-driven/>
要么
来自班级的@EnableWebMVC
注释
因为春季文件警告这一点,并且只允许合同一次。
答案 1 :(得分:7)
使用spring 3.2,可以使用ContentNegotiationManager
更好地解决问题。它对我有用。您可以使用像org.springframework.http.MediaType.APPLICATION_JSON_VALUE
这样的静态字段来提及mediatype。检查以下代码:
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="contentNegotiationManager">
<bean class="org.springframework.web.accept.ContentNegotiationManager">
<constructor-arg>
<bean class="org.springframework.web.accept.PathExtensionContentNegotiationStrategy">
<constructor-arg>
<map>
<entry key="json">
<util:constant static-field="org.springframework.http.MediaType.APPLICATION_JSON_VALUE" />
</entry>
<entry key="xml">
<util:constant static-field="org.springframework.http.MediaType.APPLICATION_XML_VALUE" />
</entry>
</map>
</constructor-arg>
</bean>
</constructor-arg>
</bean>
</property>
<property name="defaultViews">
<list>
<!-- default views -->
</list>
</property>
</bean>
为此,您必须在dispatcher-servlet.xml文件中使用util模式,即xmlns:util="http://www.springframework.org/schema/util"
和模式位置http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.0.xsd
答案 2 :(得分:0)
我认为您可以使用ContentNegotiationManagerFactoryBean更轻松地实现相同的功能。默认情况下,它首先检查URL路径扩展,然后检查URL中的format属性(例如.... / accounts?format = pdf),然后检查标准HTTP Accept标头属性。默认情况下,format参数的使用处于关闭状态。
<bean id="contentNegotiationManager"
class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="defaultContentType" value="text/html" />
<property name="mediaTypes">
<map>
<entry key="json" value="application/json" />
<entry key="pdf" value="application/pdf" />
<entry key="pdf" value="text/html" />
</map>
</property>
</bean>
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="contentNegotiationManager" ref=""/>
</bean>
如果使用JavaBeans Activation Framework,JAF,则不需要mediaTypes部分。只需将activation.jar放在类路径上即可。
您是否尝试过此操作并且您是否也获得了类别转换异常?
答案 3 :(得分:-1)
好吧,你发布的错误基本上是说Spring没有办法将你提供的字符串(例如“application / pdf”)转换为MediaType对象。我猜测ContentNegotiatingViewResolver将它的mediaTypes地图更改为Map到Map。你可以尝试这样的事情:
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="mediaTypes">
<map>
<entry key="pdf">
<value>
<bean class="org.springframework.http.MediaType">
<constructor-arg value="application/pdf" />
</bean>
</value>
</entry>
<entry key="html">
<value>
<bean class="org.springframework.http.MediaType">
<constructor-arg value="text/html" />
</bean>
</value>
</entry>
<entry key="json">
<value>
<bean class="org.springframework.http.MediaType">
<constructor-arg value="application/json" />
</bean>
</value>
</entry>
</map>
</bean>
注意:我是从内存中做到这一点的,所以我可能已经错了。基本上,您需要将条目值设置为MediaTypes,而不是字符串。