显然,Spring (4.3) 优先接受查询参数而不是路径变量,允许它们在将 @RequestMapping
与路径变量一起使用时覆盖路径变量,并将请求值绑定(bind)到模型类。给定如下 Controller :
@Controller
@RequestMapping("/")
public class HelloWorldController {
@RequestMapping(value = "/hi/{name}", method = RequestMethod.GET)
public @ResponseBody Greeting sayHello(
@Valid HelloParams helloParams) {
return new Greeting(helloParams.toString());
}
如果我们请求一个 URL,如 /hi/good?name=bad
,我们将看到 name
参数取值“bad”。因此,出现在 URL 路径中 {name}
位置的“good”值会被查询参数忽略或覆盖。如果我们删除“name”查询参数,则会得到“good”值。
注意:我正在使用模型类,以便我可以对模型的多个字段进行验证。我不能仅通过在一个简单的方法参数上使用 @PathVariable
来解决这个问题。
这是为什么?我在文档中没有看到任何提及此行为的内容。
是否有任何解决方法可以防止它发生?
Spring 的这种行为似乎也让 Springfox Swagger 感到困惑:在这种情况下,Swagger UI 生成的 URL 如下:/hi/{name}?name=foo
(文字大括号出现在网址)。而且,奇怪的是,它由于上述行为而起作用。但是,这会误导使用 API 的人,因为他们应该使用路径参数!
最佳答案
跟我的问题一模一样。我的解决方案是 @ApiImplicitParams。我的 Spring Boot 示例(使用 Lombok)代码如下。
@ApiOperation(value = "Test API.")
@RequestMapping(value = "/test/{memberId}", method = RequestMethod.GET)
@ApiImplicitParams({
@ApiImplicitParam(name = "memberId", value = "member identification number", paramType = "path", dataType = "long", required = true)
})
public ResponseEntity<String> testMethod(@Valid CommandObject command) {
return "hello, world~"
}
@Setter
@Getter
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class CommandObject {
private long memberId
}
@ApiImplicitParam的名字是CommandObject的字段名。重要的部分是paramType。它的值是路径还是查询。 path 用于路径变量,query 用于查询参数。
关于spring-mvc - Spring 4.3 允许查询参数覆盖来自 @RequestMapping 的路径变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47442926/