【问题标题】:Spring MVC Restful 406 Not Acceptable ErrorSpring MVC Restful 406 不可接受的错误
【发布时间】:2016-01-22 23:42:43
【问题描述】:

我知道以前有人问过这个问题,并且我已经检查了 Spring MVC 的每条消息以及 406 错误消息,我不知道如何解决这个问题,因为我已经尝试了几乎所有的第四个这些以前的答案。

这个网络服务接受一个电子邮件地址,并以 JSON 格式返回一个用户对象。我可以告诉你单元测试效果很好。而且我知道我们通过了 Spring Security,我们正在执行 servlet……现在唯一的问题是 JSON 输出……我不明白,我收到了这个错误消息。

所以,确切地说:
Spring核心:4.2.4.RELEASE Spring Security:4.0.3.RELEASE Jackson Faster XML:2.6.5(核心、数据绑定、注释) 2.7.0 好像还不行……

这里是springmvc-servlet.xml:

<context:annotation-config />
<context:component-scan base-package="com.agmednet.server.controller" />

<mvc:annotation-driven>
    <mvc:message-converters register-defaults="true">
        <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
          <property name="objectMapper">
             <bean class="com.agmednet.server.HibernateAwareObjectMapper">

                     <property name="dateFormat">
                        <bean class="java.text.SimpleDateFormat">
                            <constructor-arg type="java.lang.String" value="yyyy-MM-dd HH:mm:ss.SSS"></constructor-arg>
                        </bean>
                     </property>

             </bean>
          </property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

这里是控制器:

@Controller
@RequestMapping("/users")
public class UserAccountController
{
@Autowired
private UserAccountService userAccountService;

@RequestMapping(value = "/email/{email:.*}", method = RequestMethod.GET)
public @ResponseBody UserAccountEntity getByEmailAddress(@PathVariable("email") String email)
{
    Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    User user = null;
    if (principal instanceof User)
    {
        user = ((User) principal)
    }
    UserAccountEntity userAccount = userAccountService.getByEmailAddress(email);
    return userAccount;
}
}

如您所见,我有 Accept 标头设置,我有 @ResponseBody 注释。

我还有一个SimpleCORSFilter 代码:

@Component
public class SimpleCORSFilter implements Filter
{
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException
    {
    HttpServletResponse response = (HttpServletResponse) res;
    response.setHeader("Access-Control-Allow-Origin", "*");
    response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
    response.setHeader("Access-Control-Max-Age", "3600");
    response.setHeader("Access-Control-Allow-Headers", "x-requested-with, Content-Type, Accept, If-Modified-Since, openam_token");
    chain.doFilter(req, res);
    }

    public void init(FilterConfig filterConfig){}
    public void destroy(){}
}

如您所见,它接受我的“openam_token”自定义标头,但具有 “接受”和“内容类型”也是如此。

我从防火墙后面的 linux 机器上调用它,所以我必须通过 SSH 连接到机器,并执行以下 curl 语句:

curl -v -i -X GET -H "openam_token: AQIC5wM2LY4Sfcxfw-GSBSndg-4DMEyrEqcBgiTE4b4e3aE.*AAJTSQACMDE.*" -H "Content-Type: application/json, text/html" -H "Accept: application/json, text/html" backend.spring.mycompany.net:8080/services/api/users/email/user4252002@mycompany.com

所以,这是我在请求中通过 curl 发送的内容:

*   Trying 10.0.4.107...
* Connected to backend.spring.agmednet.net (10.0.4.107) port 8080 (#0)
> GET /services/api/users/email/user4252002@agmednet.com HTTP/1.1
> User-Agent: curl/7.40.0
> Host: backend.spring.agmednet.net:8080
> openam_token: AQIC5wM2LY4Sfcxfw-GSBSndg-4DMEyrEqcBgiTE4b4e3aE.*AAJTSQACMDE.*
> Content-Type: application/json, text/html
> Accept: application/json, text/html

下面是回复:

< HTTP/1.1 406 Not Acceptable
HTTP/1.1 406 Not Acceptable
< Server: Apache-Coyote/1.1
Server: Apache-Coyote/1.1
< Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: *
< Access-Control-Allow-Methods: POST, PUT, GET, OPTIONS, DELETE
Access-Control-Allow-Methods: POST, PUT, GET, OPTIONS, DELETE
< Access-Control-Max-Age: 3600
Access-Control-Max-Age: 3600
< Access-Control-Allow-Headers: x-requested-with, Content-Type, Accept, If-Modified-Since, openam_token
Access-Control-Allow-Headers: x-requested-with, Content-Type, Accept, If-Modified-Since, openam_token
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
Pragma: no-cache
< Expires: 0
Expires: 0
< X-XSS-Protection: 1; mode=block
X-XSS-Protection: 1; mode=block
< X-Frame-Options: DENY
X-Frame-Options: DENY
< X-Content-Type-Options: nosniff
X-Content-Type-Options: nosniff
< Set-Cookie: JSESSIONID=76C4B28DD0B5D88EB9341944BDBCD045; Path=/services/; HttpOnly
Set-Cookie: JSESSIONID=76C4B28DD0B5D88EB9341944BDBCD045; Path=/services/; HttpOnly
< Content-Type: text/html;charset=utf-8
Content-Type: text/html;charset=utf-8
< Content-Language: en
Content-Language: en
< Content-Length: 1110
Content-Length: 1110
< Date: Wed, 20 Jan 2016 14:30:28 GMT
Date: Wed, 20 Jan 2016 14:30:28 GMT


  <!DOCTYPE html>
  <html><head>
  <title>Apache Tomcat/8.0.30 - Error report</title>
  </head>
  <body>
  <h1>HTTP Status 406 - </h1>
  <div class="line"></div><p><b>type</b> Status report</p>
  <p><b>message</b> <u></u></p>
  <p><b>description</b> 
  <u>The resource identified by this request is only capable of generating 
  responses with characteristics not acceptable according to the request*  
  Connection #0 to host backend.spring.agmednet.net left intact
  "accept" headers.</u></p>
  <hr class="line"><h3>Apache Tomcat/8.0.30</h3></body></html>

最终,这是上面列出的错误消息:

The resource identified by this request is only capable of generating responses with characteristics not acceptable according to the request* Connection #0 to host backend.spring.mycompany.net left intact

“接受”标题。

所以,我使用的是@ResponseBody,我使用的是最新的 Jackson 2.x 版本。我正在遵循以前问题中的所有建议,但我仍然无法使其正常工作。

任何帮助将不胜感激。

【问题讨论】:

  • 对于初学者来说,删除 @EnableWebMvc 你已经有 &lt;mvc:annotation-driven /&gt; 了。
  • 如上所述删除 EnableWebMVC,以及为什么要接收一个清晰的电子邮件地址作为路径变量。接收一个简单的字符串并检查它是否是有效的电子邮件。其次,您不需要显式添加产生和接受。
  • 首先....网络服务不检查电子邮件的有效性。这是基于我们的需求,我们传入一封电子邮件,然后在该字段上进行数据库查找并从中返回用户,这是业务需求!!!!其次,我知道我不需要“生产”,但拥有“接受”并没有什么坏处,但我会删除它,看看它是否能解决我的问题。我添加它们的唯一原因是测试并查看是否可以解决问题,但没有。如前所述,我已经从我的控制器中删除了@EnableWebMvc。所以,我现在正在测试中。
  • 从控制器中删除了produces和accept,并删除了@EnabledWebMvc注解......仍然没有成功。为什么我不惊讶?!?!?!

标签: spring rest spring-mvc curl


【解决方案1】:

@EnableWebMVC 不是问题,您在问题中看到的所有内容都是 100% 正确的。我还有另外两个运行良好的网络服务。问题最终出在 curl 语句本身:

curl -v -i -X GET -H /
"openam_token: AQIC5wM2LY4Sfcxfw-GSBSndg-4DMEyrEqcBgiTE4b4e3aE.*AAJTSQACMDE.*" /
-H "Content-Type: application/json, text/html" /
-H "Accept: application/json, text/html"  /
backend.spring.mycompany.net:8080/services/api/users/email/user4252002@mycompany.com

如果您注意到,URL 和路径变量不在引号中。 如果您注意到,电子邮件地址中有一个 @ 符号,我发现这意味着要卷曲。所以,我所做的就是将我的 curl 更改为以下内容。

curl -v -i -X GET -H /
"openam_token: AQIC5wM2LY4Sfcxfw-GSBSndg-4DMEyrEqcBgiTE4b4e3aE.*AAJTSQACMDE.*" /
-H "Content-Type: */*" /
-H "Accept: */*" /    
"backend.spring.mycompany.net:8080/services/api/users/email/user4252002%40mycompany%2Ecom"

1) 我自己将电子邮件地址 @ 编码为 %40,句点编码为 %2E 您可以使用任何您想要对路径变量进行编码的工具。

2) 即使我返回一个转换为 JSON 的 java 对象,我将标题“Accept”和“Content-Type”更改为“/”。

就是这样。这有效,406 错误消息消失了。

【讨论】:

    猜你喜欢
    • 2013-04-26
    • 1970-01-01
    • 2016-03-08
    • 1970-01-01
    • 1970-01-01
    • 2011-11-12
    • 2019-04-30
    • 2015-03-17
    相关资源
    最近更新 更多