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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35155916/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 00:57:36  来源:igfitidea点击:

Handling ambiguous handler methods mapped in REST application with Spring

springrestpath-variablesrequest-mapping

提问by mikezang

I tried to use some code as below:

我尝试使用一些代码如下:

@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);
}

But I got error like this, how can I do?

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

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]

回答by cassiomolin

Spring can't distinguish if the request GET http://localhost:8080/api/brand/1will be handled by getBrand(Integer)or by getBrand(String)because your mapping is ambiguous.

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

Try using a query parameter for the getBrand(String)method. It seems more appropriate, since you are performing a query:

尝试对该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> getBrand(@RequestParam(value="name") String name) {
    return brandService.getSome(name);
}

Using the approach described above:

使用上述方法:

  • Requests like GET http://localhost:8080/api/brand/1will be handled by getBrand(Integer).
  • Requests like GET http://localhost:8080/api/brand?name=nikewill be handled by getBrand(String).
  • 类似的请求GET http://localhost:8080/api/brand/1将由 处理getBrand(Integer)
  • 类似的请求GET http://localhost:8080/api/brand?name=nike将由 处理getBrand(String)


Just a hint:As a common practice, prefer plural nouns for collections of resources. So instead of /brand, use /brands.

只是一个提示:作为一种常见的做法,对于资源的集合,更喜欢使用复数名词。因此,不要/brand使用/brands.

回答by sandeep srivastav vaddiparthy

@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);
}

When you run the app, and access the endpoints you tried coding up you realize the following, 'http://localhost:8086/brand/1' and 'http://localhost:8086/brand/FooBar' correspond to the same URL format (which can be described as protocol+endpoint+'brand'+). So SpringBoot is essentially confused if it should call the function 'getBrand' with a String datatype or an Integer. So to get over this I'd suggest you use a query parameter as mentioned by @cassiomolin or have separate paths for both invocations. This may be against the REST principles but assuming you are just doing a sample app this is another workaround.

当您运行应用程序并访问您尝试编码的端点时,您会意识到以下内容,“ 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);
}

This worked for me.

这对我有用。