Spring Boot 2.3 Ambiguous Mapping冲突 如何通过Content-Type区分映射方法
问题根因
你遇到的映射歧义和内容协商没有关系,Spring MVC的consumes匹配逻辑本身就是独立于内容协商机制存在的,在请求映射的初选阶段就会执行,不需要额外配置内容协商策略来支持。出现冲突的核心原因有两个:
- 两个方法的
@RequestBody都配置了required=false,当请求不带任何请求体且未传递Content-Type头时,Spring会默认将请求的Content-Type识别为*/*,此时两个方法的consumes配置都能匹配*/*,触发歧义。 - 两个接口的路径模板完全一致(仅路径变量名称不同不影响路径匹配结果)、请求方法都是POST,除
consumes外没有其他映射区分条件,当出现满足两个方法匹配规则的请求时,Spring无法判断优先级就会抛出异常。
consumes属性的作用
consumes的核心作用是根据请求的Content-Type头筛选处理方法,属于请求映射阶段的过滤规则,和处理返回值的内容协商机制完全无关:
- 当请求携带明确的
Content-Type头时,Spring会直接将头的值和方法配置的consumes列表做匹配,只有匹配成功的方法才会进入后续的候选列表。 - 只有当请求无
Content-Type头、或头的值不符合任何consumes配置时,才会触发模糊匹配逻辑,导致你遇到的冲突问题。
解决方案
你可以任选以下一种方案解决冲突:
- 方案1:给第二个方法的
consumes配置增加否定规则,明确排除text/plain类型,修改后配置如下:
@RequestMapping(method = { RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE, Class1.MEDIA_TYPE_JSON_VALUE }, consumes = { Class1.MEDIA_TYPE_JSON_VALUE, Class2.MEDIA_TYPE_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE, "!" + MediaType.TEXT_PLAIN_VALUE})
这样当请求Content-Type为text/plain时只会匹配第一个方法,其余请求匹配第二个方法,不会再出现歧义。
- 方案2:如果业务允许,将其中一个方法的
@RequestBody改为required=true,避免无请求体的请求同时匹配两个方法。 - 方案3:给其中一个方法增加额外的映射区分条件,比如通过
headers参数指定自定义请求头、或者params参数指定特定请求参数,进一步缩小匹配范围。
内容的提问来源于stack exchange,提问作者ledigiacomo
相关产品推荐
相关产品推荐

