在 Spring Boot 上重载 REST 控制器端点


一种特殊情况是需要相同的端点和方法,但具有不同的参数和不同的行为,例如

http://example.com/test?foo=bobby
http://example.com/test?bar=tables

现在处理这个问题的标准方法是让一个端点带有两个可选参数:
@GetMapping("/endpoint")
public Response getStuff(@RequestParam(value = "foo", required = false) String foo, 
            @RequestParam(value = "bar", required = false) String bar) {
        
        if (foo != null)
            // do stuff for foo
        else if (bar != null)
            // do stuff for bar
}

但是,还有另一种方法。

@GetMapping(value = "/endpoint", params = { "foo" })
public Response getStuff(@RequestParam(value = "foo") String foo) {

        // do stuff for foo
}

@GetMapping("/endpoint", params = { "bar" })
public Response getStuff(@RequestParam(value = "bar") String bar) {

        // do stuff for bar
}

此功能提供了很大的灵活性,但它带来了以下形式的风险:
www.example.com/endpoint?foo=bobby&bar=tables
这将导致 Spring boot 崩溃,因为它无法解析到 REST 控制器中的适当功能。
为了解决这个问题,可以使用其中一个端点作为默认值。附加参数将被忽略。

@GetMapping(value = "/endpoint", params = { "foo", "bar" })
public Response getStuff(@RequestParam(value = "foo") String foo
@RequestParam(value = "bar", required = false)) String bar {

        // do stuff for foo by default, ignore bar variable
}

@GetMapping("/endpoint", params = { "bar" })
public Response getStuff(@RequestParam(value = "bar") String bar) {

        // do stuff for bar
}