JavaRush /Java Blog /Random-IT /Panoramica di REST. Parte 3: creazione di un servizio RES...

Panoramica di REST. Parte 3: creazione di un servizio RESTful in Spring Boot

Pubblicato nel gruppo Random-IT
Questa è la parte finale dell'analisi REST. Nelle parti precedenti: Panoramica di REST.  Parte 3: creazione di un servizio RESTful in Spring Boot - 1

Creazione di un progetto

In questa sezione creeremo una piccola applicazione RESTful utilizzando Spring Boot. La nostra applicazione implementerà le operazioni CRUD (Crea, Leggi, Aggiorna, Elimina) sui client dell'esempio dell'ultima parte dell'analisi. Per prima cosa creiamo una nuova applicazione Spring Boot tramite il menu File -> Nuovo -> Progetto... Nella finestra che si apre, selezioniamo Spring Inizializr e specifichiamo Project SDK: Panoramica di REST.  Parte 3: creazione di un servizio RESTful in Spring Boot - 2clicca sul pulsante Avanti. Nella finestra successiva, specifica il tipo di progetto Maven, specifica Gruppo e Artifatto: Panoramica di REST.  Parte 3: creazione di un servizio RESTful in Spring Boot - 3fai clic sul pulsante Avanti. Nella finestra successiva, dobbiamo selezionare i componenti Spring Framework necessari per il progetto. A noi basterà Spring Web: Panoramica di REST.  Parte 3: creazione di un servizio RESTful in Spring Boot - 4fare clic sul pulsante Avanti. Successivamente non resta che specificare il nome del progetto e la sua posizione nel file system: Panoramica di REST.  Parte 3: creazione di un servizio RESTful in Spring Boot - 5fare clic sul pulsante Fine. Il progetto è stato creato, ora possiamo vedere la sua struttura: Panoramica di REST.  Parte 3: creazione di un servizio RESTful in Spring Boot - 6IDEA ha generato per noi il descrittore di distribuzione del sistema di build Maven - pom.xml e la classe dell'applicazione principale: RestExampleApplication. Ecco il loro codice:
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>
RiposoEsempioApplicazione:
@SpringBootApplication
public class RestExampleApplication {

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

}

Creazione della funzionalità REST

La nostra applicazione gestisce i clienti. Quindi la prima cosa che dobbiamo fare è creare un'entità cliente. Questa sarà una lezione POJO. Creiamo un pacchetto modelall'interno di un pacchetto com.javarush.lectures.rest_example. modelCreiamo una classe all'interno del pacchetto 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;
   }
}
Il servizio implementerà le operazioni CRUD sul client. Il prossimo passo è creare un servizio che implementerà queste operazioni. Nel pacchetto com.javarush.lectures.rest_examplecreeremo un pacchetto service, all'interno del quale creeremo un'interfaccia ClientService. Ecco il codice dell'interfaccia con i commenti:
public interface ClientService {

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

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

   /**
    * returns клиента по его ID
    * @param id - ID клиента
    * @return - an object клиента с заданным 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);
}
Successivamente dobbiamo creare un'implementazione di questa interfaccia. Ora fungerà da repository client Map<Integer, Client>. La chiave della carta sarà l'ID del cliente e il valore sarà il cliente stesso. Ciò è stato fatto per non sovraccaricare l'esempio con le specifiche del lavoro con il database. Tuttavia, in futuro potremo scrivere un'altra implementazione dell'interfaccia in cui sarà possibile collegare un vero e proprio database. Nel pacchetto servicecreeremo un'implementazione dell'interfaccia ClientService:
@Service
public class ClientServiceImpl implements ClientService {

   // Хранorще клиентов
   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;
   }
}
L'annotazione @Serviceindica a Spring che questa classe è un servizio. Questo è un tipo speciale di classe in cui viene implementata una parte della logica aziendale dell'applicazione. Successivamente, grazie a questa annotazione, Spring ci fornirà un'istanza di questa classe nei luoghi in cui è necessaria utilizzando la Dependency Injection. Ora è il momento di creare il controller. Una classe speciale in cui implementiamo la logica per l'elaborazione delle richieste del client per gli endpoint (URI). Per renderlo più chiaro, creeremo questa classe in parti. Innanzitutto, creiamo la classe stessa e introduciamo una dipendenza su di essa ClientService:
@RestController
public class ClientController {

   private final ClientService clientService;

   @Autowired
   public ClientController(ClientService clientService) {
       this.clientService = clientService;
   }
}
Chiariamo le annotazioni: @RestController - dice a Spring che questa classe è un controller REST. Quelli. questa classe implementerà la logica per l'elaborazione delle richieste del client @Autowired - dice a Spring che è necessario inserire una dipendenza in questo posto. Passiamo l'interfaccia al costruttore ClientService. In precedenza abbiamo contrassegnato l'implementazione di questo servizio con un'annotazione @Servicee ora Spring sarà in grado di passare un'istanza di questa implementazione al costruttore del controller. Successivamente, implementeremo passo dopo passo ciascun metodo del controller per elaborare le operazioni CRUD. Iniziamo con l'operazione Crea. Per fare ciò, scriviamo un metodo create:
@PostMapping(value = "/clients")
public ResponseEntity<?> create(@RequestBody Client client) {
   clientService.create(client);
   return new ResponseEntity<>(HttpStatus.CREATED);
}
Diamo un'occhiata a questo metodo: @PostMapping(value = "/clients")- qui intendiamo che questo metodo elabora le richieste POST all'indirizzo /clients.Il metodo restituisce ResponseEntity<?>. ResponseEntity- una classe speciale per restituire le risposte. Usandolo, possiamo successivamente restituire il codice di stato HTTP al client. Il metodo accetta un parametro @RequestBody Client client, il valore di questo parametro viene sostituito dal corpo della richiesta. L'abstract parla di questo @RequestBody. All'interno del corpo del metodo chiamiamo il metodo create sul servizio precedentemente creato e gli passiamo il client controller accettato nei parametri. Quindi restituiamo lo stato 201 Created creando un nuovo oggetto ResponseEntitye passandogli il valore enum richiesto HttpStatus. Successivamente, implementiamo l'operazione Read: Innanzitutto, implementiamo l'operazione per ottenere un elenco di tutti i client disponibili:
@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);
}
Iniziamo l'analisi: @GetMapping(value = "/clients")- tutto è simile all'annotazione @PostMapping, solo che ora elaboriamo le richieste GET. Questa volta restituiamo ResponseEntity<List<Client>>, solo che questa volta, oltre allo stato HTTP, restituiremo anche il corpo della risposta, che sarà un elenco di client. Nei controller Spring REST, tutti gli oggetti POJO, così come le raccolte di oggetti POJO restituiti come corpi di risposta, vengono serializzati automaticamente su JSON se non diversamente specificato esplicitamente. Siamo abbastanza contenti di questo. All'interno del metodo, utilizzando il nostro servizio, otteniamo un elenco di tutti i clienti. Successivamente, se l'elenco non è nullo o vuoto, restituiamo ResponseEntityl'elenco dei client e lo stato HTTP 200 OK utilizzando la classe. Altrimenti restituiamo semplicemente lo stato HTTP 404 Not Found. Successivamente, implementeremo la possibilità di ricevere un cliente tramite il suo ID:
@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);
}
Qualcosa di nuovo è che ora abbiamo una variabile di percorso. Una variabile definita in un URI. value = "/clients/{id}". Lo abbiamo indicato tra parentesi graffe. E nei parametri del metodo lo accettiamo come intvariabile utilizzando l'annotazione @PathVariable(name = "id"). Questo metodo accetterà richieste di uri nel formato /clients/{id}, dove invece {id}può essere presente qualsiasi valore numerico. Questo valore viene successivamente passato a una variabile int id, il parametro del metodo. Nel corpo riceviamo l'oggetto Clientutilizzando il nostro servizio e lo accettiamo id. E poi, per analogia con l'elenco, restituiamo lo stato 200 OK e l'oggetto stesso Client, o semplicemente lo stato 404 Not Found, se idnel sistema non è presente alcun client con questo. Resta da implementare due operazioni: Aggiorna ed Elimina. Ecco il codice per questi metodi:
@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);
}
Non c'è nulla di essenzialmente nuovo in questi metodi, quindi salteremo una descrizione dettagliata. L'unica cosa degna di nota è che il metodo updateelabora le richieste PUT (annotation @PutMapping) e il metodo deleteelabora le richieste DELETE (annotation DeleteMapping). Ecco il codice completo del controller:
@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);
   }
}
Di conseguenza, la struttura del nostro progetto è simile alla seguente: Panoramica di REST.  Parte 3: creazione di un servizio RESTful in Spring Boot - 7

Lancio e test

Per eseguire la nostra applicazione, basta eseguire il metodo mainnella classe RestExampleApplication. E per testare i servizi web RESTful, è necessario scaricare nuovo software) Il fatto è che le richieste GET sono abbastanza facili da inviare da un normale browser, ma per POST, PUT e DELETE un normale browser non è sufficiente. Non preoccuparti: puoi utilizzare Postman per inviare eventuali richieste HTTP. Puoi scaricarlo da qui . Dopo il download e l'installazione, iniziamo a testare la nostra applicazione. Per fare ciò, apri il programma e crea una nuova richiesta: Panoramica di REST.  Parte 3: creazione di un servizio RESTful in Spring Boot - 9fai clic sul pulsante Nuovo nell'angolo in alto a sinistra. Successivamente, seleziona Richiedi: Panoramica di REST.  Parte 3: creazione di un servizio RESTful in Spring Boot - 10quindi assegnagli un nome e salvalo. Proviamo ora a inviare una richiesta POST al server e creare il primo client: Panoramica di REST.  Parte 3: creazione di un servizio RESTful in Spring Boot - 11Creiamo diversi client in questo modo. Quindi modifichiamo il tipo di richiesta in GET e lo inviamo al server: Panoramica di REST.  Parte 3: creazione di un servizio RESTful in Spring Boot - 12

Risultati generali

Congratulazioni: abbiamo trattato abbastanza l'argomento REST. Tutto il materiale si è rivelato voluminoso, ma speriamo che ti sia utile:
  1. Abbiamo imparato cos'è REST.

  2. Abbiamo conosciuto la storia di REST.

  3. Abbiamo parlato dei limiti e dei principi di questo stile architettonico:

    • portare l'architettura ad un modello client-server;
    • mancanza di condizione;
    • memorizzazione nella cache;
    • uniformità dell'interfaccia;
    • strati;
    • codice su richiesta (restrizione opzionale).
  4. Abbiamo esaminato i vantaggi offerti da REST

  5. Abbiamo esaminato in dettaglio come il server e il client interagiscono tra loro utilizzando il protocollo HTTP.

  6. Vediamo più da vicino le richieste e le risposte. I loro componenti sono stati smontati.

  7. Infine, siamo passati alla pratica e abbiamo scritto la nostra piccola applicazione RESTful in Spring Boot. E abbiamo anche imparato a testarlo utilizzando il programma Postman.

Uff. Si è rivelato voluminoso, ma c'è comunque qualcosa da fare come compiti a casa.

Compiti a casa

Prova quanto segue:
  1. Seguendo la descrizione sopra, crea il tuo progetto Spring Boot e implementa in esso la stessa logica della lezione. Ripeti tutto 1 in 1.
  2. Lanciatelo. applicazione.
  3. Scarica e configura Postman (o qualsiasi altro strumento per l'invio di richieste, anche curl).
  4. Testare le richieste POST e GET nello stesso modo descritto nella lezione.
  5. Prova tu stesso le richieste PUT e DELETE.
Parte 1: Cos'è REST Parte 2: Comunicazione tra client e server
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION