CodeGym /Blog Java /Random-ES /Descripción general de REST. Parte 3: Creación de un serv...
John Squirrels
Nivel 41
San Francisco

Descripción general de REST. Parte 3: Creación de un servicio RESTful en Spring Boot

Publicado en el grupo Random-ES
Esta es la parte final de nuestra descripción general de REST. En las partes anteriores, cubrimos: Descripción general de REST.  Parte 3: Creación de un servicio RESTful en Spring Boot - 1

Creando un proyecto

En esta sección, crearemos una pequeña aplicación RESTful usando Spring Boot. Nuestra aplicación implementará operaciones CRUD (Crear, Leer, Actualizar, Eliminar) en los clientes del ejemplo en la parte anterior de la descripción general. Para comenzar, crearemos una nueva aplicación Spring Boot a través del menú: Archivo -> Nuevo -> Proyecto... En la ventana que se abre, seleccione Spring Initializr y especifique el SDK del proyecto: Descripción general de REST.  Parte 3: Creación de un servicio RESTful en Spring Boot - 2Haga clic en el botón "Siguiente". En la siguiente ventana, especifique "Proyecto Maven" como tipo de proyecto, especifique el "Grupo" y el "Artefacto": Descripción general de REST.  Parte 3: Creación de un servicio RESTful en Spring Boot - 3Haga clic en el botón "Siguiente". En la siguiente ventana, debemos seleccionar los componentes de Spring Framework necesarios para el proyecto. Spring Web será suficiente para nosotros: Descripción general de REST.  Parte 3: Creación de un servicio RESTful en Spring Boot - 4Haga clic en el botón "Siguiente". Ahora todo lo que queda es indicar el nombre del proyecto y su ubicación en el sistema de archivos: Descripción general de REST.  Parte 3: Creación de un servicio RESTful en Spring Boot - 5Haga clic en el botón "Finalizar". El proyecto está creado y ahora podemos ver su estructura: Descripción general de REST.  Parte 3: Creación de un servicio RESTful en Spring Boot - 6IDEA generó un descriptor de implementación de Maven (pom.xml) y la clase principal de la aplicación ( RestExampleApplication) para nosotros. Así es como se ven:

pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-parent</artifactId>
       <version>2.2.2.RELEASE</version>
       <relativePath/> <!-- lookup parent from repository -->
   </parent>
   <groupId>com.codegym.lessons/groupId>
   <artifactId>rest_example</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <name>rest_example</name>
   <description>REST example project</description>

   <properties>
       <java.version>1.8</java.version>
   </properties>

   <dependencies>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-web</artifactId>
       </dependency>

       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-test</artifactId>
           <scope>test</scope>
           <exclusions>
               <exclusion>
                   <groupId>org.junit.vintage</groupId>
                   <artifactId>junit-vintage-engine</artifactId>
               </exclusion>
           </exclusions>
       </dependency>
   </dependencies>

   <build>
       <plugins>
           <plugin>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-maven-plugin</artifactId>
           </plugin>
       </plugins>
   </build>

</project>
Aplicación de ejemplo de descanso:

@SpringBootApplication
public class RestExampleApplication {

   public static void main(String[] args) {
       SpringApplication.run(RestExampleApplication.class, args);
   }

}

Crear funcionalidad REST

Nuestra aplicación es un sistema de gestión de clientes. Entonces, lo primero que debemos hacer es crear una entidad de cliente. Será una clase POJO (objeto Java simple y antiguo). Cree un modelpaquete dentro del com.codegym.lessons.rest_examplepaquete. Dentro del modelpaquete, crea el Customer:

public class Customer {

   private Integer id;
   private String name;
   private String email;
   private String phone;

   public Integer getId() {
       return id;
   }

   public void setId(Integer id) {
       this.id = id;
   }

   public String getName() {
       return name;
   }

   public void setName(String name) {
       this.name = name;
   }

   public String getEmail() {
       return email;
   }

   public void setEmail(String email) {
       this.email = email;
   }

   public String getPhone() {
       return phone;
   }

   public void setPhone(String phone) {
       this.phone = phone;
   }
}
El servicio implementará operaciones CRUD en los clientes. El siguiente paso es crear un servicio que implementará estas operaciones. En el com.codegym.lessons.rest_examplepaquete, cree un servicepaquete. Y dentro de eso, crea una CustomerServiceinterfaz. Aquí está el código de la interfaz con comentarios:

public interface CustomerService {

   /**
    * Creates a new customer
    * @param customer - Customer to be created
    */
   void create(Customer customer);

   /**
    * Returns a list of all existing customers
    * @return List of customers
    */
   List<Customer> readAll();

   /**
    * Returns a customer based on its ID
    * @param id - Customer ID
    * @return - Customer object with the given ID
    */
   Customer read(int id);

   /**
    * Updates the customer with the given ID,
    * according to the passed customer
    * @param customer - Customer to use to update the data
    * @param id - ID of the customer you want to update
    * @return - true if the data has been updated, otherwise false
    */
   boolean update(Customer customer, int id);

   /**
    * Deletes the customer with the given ID
    * @param id - ID of the customer to be deleted
    * @return - true if the customer was deleted, otherwise false
    */
   boolean delete(int id);
}
A continuación, necesitamos implementar esta interfaz. Ahora una Map<Integer, Customer>tienda de nuestros clientes. Las claves del mapa serán los ID de los clientes y los valores serán los propios clientes. Esto se hace para no sobrecargar este ejemplo con las especificaciones de trabajar con una base de datos real. Sin embargo, en el futuro podremos escribir otra implementación de la interfaz, que permitirá conectarse a una base de datos real. En el servicepaquete, cree una implementación de la CustomerServiceinterfaz:

@Service
public class CustomerServiceImpl implements CustomerService {

   // Customer repository
   private static final Map<Integer, Customer> CUSTOMER_REPOSITORY_MAP = new HashMap<>();
  
   // Variable for generating a customer ID
   private static final AtomicInteger CUSTOMER_ID_HOLDER = new AtomicInteger();

   @Override
   public void create(Customer customer) {
       final int customerId = CUSTOMER_ID_HOLDER.incrementAndGet();
       customer.setId(customerId);
       CUSTOMER_REPOSITORY_MAP.put(customerId, customer);
   }

   @Override
   public List<Customer> readAll() {
       return new ArrayList<>(CUSTOMER_REPOSITORY_MAP.values());
   }

   @Override
   public Customer read(int id) {
       return CUSTOMER_REPOSITORY_MAP.get(id);
   }

   @Override
   public boolean update(Customer customer, int id) {
       if (CUSTOMER_REPOSITORY_MAP.containsKey(id)) {
           customer.setId(id);
           CUSTOMER_REPOSITORY_MAP.put(id, customer);
           return true;
       }

       return false;
   }

   @Override
   public boolean delete(int id) {
       return CUSTOMER_REPOSITORY_MAP.remove(id) != null;
   }
}
La @Serviceanotación le dice a Spring que esta clase es un servicio. Este es un tipo especial de clase que implementa alguna lógica de aplicación empresarial. Posteriormente, gracias a esta anotación, Spring utilizará la inyección de dependencias para proporcionarnos una instancia de esta clase en todos los lugares donde se necesite. Ahora es el momento de crear un controlador. Esta es una clase especial en la que implementaremos la lógica para procesar las solicitudes de los clientes enviadas a los puntos finales (URI). Para aclarar todo esto, crearemos esta clase de forma incremental. Primero, cree la clase en sí y agregue una dependencia en CustomerService:

@RestController
public class CustomerController {

   private final CustomerService customerService;

   @Autowired
   public CustomerController(CustomerService customerService) {
       this.customerService = customerService;
   }
}
Expliquemos las anotaciones: @RestController le dice a Spring que esta clase es un controlador REST. En otras palabras, esta clase implementa la lógica para procesar las solicitudes de los clientes. @Autowired le dice a Spring que se debe agregar una dependencia aquí. Pasamos la CustomerServiceinterfaz al constructor. Anteriormente, marcamos la implementación de este servicio con la @Serviceanotación, y ahora Spring podrá pasar una instancia de esta implementación al constructor del controlador. A continuación, implementaremos cada método de controlador para manejar operaciones CRUD. Comencemos con la operación de creación. Para hacer esto, escribimos un createmétodo:

@PostMapping(value = "/customers")
public ResponseEntity<?> create(@RequestBody Customer customer) {
   customerService.create(customer);
   return new ResponseEntity<>(HttpStatus.CREATED);
}
Analicemos este método: @PostMapping(value = "/customers")significa que este método procesa las solicitudes POST enviadas a la dirección "/clientes". El método devuelve un ResponseEntity<?>. A ResponseEntityes una clase especial para devolver respuestas. Más tarde, lo usaremos para devolver un código de estado HTTP al cliente. El método tiene un @RequestBody Customer customerparámetro. El valor de este parámetro proviene del cuerpo de la solicitud. La @RequestBodyanotación así lo indica. Dentro del cuerpo del método, llamamos al create()método en el servicio creado previamente y lo pasamos al controlador del cliente recibido en los parámetros. Luego devolvemos el estado "201 Creado" creando un nuevo ResponseEntityobjeto y pasándole el HttpStatuscampo de enumeración correspondiente. A continuación, implementaremos elreadoperación: Primero, implementaremos la operación para obtener una lista de todos los clientes disponibles:

@GetMapping(value = "/customers")
public ResponseEntity<List<Customer>> read() {
   final List<Customer> customers = customerService.readAll();

   return customers != null &&  !customers.isEmpty()
           ? new ResponseEntity<>(customers, HttpStatus.OK)
           : new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
Profundicemos: @GetMapping(value = "/customers")todo aquí es similar a la @PostMappinganotación, pero ahora estamos procesando solicitudes GET. Esta vez devolvemos un ResponseEntity<List<Customer>>, y además de un estado HTTP, también devolveremos un cuerpo de respuesta, que será la lista de clientes. En los controladores REST de Spring, todo son objetos POJO y colecciones de objetos POJO, que se devuelven como cuerpos de respuesta y se serializan automáticamente en JSON, a menos que se especifique lo contrario. Esto nos queda perfecto. Dentro del método, usamos nuestro servicio para obtener una lista de todos los clientes. Luego, si la lista no es nula y no está vacía, entonces usamos elResponseEntityclass para devolver la lista de clientes y el código de estado HTTP "200 OK". De lo contrario, simplemente devolvemos el código de estado HTTP "404 Not Found". Ahora implementaremos la capacidad de obtener un cliente usando su ID:

@GetMapping(value = "/customers/{id}")
public ResponseEntity<Customer> read(@PathVariable(name = "id") int id) {
   final Customer customer = customerService.read(id);

   return customer != null
           ? new ResponseEntity<>(customer, HttpStatus.OK)
           : new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
Una cosa nueva aquí es la variable de ruta. La variable se define en la URI: value = "/customers/{id}". Lo indicamos entre llaves. Y lo recibimos como un intparámetro de método usando la @PathVariable(name = "id")anotación. Este método aceptará solicitudes enviadas a URI en el formulario /customers/{id}, donde {id}representa cualquier valor numérico. Este valor se pasa posteriormente a través de la int idvariable al parámetro de método. En el cuerpo, obtenemos el Customerobjeto usando nuestro servicio y el recibido id. Y luego, por analogía con la lista, devolvemos el estado "200 OK" y el Customerobjeto en sí, o simplemente el estado "404 No encontrado" si el sistema no tiene ningún cliente con ese id. Todavía necesitamos implementar dos operaciones: actualizar y eliminar. Aquí está el código para estos métodos:

@PutMapping(value = "/customers/{id}")
public ResponseEntity<?> update(@PathVariable(name = "id") int id, @RequestBody Customer customer) {
   final boolean updated = customerService.update(customer, id);

   return updated
           ? new ResponseEntity<>(HttpStatus.OK)
           : new ResponseEntity<>(HttpStatus.NOT_MODIFIED);
}

@DeleteMapping(value = "/customers/{id}")
public ResponseEntity<?> delete(@PathVariable(name = "id") int id) {
   final boolean deleted = customerService.delete(id);

   return deleted
           ? new ResponseEntity<>(HttpStatus.OK)
           : new ResponseEntity<>(HttpStatus.NOT_MODIFIED);
}
No hay nada esencialmente nuevo en estos métodos, por lo que omitiremos la descripción detallada. Lo único que vale la pena mencionar es que el update()método maneja las solicitudes PUT ( @PutMappinganotación) y el delete()método maneja las solicitudes DELETE ( DeleteMappinganotación). Aquí está el código completo para el controlador:

@RestController
public class CustomerController {

   private final CustomerService customerService;

   @Autowired
   public CustomerController(CustomerService customerService) {
       this.customerService = customerService;
   }

   @PostMapping(value = "/customers")
   public ResponseEntity<?> create(@RequestBody Customer customer) {
       customerService.create(customer);
       return new ResponseEntity<>(HttpStatus.CREATED);
   }

   @GetMapping(value = "/customers")
   public ResponseEntity<List<Customer>> read() {
       final List<Customer> customers = customerService.readAll();

       return customers != null &&  !customers.isEmpty()
               ? new ResponseEntity<>(customers, HttpStatus.OK)
               : new ResponseEntity<>(HttpStatus.NOT_FOUND);
   }

   @GetMapping(value = "/customers/{id}")
   public ResponseEntity<Customer> read(@PathVariable(name = "id") int id) {
       final Customer customer = customerService.read(id);

       return customer != null
               ? new ResponseEntity<>(customer, HttpStatus.OK)
               : new ResponseEntity<>(HttpStatus.NOT_FOUND);
   }

   @PutMapping(value = "/customers/{id}")
   public ResponseEntity<?> update(@PathVariable(name = "id") int id, @RequestBody Customer customer) {
       final boolean updated = customerService.update(customer, id);

       return updated
               ? new ResponseEntity<>(HttpStatus.OK)
               : new ResponseEntity<>(HttpStatus.NOT_MODIFIED);
   }

   @DeleteMapping(value = "/customers/{id}")
   public ResponseEntity<?> delete(@PathVariable(name = "id") int id) {
       final boolean deleted = customerService.delete(id);

       return deleted
               ? new ResponseEntity<>(HttpStatus.OK)
               : new ResponseEntity<>(HttpStatus.NOT_MODIFIED);
   }
}
Como resultado, la estructura de nuestro proyecto es la siguiente: Descripción general de REST.  Parte 3: Creación de un servicio RESTful en Spring Boot - 7

Lanzamiento y prueba

Para iniciar nuestra aplicación, simplemente ejecute el main()método en la RestExampleApplicationclase. Pero para probar los servicios web RESTful, necesitamos descargar software adicional. El hecho es que las solicitudes GET son bastante simples de enviar desde un navegador común, pero un navegador común no puede enviar solicitudes POST, PUT y DELETE. No te preocupes: puedes usar un programa llamado Postman para enviar cualquier solicitud HTTP. Puedes descargarlo aquí . Después de descargar e instalar Postman, comenzamos a probar nuestra aplicación. Para hacer esto, abra el programa y cree una nueva solicitud: Descripción general de REST.  Parte 3: Creación de un servicio RESTful en Spring Boot - 9Haga clic en el botón "Nuevo" en la esquina superior izquierda. A continuación, seleccione "Solicitud": Descripción general de REST.  Parte 3: Creación de un servicio RESTful en Spring Boot - 10A continuación, asígnele un nombre y guárdelo. Ahora intentemos enviar una solicitud POST al servidor y crear el primer cliente: Descripción general de REST.  Parte 3: Creación de un servicio RESTful en Spring Boot - 11Creamos varios clientes de esta manera. Luego cambiamos el tipo de solicitud a GET y enviamos la solicitud al servidor: Descripción general de REST.  Parte 3: Creación de un servicio RESTful en Spring Boot - 12

Resumen

¡Felicidades! Hemos cubierto lo suficiente REST. Hubo un gran volumen de material, pero espero que haya sido útil para usted:
  1. Aprendimos qué es REST.

  2. Aprendimos cómo nació REST.

  3. Hablamos sobre las limitaciones y los principios detrás de este estilo arquitectónico:

    • arquitectura cliente-servidor
    • apátrida
    • almacenamiento en caché
    • interfaz uniforme
    • capas
    • código bajo demanda (opcional)
  4. Exploramos los beneficios proporcionados por REST

  5. Examinamos en detalle cómo el servidor y el cliente interactúan entre sí a través del protocolo HTTP.

  6. Echamos un vistazo más de cerca a las solicitudes y respuestas. Diseccionamos sus partes constituyentes.

  7. Finalmente, obtuvimos algo de experiencia práctica al escribir nuestra propia aplicación RESTful pequeña usando Spring Boot. E incluso aprendimos a probarlo usando Postman.

Uf. Eso fue mucho, pero todavía hay algo para que hagas como tarea.

Tarea

Prueba lo siguiente:
  1. Siguiendo la descripción anterior, cree su propio proyecto Spring Boot e implemente la misma lógica que en la lección. Repite todo exactamente.
  2. Iniciar la aplicacion.
  3. Descargue y configure Postman (o cualquier otra herramienta para enviar solicitudes, por ejemplo, curl).
  4. Pruebe las solicitudes POST y GET de la misma manera que se describe en la lección.
  5. Pruebe las solicitudes PUT y DELETE usted mismo.
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION