为什么Spring Web对GET请求抛出415错误代码响应?

时间:2018-09-06 19:46:10

标签: java spring rest

我正在将Spring应用程序从较旧的Spring版本转换为当前版本。我遇到了许多必须解决的问题。这是我不知道如何解决的问题,想知道为什么我必须这样做。对我来说,这似乎是个错误...

我有一系列REST api,每个api都是GET和POST请求的混合物。对于POST请求正文,在所有情况下对于响应正文,我都返回JSON。因此,看来我可以像这样全局定义整个API模块的返回类型:

@RequestMapping(path = "/api/v1", consumes = "application/json", produces = "application/json")
public class ApiService_Account extends ApiServiceBase {
    ...

我的问题是我收到415请求的响应,消息为“不支持内容类型”。但是GET请求通常没有内容,因此没有内容类型。为什么在没有内容的情况下代码会抱怨不存在的内容的类型?

这是我对这样一个端点的定义,以防万一:

@RequestMapping(method=RequestMethod.GET, value="/accounts")
@ResponseBody
public void getAccounts(...

我认为在GET请求中要求Content-Type标头(特别是JSON类型)是没有道理的。我宁愿不必为每个端点定义都定义我的有效载荷类型。

这里最好的课程是什么?我想念什么吗?这是错误吗?有没有一种方法可以只为所有POST请求指定'consumes'属性?

更新:我可以看到Spring在这里只是字面意思,而这也许已经结束了。我告诉我,我的所有端点都应该期待JSON,而这只是在继续。即使GET不应包含主体,将它作为GET请求的例外也可能没有意义。因此,也许这是一个“功能”。尽管如此,我还是想知道如何解决它,因此不必在每个端点上都指定一个“消耗”。我想我可以将POST放在一个类中,将GET放在另一个类中。好吧。

PS:如果我从第一个注释中删除了“ consumes”参数,问题就消失了。我尚未探讨是否会破坏我期望JSON正文的POST方法。

1 个答案:

答案 0 :(得分:0)

在类级别上定义@RequestMapping(consumes = "application/json")会强制使用Content-Type报头,用于对在此类中定义的一个端点的所有请求。当标题被忽略时,结果为415。

Spring不够聪明,无法确定GET请求上的Content-Type是没有道理的。

AFAIK没有简单的方法可以规避此问题。最简单的解决方案是:

@RequestMapping(path = "/api/v1", produces = "application/json")
public class ApiService_Account extends ApiServiceBase {

    @RequestMapping(method=RequestMethod.GET, value="/accounts")
    @ResponseBody
    public void getAccounts(...

    @RequestMapping(method=RequestMethod.POST, value="/accounts", consumes = "application/json")
    public void saveAccount(@RequestBody Account account...

这样,您将需要在consumes端点上定义真正消耗内容的RequestMapping