相同的其他端点具有不同的PathVariable
我试图做两个相同的uri,但不同类型的休息端点。 第一个将通过EAN(Int)进行搜索,第二个将通过id(String)进行搜索。 我能否以某种方式超载端点? 我和Kotlin一起使用Spring Boot
@GetMapping("/book/{ean}") fun getABookByEan(@PathVariable ean: Int) : ResponseEntity<*> { repository.getByEan(ean)?.let { return ResponseEntity.status(HttpStatus.OK).body(it) } throw ItemNotFoundException() } @GetMapping("/book/{id}") fun getABookById(@PathVariable id: String) : ResponseEntity<*> { repository.getById(id)?.let { return ResponseEntity.status(HttpStatus.OK).body(it) } throw ItemNotFoundException() }
在此之后,我得到了一个异常,多个方法被映射为相同的端点。
NestedServletException:请求处理失败; 嵌套异常是java.lang.IllegalStateException:为HTTP路径映射的模糊处理程序方法…
从HTTP的角度来看,它是相同的端点,因为它是基于文本的协议,路径参数始终是一个字符串。 因此,Spring引发一个异常。
要处理这个问题,您可以在方法体内标识参数类型:
@GetMapping("/book/{identifier}") fun getABookById(@PathVariable identifier: String) : ResponseEntity<*> { try { val id = identifier.toInt() // id case repository.getById(id)?.let { return ResponseEntity.status(HttpStatus.OK).body(it) } } catch (e: NumberFormatException) { // ean case repository.getByEan(identifier)?.let { return ResponseEntity.status(HttpStatus.OK).body(it) } } throw ItemNotFoundException() }
或者像@RequestParam一样传递ean或者id / book?ean = abcdefg,/ book?id = 5。
在映射层面上做不到这一点。 可能你应该尝试像下面这样的路径:
/book/ean/{ean} /book/id/{id}
或者只是
/book/id/{someUniversalId}
然后在可执行代码中区分不同类型的ID。
我发现唯一的方法是正则表达式,如果我想坚持我的API。
@GetMapping("/book/{ean:[\\d]+}") @GetMapping("/book/{id:^[0-9a-fA-F]{24}$}")
有了它,MongoDB生成的十六进制24个字符就可以与简单的数字区分开来。 如果有人找到更好的方法,让我知道在评论中。
开发一个查询过滤器/查询条件将是有益的,以处理类似于:
/book?q=ean+eq+abcdefg (meaning ean=abcdefg) /book?q=id+gt+1000 (meaning id>1000)
等等。