使用 Spring 处理在 REST 应用程序中映射的模糊处理程序方法

Posted

技术标签:

【中文标题】使用 Spring 处理在 REST 应用程序中映射的模糊处理程序方法【英文标题】:Handling ambiguous handler methods mapped in REST application with Spring 【发布时间】:2016-05-11 09:39:39 【问题描述】:

我尝试使用如下代码:

@RequestMapping(value = "/id", method = RequestMethod.GET)
public Brand getBrand(@PathVariable Integer id) 
    return brandService.getOne(id);


@RequestMapping(value = "/name", method = RequestMethod.GET)
public List<Brand> getBrand(@PathVariable String name) 
    return brandService.getSome(name);

但是我遇到了这样的错误,我该怎么办?

java.lang.IllegalStateException: Ambiguous handler methods mapped for HTTP path 'http://localhost:8080/api/brand/1': public java.util.List com.zangland.controller.BrandController.getBrand(java.lang.String), public com.zangland.entity.Brand com.zangland.controller.BrandController.getBrand(java.lang.Integer)
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.lookupHandlerMethod(AbstractHandlerMethodMapping.java:375) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]

【问题讨论】:

【参考方案1】:

Spring 无法区分请求 GET http://localhost:8080/api/brand/1 将由 getBrand(Integer) 还是由 getBrand(String) 处理,因为您的映射不明确。

尝试为getBrand(String) 方法使用查询参数。这似乎更合适,因为您正在执行查询:

@RequestMapping(value = "/id", method = RequestMethod.GET)
public Brand getBrand(@PathVariable Integer id) 
    return brandService.getOne(id);


@RequestMapping(method = RequestMethod.GET)
public List<Brand> getBrands(@RequestParam(value="name") String name) 
    return brandService.getSome(name);

使用上述方法:

GET http://localhost:8080/api/brand/1 之类的请求将由 getBrand(Integer) 处理。 GET http://localhost:8080/api/brand?name=nike 之类的请求将由 getBrand(String) 处理。

提示:作为一种常见做法,资源集合首选复数名词。所以不要使用/brand,而是使用/brands

【讨论】:

如果控制器也有一个 getAll() 方法和以下 URL:http://localhost:8080/api/brand。如何将这三个放在一起(按名称的 getAll 和 getBrand 会有冲突的路径) @fireball.1 name 查询参数的存在(或不存在)将决定服务器是否会获取所有品牌(或按名称过滤品牌)。 这似乎不起作用,我在这里详细描述了我的问题:***.com/questions/64913401/… @fireball.1 我已经为您的问题发布了答案。希望对您有所帮助。【参考方案2】:
@RequestMapping(value = "/id", method = RequestMethod.GET)
public Brand getBrand(@PathVariable Integer id) 
    return brandService.getOne(id);


@RequestMapping(value = "/name", method = RequestMethod.GET)
public List<Brand> getBrand(@PathVariable String name) 
    return brandService.getSome(name);

当您运行应用程序并访问您尝试编码的端点时,您会意识到以下内容,“http://localhost:8086/brand/1”和“http://localhost:8086/brand/FooBar”对应于相同的 URL 格式(可以描述为协议+端点+'品牌'+)。因此,如果 SpringBoot 应该使用 String 数据类型或 Integer 调用函数“getBrand”,它本质上会感到困惑。因此,为了克服这个问题,我建议您使用@cassiomolin 提到的查询参数,或者为两个调用设置单独的路径。这可能违反 REST 原则,但假设您只是在做一个示例应用程序,这是另一种解决方法。

@RequestMapping(value = "/id/id", method = RequestMethod.GET)
public Brand getBrand(@PathVariable Integer id) 
    return brandService.getOne(id);


@RequestMapping(value = "/name/name", method = RequestMethod.GET)
public List<Brand> getBrand(@PathVariable String name) 
    return brandService.getSome(name);

这对我有用。

【讨论】:

以上是关于使用 Spring 处理在 REST 应用程序中映射的模糊处理程序方法的主要内容,如果未能解决你的问题,请参考以下文章

ControllerAdvice 的异常处理程序在使用 Spring Boot 的 Rest API 获取请求中不起作用。如何解决?

处理事务中的 spring-data-rest 应用程序事件

在 Spring Boot REST 应用程序中处理 gzipped 请求

[转] 使用Spring MVC构建REST风格WEB应用

spring rest 处理空请求体(400 Bad Request)

在 Flutter 中映射流