具有不同PathVariable的相同休息端点

时间:2017-06-12 12:52:18

标签: java spring rest spring-boot kotlin

我正在尝试使用相同的uri但不同的类型创建两个休息端点。 第一个将通过EAN(Int)搜索第二个将通过id(String)搜索。我可以以某种方式超载端点吗?我使用Spring Boot with Kotlin

@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路径映射的不明确的处理程序方法...

5 个答案:

答案 0 :(得分:3)

我发现如果我想坚持使用API​​,那么唯一的方法是使用正则表达式。

@GetMapping("/book/{ean:[\\d]+}")

@GetMapping("/book/{id:^[0-9a-fA-F]{24}$}")

使用它可以将MongoDB生成的十六进制24字符与简单数字区分开来。如果有人找到更好的方式,请在评论中告诉我。

答案 1 :(得分:1)

从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()
}

或将ean或id传递给@RequestParam,例如/ book?ean = abcdefg,/ book?id = 5.

答案 2 :(得分:0)

在映射级别上无法执行此操作。可能你应该尝试以下路径:

/book/ean/{ean}
/book/id/{id}

或者只是

/book/id/{someUniversalId}

然后在可执行代码中区分不同类型的ID。

答案 3 :(得分:0)

开发查询过滤器/查询条件以处理类似以下内容将是有益的:

/book?q=ean+eq+abcdefg (meaning ean=abcdefg)
/book?q=id+gt+1000  (meaning id>1000)

等等。

答案 4 :(得分:0)

如何使用矩阵参数?

因此,对于id,您可以使用path参数-/books/{id}

对于ean,矩阵参数-/books;ean={ean}

实际上,对于id,您也可以使用矩阵参数-/books;{id}/books;id={id}

矩阵参数的通用网址-/{resource-name}[;{selector}]/

源-Apigee REST API设计最佳实践