RestController:HTTP状态406 - 不可接受

时间:2017-12-17 17:52:49

标签: java spring-mvc

我使用“Jsonitter”作为JSON序列化框架,我不在我的项目中使用Maven。我一直在我的restful api中返回JSON对象,直接将“Jsonitter”的结果写入HttpServletResponse,直到现在我找到了@RestController属性。来自ASP.Net MVC背景,我希望框架能够根据Accept标头自动序列化我的api中的返回对象。但我觉得,Spring需要第三方序列化框架来呈现结果(即Jackson),因为它会返回HTTP Status 406 - Not Acceptable结果。

我使用它的方式如下:

@RestController
@EnableWebMvc
public class TestApi {
    @RequestMapping(value = "Test", method = RequestMethod.Get, produces = "application/json")
    public List<String> letsTest(){
        return myStringList;
    }
}

我没有提及杰克逊,我宁愿根本不使用它,我觉得错误是由于这个原因造成的。没有杰克逊,有没有办法让这项工作?

3 个答案:

答案 0 :(得分:4)

关于406 - 不可接受

由于您的控制器配置为仅在客户端请求application/json数据时返回响应,

produces = "application/json"

您可能会收到“406 Not Acceptable”,因为您的客户端请求了其他内容/未指定任何Accepts标头。你可以修理:

  • 修复您的客户端请求以提供Accepts标题
  • 更改注释以接受客户发送的任何内容(如果您是懒惰的话,请加上*/*。)

这是你唯一的问题,你没有被强制使用Spring的任何Serialization框架(但如果你定义你的控制器方法来返回任意bean,则需要一个Serializer)。您可以将任何String写为对客户的响应。

关于如何在后台响应Jsoniter

如果你想继续使用Jsoniter,但是把它移到后台让你的Controller类不再明确提到jsoniter,你需要定义自己的custom HttpMessageConverter

关于如何在没有Jsoniter的情况下做出回应

您需要一些Serializer来从Java生成Json。您可以编写自定义代码,或使用Jackson或Gson。 Spring默认支持Jackson,而Gson使用GsonHttpMessageConverter支持。对于Jackson,您当前的代码是可以的,但您需要添加jackson依赖项。对于Gson,您需要声明转换器,有几个资源在线解释。

关于如何使用Jsoniter

手动响应

与此问题的答案Does spring mvc have response.write to output to the browser directly?

一样

您可以使用@ResponseBody撰写回复。由于@RestController已经隐含@ResponseBody,因此您也可以将其排除在外。在此处显示只是为了澄清:

@ResponseBody // not needed with @RestController
@RequestMapping(value = "Test", method = RequestMethod.Get, produces = "application/json")
public String letsTest() {
    // Using Jsoniter JsonStream
    return JsonStream.serialize(myStringList);
}

答案 1 :(得分:1)

Spring 4.3.10:我使用以下设置来解决问题。

步骤1:添加以下依赖项

    <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.6.7</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.6.7</version>
</dependency>
<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-core-asl</artifactId>
    <version>1.9.13</version>
</dependency>
<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
    <version>1.9.13</version>
</dependency>

步骤2:在MVC DispatcherServlet上下文配置中添加以下内容:

<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="true"/>
        <property name="ignoreAcceptHeader" value="false" />
    </bean>

从Spring 3.2开始,根据默认配置,favorPathExtension设置为true,因此如果请求uri具有任何适当的扩展名,如.htm,spring将优先考虑扩展名。在第2步中,我添加了contentNegotiationManager bean来覆盖它。

答案 2 :(得分:0)

在我的案例中,方案是使用Spring restTemplate.put方法在数据库中插入pdf资源。

http:// $ {apiGateWay} /resource/provision/Test.pdf

,标题为application / pdf。但是我仍然收到406不可接受的错误。

在调试问题之后,发现put请求不接受带有的密钥。扩展名。

因此网址应为

http:// $ {apiGateWay} / resource / provision / Test