The resource identified by this request is only capable of generating responses with characteristics

本文介绍了在Spring MVC 4.0.x中使用@ResponseBody注解返回JSON数据时出现406 Not Acceptable错误的原因及解决方法。分析了不同版本间处理请求头差异,并提供了多种解决策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

[html]  view plain  copy
  1. HTTP Status 406 -  
  2.   
  3. type Status report  
  4.   
  5. message  
  6.   
  7. description The resource identified by this request is only capable of generating responses with characteristics not acceptable according to the request "accept" headers.  
  8.   
  9. Apache Tomcat/7.0.56  

本文转自:http://www.tuicool.com/articles/FJnmAvY

spring 4.0.x通过@ResponseBody标签返回JSON数据的方法都报406错:  Failed to load resource: the server responded with a status of 406 (Not Acceptable)  以及报错描述:

  The resource identified by this request is only capable of generating responses with characteristics not acceptable according to the request "accept" headers ()   于是,百度、Google了半天,发现遇到此问题的人挺多的,但是都是说什么添加Jackson什么的,我是采用的fastjson,换成Jackson尝试了半天均还是406。   后来在stackoverflow有人说是Spring 3.2的存在BUG,但是我使用的是3.1.x,不再报406了,  虽然换回 3.1不报错了,但还是想看看在处理ajax返回json数据的方式上两个版本到底有何区别,debug之。 debug到

org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(T returnValue,MethodParameter returnType,ServletServerHttpRequest inputMessage,ServletServerHttpResponse outputMessage)

在以下代码处抛出了异常:

if (compatibleMediaTypes.isEmpty()) {  
    throw new HttpMediaTypeNotAcceptableException(allSupportedMediaTypes);  
}

看 来是compatibleMediaTypes为空导致。看debug信息,经过比较发现3.1的requestedMediaTypes为[*/*], 而3.2的requestedMediaTypes却为[text/html],producibleMediaTypes都是[application /json],继而发现获取acceptableMediaTypes的方式3.1与3.2不同

3.1

private List<MediaType> getAcceptableMediaTypes(HttpInputMessage inputMessage) {  
      try {  
        List<MediaType> result = inputMessage.getHeaders().getAccept();  
        return result.isEmpty() ? Collections.singletonList(MediaType.ALL) : result;  
      } catch (IllegalArgumentException ex) {  
        if (logger.isDebugEnabled()) {  
          logger.debug("Could not parse Accept header: " + ex.getMessage());  
        }  
        return Collections.emptyList();  
      }  
}

3.2

private List<MediaType> getAcceptableMediaTypes(HttpServletRequest request) throws HttpMediaTypeNotAcceptableException {  
	List<MediaType> mediaTypes = this.contentNegotiationManager.resolveMediaTypes(new ServletWebRequest(request));  
        return mediaTypes.isEmpty() ? Collections.singletonList(MediaType.ALL) : mediaTypes;  
}

4.0.x

private List<MediaType> getAcceptableMediaTypes(HttpServletRequest request) throws HttpMediaTypeNotAcceptableException {
    List<MediaType> mediaTypes = this.contentNegotiationManager.resolveMediaTypes(new ServletWebRequest(request));
    return (mediaTypes.isEmpty() ? Collections.singletonList(MediaType.ALL) : mediaTypes);
}

看来问题就是出在这里了。不知Spring为何改变该实现方式??!!

解决方法如下:

第一种:

退回3.1.x

第二种:

<?xml version="1.0" encoding="UTF-8"?>  
     <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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"  
     xmlns:mvc="http://www.springframework.org/schema/mvc"  
     
      xsi:schemaLocation="http://www.springframework.org/schema/beans  
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
        http://www.springframework.org/schema/context  
        http://www.springframework.org/schema/context/spring-context-3.0.xsd  
        http://www.springframework.org/schema/aop  
        http://www.springframework.org/schema/aop/spring-aop-3.0.xsd  
        http://www.springframework.org/schema/tx   
        http://www.springframework.org/schema/tx/spring-tx-3.0.xsd  
        http://www.springframework.org/schema/mvc    
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"

把spring-mvc-3.0.xsd 升级到  spring-mvc-3.2.xsd

<?xml version="1.0" encoding="UTF-8"?>  
    <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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"  
    xmlns:mvc="http://www.springframework.org/schema/mvc"  
      
    xsi:schemaLocation="http://www.springframework.org/schema/beans  
      http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
      http://www.springframework.org/schema/context  
      http://www.springframework.org/schema/context/spring-context-3.0.xsd  
      http://www.springframework.org/schema/aop  
      http://www.springframework.org/schema/aop/spring-aop-3.0.xsd  
      http://www.springframework.org/schema/tx   
      http://www.springframework.org/schema/tx/spring-tx-3.0.xsd  
     http://www.springframework.org/schema/mvc   
     http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">

然后把<mvc:annotation-driven>修改成如下格式

<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager" />   
  <bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">   
    <property name="favorPathExtension" value="false" />  
    <property name="favorParameter" value="false" />   
    <property name="ignoreAcceptHeader" value="false" />   
    <property name="mediaTypes" >   
      <value>  
        atom=application/atom+xml  
        html=text/html  
        json=application/json  
        *=*/*  
      </value>   
    </property>  
  </bean>

  三、第三种

详情见下面的地址 点击打开链接(主要针对3.2.X)

http://stackoverflow.com/questions/14333709/spring-mvc-3-2-and-json-objectmapper-issue

四、第四种

spring 3.2时requestedMediaTypes却为[text/html]的情况报406错误,还有一个原因可能是由于采用的后缀有关,如果使 用*.htm,*.html等,默认就会采用[text/html]编码,若改成*.json,*.shtml等就OK!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值