我正在将Web应用程序从Spring 3.0.5迁移到4.2.4。经过许多障碍(显然这个过程并没有真正记录下来......),我遇到了可怕的406错误。似乎有很多问题,但没有一个答案是有效的(即使是有问题的)。
这是带有以下函数的控制器代码:
@Controller
public class TestController {
@RequestMapping(value = "/echo", method = RequestMethod.GET, headers = "Accept=*/*")
@ResponseBody
public String echoReply(HttpServletRequest request) throws Exception {
return "echo";
}
@RequestMapping(value = "/test", method = RequestMethod.GET, headers = "Accept=*/*")
@ResponseBody
public boolean testFunc(HttpServletRequest request) throws Exception {
...
return ...;
}
第一个函数按预期返回echo
,但测试函数返回错误 406 - Could not find acceptable representation
。确切的消息是:
The resource identified by this request is only capable of generating
responses with characteristics not acceptable according to the request
"accept" headers
两者都与 AJAX 调用和通过 URL 直接访问相关。
任何想法要寻找什么以及为什么会这样发生?
编辑:也许这是控制器类注释中的一些问题(Spring 4.2 中应该缺少的东西)?
应用上下文.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd" default-lazy-init="true">
<context:annotation-config />
<aop:aspectj-autoproxy />
<tx:annotation-driven/>
<mvc:annotation-driven/>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="..." />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
// bunch of component-scans and some more beans
</beans>
绒球.xml:(杰克逊的相关依赖关系)
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>1.9.13</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.7.1-1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.7.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.7.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-base</artifactId>
<version>2.7.1</version>
</dependency>
Spring MVC 官方文档将以下数据类型列为控制器方法的有效返回类型:
-
ModelAndView
-
Model
-
Map
-
View
-
String
-
void
-
HttpEntity
-
HttpHeaders
-
Callable
-
DeferredResult
-
ListenableFuture
-
ResponseBodyEmitter
-
SseEmitter
-
StreamingResponseBody
对于用 @ResponseBody
批注的控制器方法,返回类型将写入响应正文。 此过程使用适用于Accepts
请求标头的HttpMessageConverter
执行。
由于您的testFunc
方法的返回类型为 boolean
,Spring MVC 将尝试使用 HttpMessageConverter
写入返回值。 这意味着,Accepts
标头必须指定一个值,该值将导致boolean
值的有效表示形式。 因此,表示形式只能是无架构的,例如 JSON。 任何其他表示都将导致所描述的错误。
因此,如果Accepts
标头设置为 text/html
或 application/xml
,boolean
将无法写入响应正文。 但是,如果您将标头设置为 application/json
,您的boolean
值将被正确写入。
如果还想支持 HTML 和 XML,则必须将boolean
包装在对象(如 Map
或自定义对象)中。
尝试使用 更新app-context.xml
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
</mvc:message-converters>
</mvc:annotation-driven>