1. Información general
En este tutorial rápido, exploraremos la anotación @PathVariable de Spring .
En pocas palabras, la anotación @PathVariable se puede usar para manejar variables de plantilla en la asignación de URI de solicitud y usarlas como parámetros de método.
Veamos cómo usar @PathVariable y sus diversos atributos.
2. Un mapeo simple
Un caso de uso simple de la anotación @PathVariable sería un punto final que identifica una entidad con una clave principal:
@GetMapping("/api/employees/{id}") @ResponseBody public String getEmployeesById(@PathVariable String id) { return "ID: " + id; }
En este ejemplo, usamos la anotación @PathVariable para extraer la parte de plantilla del URI representada por la variable {id} .
Una simple solicitud GET a / api / employee / {id} invocará getEmployeesById con el valor de id extraído:
//localhost:8080/api/employees/111 ---- ID: 111
Ahora, exploremos más a fondo esta anotación y echemos un vistazo a sus atributos.
3. Especificación del nombre de la variable de ruta
En el ejemplo anterior, omitimos definir el nombre de la variable de ruta de la plantilla ya que los nombres para el parámetro del método y la variable de ruta eran los mismos.
Sin embargo, si el nombre de la variable de ruta es diferente, podemos especificarlo en el argumento de la anotación @PathVariable :
@GetMapping("/api/employeeswithvariable/{id}") @ResponseBody public String getEmployeesByIdWithVariableName(@PathVariable("id") String employeeId) { return "ID: " + employeeId; }
//localhost:8080/api/employeeswithvariable/1 ---- ID: 1
También podemos definir el nombre de la variable de ruta como @PathVariable (valor = ”id”) en lugar de PathVariable (“id”) para mayor claridad.
4. Varias variables de ruta en una sola solicitud
Dependiendo del caso de uso, podemos tener más de una variable de ruta en nuestro URI de solicitud para un método de controlador, que también tiene múltiples parámetros de método :
@GetMapping("/api/employees/{id}/{name}") @ResponseBody public String getEmployeesByIdAndName(@PathVariable String id, @PathVariable String name) { return "ID: " + id + ", name: " + name; }
//localhost:8080/api/employees/1/bar ---- ID: 1, name: bar
También podemos manejar más de un parámetro @PathVariable usando un parámetro de método de tipo java.util.Map:
@GetMapping("/api/employeeswithmapvariable/{id}/{name}") @ResponseBody public String getEmployeesByIdAndNameWithMapVariable(@PathVariable Map pathVarsMap) { String id = pathVarsMap.get("id"); String name = pathVarsMap.get("name"); if (id != null && name != null) { return "ID: " + id + ", name: " + name; } else { return "Missing Parameters"; } }
//localhost:8080/api/employees/1/bar ---- ID: 1, name: bar
Sin embargo, hay un pequeño problema al manejar múltiples parámetros @ PathVariable cuando la cadena de la variable de ruta contiene un carácter de punto (.) Hemos discutido esos casos de esquina en detalle aquí.
5. Variables de ruta opcionales
En Spring, los parámetros del método anotados con @PathVariable son obligatorios de forma predeterminada:
@GetMapping(value = { "/api/employeeswithrequired", "/api/employeeswithrequired/{id}" }) @ResponseBody public String getEmployeesByIdWithRequired(@PathVariable String id) { return "ID: " + id; }
Por su apariencia, el controlador anterior debe manejar las rutas de solicitud / api / employeewithrequired y / api / employeewithrequired / 1 . Pero, dado que los parámetros del método anotados por @PathVariables son obligatorios por defecto, no maneja las solicitudes enviadas a / api / employee con la ruta requerida :
//localhost:8080/api/employeeswithrequired ---- {"timestamp":"2020-07-08T02:20:07.349+00:00","status":404,"error":"Not Found","message":"","path":"/api/employeeswithrequired"}
//localhost:8080/api/employeeswithrequired/1 ---- ID: 111
Podemos manejar esto de dos maneras.
5.1. Configurar @PathVariable como no obligatorio
Podemos establecer la propiedad requerida de @PathVariable en false para que sea opcional. Por lo tanto, modificando nuestro ejemplo anterior, ahora podemos manejar las versiones de URI con y sin la variable de ruta:
@GetMapping(value = { "/api/employeeswithrequiredfalse", "/api/employeeswithrequiredfalse/{id}" }) @ResponseBody public String getEmployeesByIdWithRequiredFalse(@PathVariable(required = false) String id) { if (id != null) { return "ID: " + id; } else { return "ID missing"; } }
//localhost:8080/api/employeeswithrequiredfalse ---- ID missing
5.2. Usando java.util.Optional
Desde Spring 4.1, también podemos usar java.util.Optional (disponible en Java 8+) para manejar una variable de ruta no obligatoria:
@GetMapping(value = { "/api/employeeswithoptional", "/api/employeeswithoptional/{id}" }) @ResponseBody public String getEmployeesByIdWithOptional(@PathVariable Optional id) { if (id.isPresent()) { return "ID: " + id.get(); } else { return "ID missing"; } }
Ahora, si no especificamos la identificación de la variable de ruta en la solicitud, obtenemos la respuesta predeterminada:
//localhost:8080/api/employeeswithoptional ---- ID missing
5.3. Uso de un parámetro de método del mapa de tipos
Como se mostró anteriormente, podemos usar un único parámetro de método de tipo java.util.Map para manejar todas las variables de ruta en el URI de solicitud. También podemos usar esta estrategia para manejar el caso de variables de ruta opcionales:
@GetMapping(value = { "/api/employeeswithmap/{id}", "/api/employeeswithmap" }) @ResponseBody public String getEmployeesByIdWithMap(@PathVariable Map pathVarsMap) { String id = pathVarsMap.get("id"); if (id != null) { return "ID: " + id; } else { return "ID missing"; } }
6. Valor predeterminado para @PathVariable
Fuera de la caja, no existe una disposición para definir un valor predeterminado para los parámetros del método anotados con @PathVariable . Sin embargo, podemos usar las mismas estrategias discutidas anteriormente para satisfacer el caso de valor predeterminado para @PathVariable . Solo necesitamos verificar si hay nulo en la variable de ruta.
Por ejemplo, usando java.util.Optional , podemos identificar si la variable de ruta es nula o no. Si es nulo, entonces podemos responder a la solicitud con un valor predeterminado:
@GetMapping(value = { "/api/defaultemployeeswithoptional", "/api/defaultemployeeswithoptional/{id}" }) @ResponseBody public String getDefaultEmployeesByIdWithOptional(@PathVariable Optional id) { if (id.isPresent()) { return "ID: " + id.get(); } else { return "ID: Default Employee"; } }
7. Conclusión
En este artículo, discutimos cómo usar la anotación @PathVariable de Spring . También identificamos las diversas formas de utilizar eficazmente la anotación @PathVariable para adaptarse a diferentes casos de uso, como los parámetros opcionales y el manejo de valores predeterminados.
El ejemplo de código que se muestra en este artículo también está disponible en Github.