JavaRush /Blog Java /Random-ES /Descripción general del DESCANSO. Parte 3: Creación de un...

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

Publicado en el grupo Random-ES
Esta es la parte final del análisis REST. En partes anteriores: Descripción general del DESCANSO.  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 de la última parte del análisis. Primero, creemos 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 Project SDK: Descripción general del DESCANSO.  Parte 3: Creación de un servicio RESTful en Spring Boot - 2haga clic en el botón Siguiente. En la siguiente ventana, especifique el tipo de proyecto Maven, especifique Grupo y Artefacto: Descripción general del DESCANSO.  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 del DESCANSO.  Parte 3: Creación de un servicio RESTful en Spring Boot - 4haga clic en el botón Siguiente. A continuación, sólo queda especificar el nombre del proyecto y su ubicación en el sistema de archivos: Descripción general del DESCANSO.  Parte 3: Creación de un servicio RESTful en Spring Boot - 5Haga clic en el botón Finalizar. El proyecto ha sido creado, ahora podemos ver su estructura: Descripción general del DESCANSO.  Parte 3: Creación de un servicio RESTful en Spring Boot - 6IDEA ha generado para nosotros el descriptor de implementación del sistema de compilación Maven - pom.xml y la clase de aplicación principal: RestExampleApplication. Aquí está su código:
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.javarush.lectures</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>
RestExampleAplicación:
@SpringBootApplication
public class RestExampleApplication {

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

}

Creando funcionalidad REST

Nuestra aplicación gestiona clientes. Entonces, lo primero que debemos hacer es crear una entidad de cliente. Esta será una clase POJO. Creemos un paquete modeldentro de un paquete com.javarush.lectures.rest_example. modelCreemos una clase dentro del paquete Client:
public class Client {

   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 el cliente. El siguiente paso es crear un servicio que implementará estas operaciones. En el paquete com.javarush.lectures.rest_examplecrearemos un paquete service, dentro del cual crearemos una interfaz ClientService. Aquí está el código de la interfaz con comentarios:
public interface ClientService {

   /**
    * Создает нового клиента
    * @param client - клиент для создания
    */
   void create(Client client);

   /**
    * devoluciones список всех имеющихся клиентов
    * @return список клиентов
    */
   List<client> readAll();

   /**
    * devoluciones клиента по его ID
    * @param id - ID клиента
    * @return - un objeto клиента с заданным ID
    */
   Client read(int id);

   /**
    * Обновляет клиента с заданным ID,
    * в соответствии с переданным клиентом
    * @param client - клиент в соответсвии с которым нужно обновить данные
    * @param id - id клиента которого нужно обновить
    * @return - true если данные были обновлены, иначе false
    */
   boolean update(Client client, int id);

   /**
    * Удаляет клиента с заданным ID
    * @param id - id клиента, которого нужно удалить
    * @return - true если клиент был удален, иначе false
    */
   boolean delete(int id);
}
A continuación necesitamos crear una implementación de esta interfaz. Ahora actuará como un repositorio de cliente Map<Integer, Client>. La clave de la tarjeta será la identificación del cliente y el valor será el propio cliente. Esto se hizo para no sobrecargar el ejemplo con los detalles específicos de trabajar con la base de datos. Sin embargo, en el futuro podremos escribir otra implementación de la interfaz en la que será posible conectar una base de datos real. En el paquete servicecrearemos una implementación de la interfaz ClientService:
@Service
public class ClientServiceImpl implements ClientService {

   // Хранoще клиентов
   private static final Map<Integer, Client> CLIENT_REPOSITORY_MAP = new HashMap<>();

   // Переменная для генерации ID клиента
   private static final AtomicInteger CLIENT_ID_HOLDER = new AtomicInteger();

   @Override
   public void create(Client client) {
       final int clientId = CLIENT_ID_HOLDER.incrementAndGet();
       client.setId(clientId);
       CLIENT_REPOSITORY_MAP.put(clientId, client);
   }

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

   @Override
   public Client read(int id) {
       return CLIENT_REPOSITORY_MAP.get(id);
   }

   @Override
   public boolean update(Client client, int id) {
       if (CLIENT_REPOSITORY_MAP.containsKey(id)) {
           client.setId(id);
           CLIENT_REPOSITORY_MAP.put(id, client);
           return true;
       }

       return false;
   }

   @Override
   public boolean delete(int id) {
       return CLIENT_REPOSITORY_MAP.remove(id) != null;
   }
}
La anotación @Servicele dice a Spring que esta clase es un servicio. Este es un tipo especial de clase en el que se implementa cierta lógica empresarial de la aplicación. Posteriormente, gracias a esta anotación, Spring nos proporcionará una instancia de esta clase en los lugares donde sea necesaria mediante Dependency injection. Ahora es el momento de crear el controlador. Una clase especial en la que implementamos la lógica para procesar solicitudes de clientes para puntos finales (URI). Para que quede más claro, crearemos esta clase en partes. Primero, creemos la clase en sí e introduzcamos una dependencia de ella ClientService:
@RestController
public class ClientController {

   private final ClientService clientService;

   @Autowired
   public ClientController(ClientService clientService) {
       this.clientService = clientService;
   }
}
Aclaremos las anotaciones: @RestController : le dice a Spring que esta clase es un controlador REST. Aquellos. esta clase implementará la lógica para procesar las solicitudes de los clientes @Autowired : le dice a Spring que se debe inyectar una dependencia en este lugar. Pasamos la interfaz al constructor ClientService. Marcamos la implementación de este servicio con una anotación @Serviceanteriormente, y ahora Spring podrá pasar una instancia de esta implementación al constructor del controlador. A continuación, implementaremos paso a paso cada método de controlador para procesar operaciones CRUD. Comencemos con la operación Crear. Para hacer esto, escribamos un método create:
@PostMapping(value = "/clients")
public ResponseEntity<?> create(@RequestBody Client client) {
   clientService.create(client);
   return new ResponseEntity<>(HttpStatus.CREATED);
}
Veamos este método: @PostMapping(value = "/clients")- aquí queremos decir que este método procesa solicitudes POST a la dirección /clients. El método devuelve ResponseEntity<?>. ResponseEntity- una clase especial para devolver respuestas. Al usarlo, luego podemos devolver el código de estado HTTP al cliente. El método toma un parámetro @RequestBody Client client, el valor de este parámetro se sustituye en el cuerpo de la solicitud. El resumen habla de esto @RequestBody. Dentro del cuerpo del método, llamamos al método create en el servicio creado previamente y le pasamos el controlador del cliente aceptado en los parámetros. Luego devolvemos el estado 201 Creado creando un nuevo objeto ResponseEntityy pasándole el valor de enumeración requerido HttpStatus. A continuación, implementamos la operación Read: Primero, implementamos la operación de obtener una lista de todos los clientes disponibles:
@GetMapping(value = "/clients")
public ResponseEntity<List<Client>> read() {
   final List<Client> clients = clientService.readAll();

   return clients != null &&  !clients.isEmpty()
           ? new ResponseEntity<>(clients, HttpStatus.OK)
           : new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
Comencemos el análisis: @GetMapping(value = "/clients")- todo es similar a la anotación @PostMapping, solo que ahora procesamos solicitudes GET. Esta vez regresamos ResponseEntity<List<Client>>, solo que esta vez, además del estado HTTP, también devolveremos el cuerpo de la respuesta, que será una lista de clientes. En los controladores Spring REST, todos los objetos POJO, así como las colecciones de objetos POJO que se devuelven como cuerpos de respuesta, se serializan automáticamente en JSON a menos que se especifique explícitamente lo contrario. Esto nos viene bastante bien. Dentro del método, utilizando nuestro servicio, obtenemos una lista de todos los clientes. A continuación, si la lista no es nula o está vacía, devolvemos ResponseEntityla lista de clientes y el estado HTTP 200 OK usando la clase. De lo contrario, simplemente devolvemos el estado HTTP 404 No encontrado. A continuación, implementaremos la capacidad de recibir un cliente por su identificación:
@GetMapping(value = "/clients/{id}")
public ResponseEntity<Client> read(@PathVariable(name = "id") int id) {
   final Client client = clientService.read(id);

   return client != null
           ? new ResponseEntity<>(client, HttpStatus.OK)
           : new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
Algo nuevo es que ahora tenemos una variable de ruta. Una variable que se define en un URI. value = "/clients/{id}". Lo indicamos entre llaves. Y en los parámetros del método lo aceptamos como intvariable usando la anotación @PathVariable(name = "id"). Este método aceptará solicitudes de uri del formulario /clients/{id}, donde en su lugar {id}puede haber cualquier valor numérico. Este valor se pasa posteriormente a una variable int id: el parámetro del método. En el cuerpo recibimos el objeto Clientusando nuestro servicio y lo aceptamos id. Y luego, por analogía con la lista, devolvemos el estado 200 OK y el objeto en sí Client, o simplemente el estado 404 No encontrado, si idno hay ningún cliente con esto en el sistema. Queda por implementar dos operaciones: Actualizar y Eliminar. Aquí está el código para estos métodos:
@PutMapping(value = "/clients/{id}")
public ResponseEntity<?> update(@PathVariable(name = "id") int id, @RequestBody Client client) {
   final boolean updated = clientService.update(client, id);

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

@DeleteMapping(value = "/clients/{id}")
public ResponseEntity<?> delete(@PathVariable(name = "id") int id) {
   final boolean deleted = clientService.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 nos saltaremos una descripción detallada. Lo único que vale la pena mencionar es que el método updateprocesa solicitudes PUT (anotación @PutMapping) y el método deleteprocesa solicitudes DELETE (anotación DeleteMapping). Aquí está el código completo del controlador:
@RestController
public class ClientController {

   private final ClientService clientService;

   @Autowired
   public ClientController(ClientService clientService) {
       this.clientService = clientService;
   }

   @PostMapping(value = "/clients")
   public ResponseEntity<?> create(@RequestBody Client client) {
       clientService.create(client);
       return new ResponseEntity<>(HttpStatus.CREATED);
   }

   @GetMapping(value = "/clients")
   public ResponseEntity<List<Client>> read() {
       final List<client> clients = clientService.readAll();

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

   @GetMapping(value = "/clients/{id}")
   public ResponseEntity<Client> read(@PathVariable(name = "id") int id) {
       final Client client = clientService.read(id);

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

   @PutMapping(value = "/clients/{id}")
   public ResponseEntity<?> update(@PathVariable(name = "id") int id, @RequestBody Client client) {
       final boolean updated = clientService.update(client, id);

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

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

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

Lanzamiento y prueba

Para ejecutar nuestra aplicación, simplemente ejecute el método mainen la clase RestExampleApplication. Y para probar los servicios web RESTful, debe descargar un nuevo software) El hecho es que las solicitudes GET son bastante fáciles de enviar desde un navegador normal, pero para POST, PUT y DELETE un navegador normal no es suficiente. No te preocupes: puedes usar Postman para enviar cualquier solicitud HTTP. Puedes descargarlo desde aquí . Después de descargar e instalar, comenzamos a probar nuestra aplicación. Para hacer esto, abra el programa y cree una nueva solicitud: Descripción general del DESCANSO.  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 Solicitar: Descripción general del DESCANSO.  Parte 3: Creación de un servicio RESTful con Spring Boot - 10A continuación, asígnele un nombre y guárdelo. Intentemos ahora enviar una solicitud POST al servidor y crear el primer cliente: Descripción general del DESCANSO.  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 la enviamos al servidor: Descripción general del DESCANSO.  Parte 3: Creación de un servicio RESTful en Spring Boot - 12

Resultados generales

Felicitaciones: hemos cubierto bastante el tema de REST. Todo el material resultó voluminoso, pero esperamos que te sea de utilidad:
  1. Aprendimos qué es DESCANSO.

  2. Nos familiarizamos con la historia de REST.

  3. Hablamos de las limitaciones y principios de este estilo arquitectónico:

    • llevar la arquitectura a un modelo cliente-servidor;
    • falta de condición;
    • almacenamiento en caché;
    • uniformidad de la interfaz;
    • capas;
    • código bajo demanda (restricción opcional).
  4. Examinamos las ventajas que ofrece REST.

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

  6. Echemos un vistazo más de cerca a las solicitudes y respuestas. Sus componentes fueron desmontados.

  7. Finalmente, pasamos a practicar y escribimos nuestra propia pequeña aplicación RESTful en Spring Boot. E incluso aprendimos a probarlo usando el programa Postman.

Uf. Resultó voluminoso, pero aún así hay algo que hacer como tarea.

Tarea

Pruebe lo siguiente:
  1. Siguiendo la descripción anterior, cree su propio proyecto Spring Boot e implemente la misma lógica que en la conferencia. Repite todo 1 en 1.
  2. Lánzalo. solicitud.
  3. Descargue y configure Postman (o cualquier otra herramienta para enviar solicitudes, incluso curl).
  4. Pruebe las solicitudes POST y GET de la misma manera que se describe en la conferencia.
  5. Pruebe las solicitudes PUT y DELETE usted mismo.
Parte 1: Qué es REST Parte 2: Comunicación entre cliente y servidor
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION