Spring 4.3允许查询参数覆盖来自@RequestMapping

时间:2017-11-22 19:54:43

标签: spring-mvc

实际上,Spring(4.3)优先接受路径变量的查询参数,允许它们在将@RequestMapping与路径变量一起使用时覆盖路径变量,并将请求值绑定到模型类。给出如下控制器:

@Controller
@RequestMapping("/")
public class HelloWorldController {
    @RequestMapping(value = "/hi/{name}", method = RequestMethod.GET)
    public @ResponseBody Greeting sayHello(
            @Valid HelloParams helloParams) {
        return new Greeting(helloParams.toString());
    }

如果我们请求/hi/good?name=bad之类的网址,我们会看到name param的值为“bad”。因此,查询参数会忽略或覆盖{name}位置中URL路径中存在的“良好”值。如果我们删除“name”查询参数,我们会得到“好”的值。

注意:我正在使用模型类,以便我可以对模型的多个字段进行验证。我只是通过在一个简单的方法参数上使用@PathVariable来解决这个问题。

为什么会这样?我在文档中没有看到任何提及此行为的内容。

是否有任何解决方法可以防止它发生?

Spring的这种行为似乎让Spring Fox Swagger感到困惑:在这种情况下,Swagger UI会生成以下URL:/hi/{name}?name=foo(URL中包含文字大括号)。奇怪的是,由于上述行为,它起作用。但是,使用API​​的人会误导它,因为他们应该使用路径参数!

2 个答案:

答案 0 :(得分:1)

与我的问题完全相同。我的解决方案是 @ApiImplicitParams 。我的Spring Boot Sample(带有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 path 用于路径变量, query 用于查询参数。

另外,请参阅文档:http://docs.swagger.io/swagger-core/v1.5.X/apidocs/index.html?io/swagger/annotations/ApiModelProperty.html

答案 1 :(得分:0)

如果要对requestparam和pathvariable使用相同的变量,则可以创建如下方法:

@RequestMapping(value = "/hi/{name}", method = RequestMethod.GET)
    public @ResponseBody String sayHello(@PathVariable(value="name") String name1, @RequestParam(value="name") String name2)