Introducción
Existen 3 niveles para aplicar API REST en el desarrollo de una Aplicación Web.
Cumplir con estás nos garantiza las mejores practicas para su implementación, integración, estabilidad y escabilidad.
Para detalles se puede consultar http://asiermarques.com/2013/conceptos-sobre-apis-rest/
Nivel 1. Uso correcto de URIs
- Identificar de forma única el recurso
- Las URI no deben contener acciones
- Independientes del formato
- Jerarquía lógica
- Los filtrados no se deben hacer en la URI
Nivel 2. HTTP
- Usar métodos HTTP; GET, POST, PUT, DELETE y PATCH
- Código de estado
- Aceptación de tipos de contenido
Nivel 3. Hypermedia
Se vera mas a detalle posteriormente.
Con lo que llevamos hasta este momento, podemos generar un proyecto de API REST en Web con las mejores practicas.
Vamos a retomar la tabla Persona y crear un Sistema Web con API REST para administrar personas; crear, leer, actualizar y eliminar.
Construir aplicación
Crear proyecto
Ir a
File -> New -> Other… -> Spring Boot -> Spring Starter Project
Seleccionamos nombre del proyecto, tipo, versión de java, paquete, entre otras opciones. Clic en Next>. Seleccionamos la versión de Spring Boot y las dependencias:
- JPA
- H2
- MySQL
- Web
Clic en Next> y posteriormente clic en Finish.
Crear paquetes
Creamos los paquetes
- com.mio.administrar.controller
- com.mio.administrar.repository
- com.mio.administrar.entity
Copiar clases e interfaces
Tomando las clases e interfaces del proyecto anterior https://github.com/arielolivagh/gs-rest-service-complete/tree/v2.0 copiamos:
- La clase PersonaController al paquete com.mio.administrar.controller
- La interface PersonaRepository al paquete com.mio.administrar.repository
- La clase Persona al paquete com.mio.administrar.entity
Conexión a la Base de Datos
Escribimos los parámetros de conexión a la Base de Datos en el archivo application.properties.
1 2 3 4 5 |
spring.jpa.show-sql = true spring.jpa.hibernate.ddl-auto=update spring.datasource.url=jdbc:mysql://localhost:3306/Pruebas spring.datasource.username=root spring.datasource.password=root |
Crear consulta para búsqueda de personas por id
En la clase repository vamos a crear un nuevo query para obtener una persona por su id.
1 2 |
@Query("select p from Persona p where p.idPersona = ?1") Persona findPersona(int id); |
Crear controller de calidad
Crear personas
- Método POST
- La respuesta es Json
- Documentación JavaDoc
1234567891011121314151617/*** Crea una persona: POST http://{servidor}:{puerto}/persona* @param nombre Nombre de la persona* @param edad Edad de la persona* @param sexo Sexo de la persona* @return mensaje de 'Agregado correctamente'*/@RequestMapping(method=RequestMethod.POST,produces={"application/json"})public String createPersona(@RequestParam String nombre,@RequestParam int edad,@RequestParam String sexo) {Persona p = new Persona();p.setNombre(nombre);p.setEdad(edad);p.setSexo(sexo);personaRepository.save(p);return "Agregado correctamente";}
Consumir:
1curl -i -X POST -d "nombre=Mariel&edad=51&sexo=F" http://localhost:8080/persona
Leer todas las personas
- Método GET
- La respuesta es Json
- ocumentación JavaDoc
12345678/*** Obtiene todas las personas: GET http://{servidor}:{puerto}/persona* @return Lista de personas*/@RequestMapping(method=RequestMethod.GET,produces={"application/json"})public Iterable<Persona> readPersonas() {return personaRepository.findAll();}
Consumir:
1curl -i -X GET http://localhost:8080/persona
Leer una persona
- Método GET
- La respuesta es Json
- Documentación JavaDoc
123456789/*** Obtiene una person por id: GET http://{servidor}:{puerto}/persona/{id}* @param id Id de la persona. En la Url* @return Una personas*/@RequestMapping(value="/{id}",method=RequestMethod.GET,produces={"application/json"})public Persona readPersonaById(@PathVariable("id") int id) {return personaRepository.findPersona(id);}
Consumir:
1curl -i -X GET http://localhost:8080/persona/7
Actualiza una persona
- Método PUT
- La respuesta es Json
- Documentación JavaDoc
123456789101112131415161718/*** Actualiza una persona por Id: PUT http://{servidor}:{puerto}/persona/{id}* @param id Id de la persona. En la Url* @param nombre Nombre de la persona* @param edad Edad de la persona* @param sexo Sexo de la person* @return mensaje de 'Actualizado correctamente'*/@RequestMapping(value="/{id}",method=RequestMethod.PUT,produces={"application/json"})public String updatePersona(@RequestParam String nombre,@RequestParam int edad,@RequestParam String sexo,@PathVariable("id") int id) {Persona p = new Persona();p.setIdPersona(id);p.setNombre(nombre);p.setEdad(edad);p.setSexo(sexo);personaRepository.save(p);return "Actualizado correctamente";}
Consumir:
1curl -i -X PUT -d "nombre=Ariel&edad=100&sexo=M" http://localhost:8080/persona/7
Actualiza edad de una persona
- Método PATCH
- La respuesta es Json
- Documentación JavaDoc
12345678910111213/*** Actualiza la edad de una persona por Id: PATCH http://{servidor}:{puerto}/persona/{id}* @param id Id de la persona. En la Url* @param edad Edad de la persona* @return mensaje de 'Actualizando la edad correctamente'*/@RequestMapping(value="/{id}",method=RequestMethod.PATCH,produces={"application/json"})public String updateParcialPersona(@PathVariable("id") int id,@RequestParam int edad) {Persona p = personaRepository.findPersona(id);p.setEdad(edad);personaRepository.save(p);return "Actualizando la edad correctamente";}
Consumir:
1curl -i -X PATCH -d "edad=10" http://localhost:8080/persona/7
Elimina todas las personas
- Método DELETE
- La respuesta es Json
- Documentación JavaDoc
123456789/*** Elimina todas las personas: DELETE http://{servidor}:{puerto}/persona* @return mensaje de 'Todo eliminado correctamente'*/@RequestMapping(method=RequestMethod.DELETE,produces={"application/json"})public String deleteAllPersona() {personaRepository.deleteAll();return "Todo eliminado correctamente";}
Consumir:
1curl -i -X DELETE http://localhost:8080/persona
Elimina una persona
- Método DELETE
- La respuesta es Json
- Documentación JavaDoc
123456789101112/*** Elimina una persona por id: DELETE http://{servidor}:{puerto}/persona/{id}* @param id Id de la persona. En la Url* @return mensaje de 'Eliminado correctamente'*/@RequestMapping(value="/{id}", method=RequestMethod.DELETE,produces={"application/json"})public String deletePersona(@PathVariable("id") int id) {Persona p = new Persona();p.setIdPersona(id);personaRepository.delete(p);return "Eliminado correctamente";}
Consumir:
1curl -i -X DELETE http://localhost:8080/persona/7
Otras
Descargar proyecto
Se puede descargar el proyecto completo de https://github.com/arielolivagh/administrarPersona/tree/v1.0
He visto muchas cosas que me han llamado la atención. Y quería comentar algunas para que la gente no copie los errores que veo aquí, sobretodo que no piensen que estamos haciendo un «controller de calidad» siguiendo estos pasos.
En cuanto al controlador:
Nunca puede haber una respuesta de un json con un simple String hardcodeado en el propio método, como en createPersona el String que devuelves….»Agregado correctamente»
Por otro lado, es confuso tener un método en el controlador llamado readPersonaById que devuelva una lista con todas las personas
Repositorio:
La query así de simple se podría hacer utilizando filtros de CrudRepository y deducir la consulta a partir del nombre, en este caso:
Persona findById(id)
Hay unos cuantos gazapos, creo que no estaría mal darle un repaso para evitar confundir a la gente que llega aquí buscando información de ayuda.
Me parecen lógicas tus sugerencias. Voy a documentarme sobre los puntos y si son exactas hago las correcciones. Gracias.