Creando un API REST
Vamos a crear un API REST sencillo apra implementar los métodos HTTP y entender un poco como funciona. En un primer momento debemos instalarlos Spring Boot.
Para instalarlo vale con acudir a nuestro IDE (en este caso Eclipse) y en el menú superior pulsamos en Help > Eclipse Marketplace. Nos saldrá un cuadro de dialogo donde podremos hacer nuestra búsqueda. A mi me valió con buscar "spring boot", no deberíais de tener problemas al respecto.
Una vez instalado el componente y reiniciado nuestro IDE, vamos a comenzar a crear nuestro proyecto. Para ello volvemos a nuestro menú superior y selecionamos File > New > Other, aquí os debería de aparecer Spring boot, seleccionamos "Spring Starter Project".
Nos saldrá la pantalla donde definiremos nuestro proyecto. Podéis llamarlo como queráis.
Lo mejor de usar Spring boot es que os crea todas las carpetas automáticamente. Hay dos archivos muy importantes, que son el pom.xml, donde añadiremos las dependencias necesarias para realizar nuestro proyecto y el archivo application.properties, donde definiremos nuestra conexión a la base de datos además de diversas configuraciones.
La estructura de vuestro proyecto debería quedar más o menos como os enseño en la imagen.
Comenzaremos con el pom.xml, donde debemos añadir nuestras dependencias. En este caso deben las dependencias que debéis de tener son las siguientes:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
Luego nos iremos al archivo de application.properties, donde haremos las configuraciones a nuestra BBDD.
server.port= (podéis poner aquí el puerto que queráis)
spring.datasource.url = jdbc:mysql://localhost:3306/clientes?zeroDateTimeBehavior=convertToNull&serverTimezone=UTC
spring.datasource.username = root
spring.datasource.password = (contraseña que sea)
spring.jpa.show-sql = true (esto hará que veamos en consolas las consultas sql que se hagan)
spring.jpa.hibernate.ddl-auto = update (crea el esquema en BBDD)
spring.jpa.open-in-view = false
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
Otro archivo importante se encuentra en el paquete, principal que estaría en src/main/java que será nuestra clase de entrada a la aplicación.
package com.init.clientes;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ProyectoApi3Application {
public static void main(String[] args) {
SpringApplication.run(ProyectoApi3Application.class, args);
}
}
Ahora nos crearemos nuestro POJO. Un objeto POJO es una instancia de una clase que no extiende ni implementa nada en especial. :
Por definición los POJOs no pueden:
- Extender otras clases
- Implementar interfaces (aunque no está mal visto que implementen interfaces marcadoras, al no aumentar la complejidad del código)
- Contener decoradores
En mi caso me he creado uno que se llama Cliente:
En esta clase vemos cosas interesantes: Establecemos la Entidad de la clase, y la tabla(Table(name="cliente") a la que hace referencia la base de datos. Cada una de las características de la clase, les asignamos una columna de la tabla, que hará que cada valor que llegue a cada una de ellas, ese valor se guardará en las diferentes columnas de la tabla. Por ejemplo el valor que llegue a nombre, ("Claudia") irá a la columna "nombre" de la tabla clientes. Existen parámetros como nullable=false, length=100, que hacen referencia a que no sea nulo, o que su longitud sea máxima de 100.
package com.init.clientes.entity;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
@Entity
@Table(name="clientes")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class Cliente {
@Id
@Column(name="ID")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
@Column(name="nombre", nullable=false, length=50)
private String nombre;
@Column(name="apellido1", nullable=false, length=100)
private String apellido1;
@Column(name="apellido2", nullable=false, length=100)
private String apellido2;
@Column(name="tipodocu", nullable=false, length=3)
private String tipoDocumento;
@Column(name="numedocu", nullable=false, length=20)
private String numeroDocumento;
public Cliente (long id, String nombre, String apellido1, String apellido2, String tipoDocumento, String numeroDocumento) {
this.id = id;
this.nombre = nombre;
this.apellido1 = apellido1;
this.apellido2 = apellido2;
this.tipoDocumento = tipoDocumento;
this.numeroDocumento = numeroDocumento;
}
public Cliente() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getApellido1() {
return apellido1;
}
public void setApellido1(String apellido1) {
this.apellido1 = apellido1;
}
public String getApellido2() {
return apellido2;
}
public void setApellido2(String apellido2) {
this.apellido2 = apellido2;
}
public String getTipoDocumento() {
return tipoDocumento;
}
public void setTipoDocumento(String tipoDocumento) {
this.tipoDocumento = tipoDocumento;
}
public String getNumeroDocumento() {
return numeroDocumento;
}
public void setNumeroDocumento(String numeroDocumento) {
this.numeroDocumento = numeroDocumento;
}
}
Luego nos creamos otro paquete que albergará una clase a la cual he llamado ClientesDAO, que extenderé de la clase JpaRepository para hacer uso de sus métodos que nos ayudarán a la hora de hacer select, insert, delete....
package com.init.clientes.DAO;
import com.init.clientes.entity.Cliente;
import com.init.clientes.entity.Cliente.*;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
public interface ClientesDAO extends JpaRepository {
}
Es ahora cuando nos vamos a la clase más importante. Donde definiremos las rutas a nuestros servicios y ejecutará las consultas o alteraciones en la tabla clientes. Esta clase se ha llamado ClientesRest.
package com.init.clientes.rest;
import com.init.clientes.DAO.ClientesDAO;
import com.init.clientes.entity.Cliente;
import java.util.Optional;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("clientes")
public class ClientesRest {
@Autowired
private ClientesDAO clienteDao;
//@GetMapping
//Cuando devolvemos todos los valores almacenados
@RequestMapping(value="getAllclientes", method =RequestMethod.GET)
public ResponseEntity> getClientes(){
List clientes = clienteDao.findAll();
return ResponseEntity.ok(clientes);
}
//Cuando devolvemos un valor específico
@RequestMapping(value="getAllclientes/{clienteId}", method =RequestMethod.GET)
public ResponseEntity getClienteById(@PathVariable("clienteId") Long clienteId){
Optional optionalCliente= clienteDao.findById(clienteId);
if(optionalCliente.isPresent()) {
return ResponseEntity.ok(optionalCliente.get());
}
return ResponseEntity.noContent().build();
}
@PostMapping(value="insertCliente")
//Hacemos un insert de un cliente
public ResponseEntity insertCliente(@RequestBody Cliente cliente){
Cliente newCliente = clienteDao.save(cliente);
return new ResponseEntity<>(HttpStatus.CREATED);
}
@DeleteMapping(value="deleteCliente/{clienteId}")
//eliminamos un cliente pasándole un id
public ResponseEntity deleteCliente(@PathVariable("clienteId") Long clienteId){
clienteDao.deleteById(clienteId);
return new ResponseEntity<>("Eliminado el registro: "+clienteId, HttpStatus.NO_CONTENT);
}
@PutMapping(value="updateCliente/{clienteId}")
//Actualizamos un registro de un cliente en concreto
public ResponseEntity updateCliente(@RequestBody Cliente cliente){
Optional optionalCliente= clienteDao.findById(cliente.getId());
if(optionalCliente.isPresent()) {
Cliente updateCliente = optionalCliente.get();
updateCliente.setNombre(cliente.getNombre());
clienteDao.save(updateCliente);
return ResponseEntity.ok(updateCliente);
}
return ResponseEntity.noContent().build();
}
}
La ruta inicial a nuestro servicio es "clientes" y por debajo de ella cuelgan los diferentes servicios que he creado. Tenemos getAllclientes donde obtendremos todos los clientes de nuestra BBDD
Tenemos getAllclientes/6, donde obtendremos el cliente con el id especificado en la ruta.
Cuando utilizamos los métodos de consulta, no hay problema de realizarlos con el navegado, pero cuando es necesario hacer un insert, delete o update de algún registro de la BBDD será necesario utilizar postman que simula las llamadas a nuestro servicio.
Voy a probar el servicio inserCliente, donde pasaremos los valores y comprobaremos que se insertan correctamente. A continuación os muestro los registros de la BBDD para que veáis como después de la llamada, tendremos uno nuevo.
Realizo la llamada al servicio.
Consultamos otra vez la BBDD.
Sabemos cuales son los código HTTP de respuesta, cuando creamos un cliente lo ideal sería utilizar :
return new ResponseEntity<>(HttpStatus.CREATED);
Esto hará que devolvamos un status code, que esto es importante para poder dar una pista a quien consuma nuestro servicio, en caso de que falle.
El resto de los servicios funcionan igual practicamente, en el caso de deleteCliente all pasar el id del que queremos eliminar, lo eliminará de nuestra BBDD.
Si queréis probarlo siempre podéis acudir a mi git para obtener el código y hacer pruebas en vuestro local.
Espero que os haya ayudado entender un poco más un API REST, Ahora sólo toca ampliar, y jugar con ello, haciéndolo cada vez más grande.
Conversación
Añadir un comentarioAún no hay comentarios.