El mismo extremo de reposo con diferentes PathVariable

Estoy tratando de hacer dos extremos de reposo con el mismo uri pero diferentes types. El primero searchía por EAN (Int) el segundo searchía por id (String). ¿Podría sobrecargar de alguna manera el punto final? Uso Spring Boot con 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() } 

Después de esto, recibí una exception de que se asignaron múltiples methods para el mismo punto final.

… NestedServletException: process de request fallido; la exception anidada es java.lang.IllegalStateException: methods de controller ambiguos asignados para la ruta HTTP …

Desde el punto de vista HTTP, es el mismo punto final ya que es un protocolo basado en text y el parámetro de ruta es siempre una cadena. Por lo tanto, Spring lanza una exception.

Para tratar el problema, puede identificar el tipo de argumento dentro del cuerpo del método:

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

o pase ean o id como @RequestParam like / book? ean = abcdefg, / book? id = 5.

No es posible hacerlo en el nivel de mapeo. Probablemente deberías probar paths como:

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

Alternativamente solo

 /book/id/{someUniversalId} 

luego distinga entre diferentes types de identificadores en su código ejecutable.

Descubrí que la única manera de hacerlo es regex si quiero mantener mi API.

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

Con él, el carácter hexadecimal 24 generado por MongoDB se puede diferenciar de los numbers simples. Si alguien encuentra una mejor manera, házmelo saber en los comentarios.

Sería beneficioso desarrollar un filter de consulta / criterios de consulta para procesar algo como:

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

y así.