Spring MVC - HttpMediaTypeNotAcceptableException
Posted
技术标签:
【中文标题】Spring MVC - HttpMediaTypeNotAcceptableException【英文标题】: 【发布时间】:2011-11-04 01:34:35 【问题描述】:在使用 Spring MVC 和 JSON 时,我不断收到 AJAX 请求的此 HttpMediaTypeNotAcceptableException 错误。错误的完整堆栈跟踪是..
org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker.writeWithMessageConverters(AnnotationMethodHandlerAdapter.java:1032)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker.handleResponseBody(AnnotationMethodHandlerAdapter.java:972)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker.getModelAndView(AnnotationMethodHandlerAdapter.java:921)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:438)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:424)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:863)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:792)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:851)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:756)
javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
我做的小谷歌搜索表明请求应该包含类似“accept:application/json”的内容。这是来自 firebug 的请求标头..
Response Headers
Server Apache-Coyote/1.1
Content-Type text/html;charset=utf-8
Content-Length 2503
Date Thu, 25 Aug 2011 21:00:05 GMT
Connection close
Request Headers
Host localhost:8080
User-Agent Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.20) Gecko/20110803 Firefox/3.6.20 (.NET CLR 3.5.30729)
Accept application/json, text/javascript, */*; q=0.01
Accept-Language en-us,en;q=0.5
Accept-Encoding gzip,deflate
Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive 115
Connection keep-alive
X-Requested-With XMLHttpRequest
Referer http://localhost:8080/legaldirectory/index.html
Cookie JSESSIONID=5C97DA19AED4D5FA17F4A58470FAA93B
现在我完全迷失了这里发生的事情..这里还有什么地方会出错...
【问题讨论】:
请发布您的控制器代码和调度程序 servlet Spring 上下文文件。我猜你没有为 JSON 配置正确的消息转换器(例如MappingJacksonHttpMessageConverter
)。
***.com/a/48806286/1849366
【参考方案1】:
请确保您的 Spring xml 文件中有以下内容:
<context:annotation-config/>
<bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jacksonMessageConverter"/>
</list>
</property>
</bean>
并且你的 POJO 的所有项目都应该有 getter/setter。 希望对你有帮助
【讨论】:
我的结果对象中缺少获取器 别忘了参考这个 - ***.com/questions/22384722/… 从 Spring 4+ 开始,您只需要添加 ,不再需要额外的 bean 来处理 JSON。 如果不在 Spring xml 文件中进行配置,你怎么能做到呢?我目前没有使用该文件。我不能自动装配这个吗? 我正在使用 Spring 4.x 并且仅使用<context:annotation-config/>
不起作用。【参考方案2】:
来自: http://georgovassilis.blogspot.ca/2015/10/spring-mvc-rest-controller-says-406.html
你已经得到了这个 Spring @RestController 并映射了一个包含电子邮件的 URL 作为 URL 路径的一部分。您巧妙地解决了点截断问题 [1],并且您已准备好滚动。突然,在某些 URL 上,Spring 将返回 406 [2],表示浏览器请求了某种内容类型,而 Spring 无法序列化对该内容的响应类型。关键是,您多年来一直在做 Spring 应用程序,并且您正确地完成了所有 MVC 声明,并且您包括 Jackson,基本上您被卡住了。更糟糕的是,它只会在 URL 路径中的某些电子邮件上吐出该错误,尤其是那些以“.com”域结尾的电子邮件。
@RequestMapping(value = "/agenda/email:.+", method = RequestMethod.GET)
public List<AgendaEntryDTO> checkAgenda(@PathVariable("email") String email)
问题 [3] 相当棘手:应用服务器执行一些内容协商并说服 Spring 浏览器请求了 "application/x-msdownload" 内容,尽管浏览器实际提交的请求中没有发生这种情况。
解决方案是为 Web 应用程序上下文指定一个内容协商管理器:
<mvc:annotation-driven enable-matrix-variables="true"
content-negotiation-manager="contentNegotiationManager" />
<bean id="contentNegotiationManager"
class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="defaultContentType" value="application/json" />
<property name="favorPathExtension" value="false" />
<property name="favorParameter" value="false" />
<property name="parameterName" value="mediaType" />
<property name="ignoreAcceptHeader" value="false" />
<property name="useJaf" value="false" />
</bean>
【讨论】:
【参考方案3】:确保将两个 Jackson jar 添加到类路径:
jackson-core-asl-x.jar jackson-mapper-asl-x.jar此外,您的 Spring xml 文件中必须包含以下内容:
<mvc:annotation-driven />
【讨论】:
这不适用于 spring4.x。就我而言,我需要的只是 getter 和 setter。【参考方案4】:因为这是“HttpMediaTypeNotAcceptableException”的第一个谷歌点击,所以我想添加另一个我偶然发现的问题,它也导致了 HttpMediaTypeNotAcceptableException。
在我的例子中,它是一个指定“生产”的控制器,例如:
@RequestMapping(path = "/mypath/filename", method = RequestMethod.GET,
produces = MediaType.APPLICATION_XML_VALUE
因为我想提供一个 XML 文件。同时我正在使用带有“@ControllerAdvice”的类来捕获异常,例如如果未找到请求的文件。异常处理程序正在返回 JSON,因此客户端(角度)应用程序可以在 SPA 中的某处显示错误消息。
现在控制器想要返回 XML,但异常处理程序正在返回 JSON,因此引发了 HttpMediaTypeNotAcceptableException。我通过添加 JSON 作为可能的“产生”值来解决这个问题:
produces = MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE
希望这对其他人有所帮助。 :-)
【讨论】:
【参考方案5】:请记住一些重要的事情:3.1.2 之前的 Spring 版本与 JACKSON 1.x 兼容,而不与 JACKSON 2.x 兼容。这是因为从 JACKSON 1.x 到 2.x 类的包名发生了变化。在 JACKSON 1.x 中,类在 org.codehaus.jackson 下,而在 JACKSON 2.x 中,它们在 com.fasterxml.jackson 下。
为了解决这个问题,从 Spring 3.1.2 开始,他们添加了一个新的 MappingJackson2HttpMessageConverter 来替换 MappingJacksonHttpMessageConverter。
您可以在此链接中找到有关兼容性问题的更多详细信息:Jackson annotations being ignored in Spring
【讨论】:
【参考方案6】:就我而言 favorPathExtension(false) 帮助了我
@Configuration
public class WebMvcConfiguration extends WebMvcConfigurerAdapter
@Override
public void configurePathMatch(PathMatchConfigurer configurer)
configurer
.setUseSuffixPatternMatch(false); // to use special character in path variables, for example, `email@dom.com`
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer)
configurer
.favorPathExtension(false); // to avoid HttpMediaTypeNotAcceptableException on standalone tomcat
【讨论】:
SO 真是个很棒的地方。在与HttpMediaTypeNotAcceptableException
挣扎了几个小时后,我遇到了这个精彩的答案并解决了我的问题 +100
从 Spring 5.3 开始,两个属性的默认值 is false 并且都已被弃用。有关更多详细信息,请参阅 PathMatchConfigurer 和 ContentNegotiationConfigurer 的 javadoc【参考方案7】:
在扩展 WebMvcConfigurerAdapter 的 Spring @Configuration 类中覆盖方法 configureMessageConverters,例如:
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters)
// http
HttpMessageConverter converter = new StringHttpMessageConverter();
converters.add(converter);
logger.info("HttpMessageConverter added");
// string
converter = new FormHttpMessageConverter();
converters.add(converter);
logger.info("FormHttpMessageConverter added");
// json
converter = new MappingJackson2HttpMessageConverter();
converters.add(converter);
logger.info("MappingJackson2HttpMessageConverter added");
错误就会消失。
【讨论】:
【参考方案8】:我遇到了同样的问题,但我发现基本上当 spring 尝试呈现响应时会发生什么,它将尝试根据您指定的媒体类型并在您的类中使用 getter 和 setter 方法对其进行序列化
以前我的课看起来像下面这样
public class MyRestResponse
private String message;
解决方案如下所示
public class MyRestResponse
private String message;
public void setMessage(String msg)
this.message = msg;
public String getMessage()
return this.message;
这对我来说是这样的
【讨论】:
【参考方案9】:尝试将“jackson-databind”jar 添加到 pom.xml
`<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>$jackson.databind-version</version>
</dependency>`
和produces =MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE
到@RequestMapping
Es。 @RequestMapping(value = "/api/xxx/akey/md5", produces =MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE
@RequestMapping(value = "/api/contrassegno/akey/md5", produces =MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE,...
【讨论】:
【参考方案10】:response.setHeader("Accept", "application/json");
【讨论】:
【参考方案11】:正如Alex 在其中一个答案中暗示的那样,您可以使用 ContentNegotiationManagerFactoryBean 将默认内容类型设置为“application/json”,但我觉得这种方法不适合我。
我试图做的是将表单发布到这样的方法
@RequestMapping(value = "/post/to/me", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public @ResponseBody MyJsonPOJO handlePostForm(@Valid @ModelAttribute("form") ValidateMeForm form, BindingResult bindingResult) throws ApiException
我选择做的是将来自浏览器的请求的“Accept”标头更改为“application/json”,从而使 SpringMVC 找到我的方法。
使用(尚未最终确定的)Javascript Fetch API:
var form = new FormData();
form.append("myData", "data");
let fetchConfig =
method: "POST",
body: form,
headers: "Accept": "application/json"
;
fetch("/post/to/me", fetchConfig)
.then(... // Javascript Promise API here
等等!现在 SpringMVC 找到方法,验证表单,并让您返回 JSON POJO。
【讨论】:
【参考方案12】:就我而言,只需添加@ResponseBody
注释即可解决此问题。
【讨论】:
【参考方案13】:就我而言
"timestamp":1537542856089,"status":406,"error":"Not Acceptable","exception":"org.springframework.web.HttpMediaTypeNotAcceptableException","message":"Could not find acceptable representation","path":"/a/101.xml"
由以下原因引起:
path = "/path/VariableName"
但我传入了带后缀的变量名,例如“abc.xml”,这使得它将.xml 解释为某种format request instead。在那里查看答案。
【讨论】:
【参考方案14】:对我来说,问题是我试图访问的 URL。我有这样的网址:
ip:port/path/person.html
当您以 .html 结束 url 时,这意味着您不会接受除 html 之外的任何其他有效负载。我需要从末尾删除 .html 才能使我的端点正常工作。 (您也可以在 url 末尾附加 .json,它也可以使用)
此外,web.xml
中的 url-pattern 需要正确配置以允许您访问资源。对我来说是
<servlet-mapping>
<servlet-name>spring-mvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
以前我有*.html*
,它阻止我访问端点。
【讨论】:
【参考方案15】:更多的是评论而不是答案......
我正在使用 Lombok,我正在开发一个(非常)骨架 API,我的响应 DTO 还没有任何字段,并且在运行集成测试时出现 HttpMediaTypeNotAcceptableException
错误。
在响应 DTO 中添加一个字段解决了这个问题。
【讨论】:
以上是关于Spring MVC - HttpMediaTypeNotAcceptableException的主要内容,如果未能解决你的问题,请参考以下文章
Spring MVC学习—MVC的介绍以及Spring MVC的入门案例
spring mvc中 Circular view path 问题