JavaRush /Java-Blog /Random-DE /Übersicht über REST. Teil 3: Erstellen eines RESTful-Dien...

Übersicht über REST. Teil 3: Erstellen eines RESTful-Dienstes in Spring Boot

Veröffentlicht in der Gruppe Random-DE
Dies ist der letzte Teil der REST-Analyse. In den vorherigen Teilen: Übersicht über REST.  Teil 3: Erstellen eines RESTful-Dienstes in Spring Boot – 1

Ein Projekt erstellen

In diesem Abschnitt erstellen wir eine kleine RESTful-Anwendung mit Spring Boot. Unsere Anwendung implementiert CRUD-Operationen (Erstellen, Lesen, Aktualisieren, Löschen) auf Clients aus dem Beispiel aus dem letzten Teil der Analyse. Erstellen wir zunächst eine neue Spring Boot-Anwendung über das Menü Datei -> Neu -> Projekt... Wählen Sie im sich öffnenden Fenster Spring Initializr aus und geben Sie Project SDK an: Übersicht über REST.  Teil 3: Erstellen eines RESTful-Dienstes in Spring Boot – 2Klicken Sie auf die Schaltfläche Weiter. Geben Sie im nächsten Fenster den Maven-Projekttyp an, geben Sie Gruppe und Artefakt an: Übersicht über REST.  Teil 3: Erstellen eines RESTful-Dienstes in Spring Boot – 3Klicken Sie auf die Schaltfläche Weiter. Im nächsten Fenster müssen wir die für das Projekt benötigten Spring Framework-Komponenten auswählen. Spring Web reicht uns: Übersicht über REST.  Teil 3: Erstellen eines RESTful-Dienstes in Spring Boot – 4Klicken Sie auf die Schaltfläche Weiter. Als nächstes müssen Sie nur noch den Namen des Projekts und seinen Speicherort im Dateisystem angeben: Übersicht über REST.  Teil 3: Erstellen eines RESTful-Dienstes in Spring Boot – 5Klicken Sie auf die Schaltfläche „Fertig stellen“. Das Projekt wurde erstellt, jetzt können wir seine Struktur sehen: Übersicht über REST.  Teil 3: Erstellen eines RESTful-Dienstes in Spring Boot – 6IDEA hat für uns den Maven-Build-System-Bereitstellungsdeskriptor - pom.xml und die Hauptanwendungsklasse generiert: RestExampleApplication. Hier ist ihr Code:
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>
RestExampleApplication:
@SpringBootApplication
public class RestExampleApplication {

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

}

REST-Funktionalität erstellen

Unsere Anwendung verwaltet Kunden. Als Erstes müssen wir also eine Kundenentität erstellen. Dies wird eine POJO-Klasse sein. Lassen Sie uns ein Paket modelinnerhalb eines Pakets erstellen com.javarush.lectures.rest_example. Lassen Sie uns eine Klasse innerhalb des Pakets modelerstellen 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;
   }
}
Der Dienst implementiert CRUD-Operationen auf dem Client. Der nächste Schritt besteht darin, einen Dienst zu erstellen, der diese Vorgänge implementiert. Im Paket com.javarush.lectures.rest_exampleerstellen wir ein Paket service, in dem wir eine Schnittstelle erstellen ClientService. Hier ist der Schnittstellencode mit Kommentaren:
public interface ClientService {

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

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

   /**
    * kehrt zurück клиента по его ID
    * @param id - ID клиента
    * @return - ein Objekt клиента с заданным 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);
}
Als nächstes müssen wir eine Implementierung dieser Schnittstelle erstellen. Jetzt fungiert es als Client-Repository Map<Integer, Client>. Der Kartenschlüssel ist die Kunden-ID und der Wert ist der Kunde selbst. Dies geschah, um das Beispiel nicht mit den Besonderheiten der Arbeit mit der Datenbank zu überladen. In Zukunft werden wir jedoch in der Lage sein, eine weitere Implementierung der Schnittstelle zu schreiben, in der es möglich sein wird, eine echte Datenbank anzubinden. Im Paket serviceerstellen wir eine Implementierung der Schnittstelle ClientService:
@Service
public class ClientServiceImpl implements ClientService {

   // Хранoderще клиентов
   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;
   }
}
Die Annotation @Serviceteilt Spring mit, dass es sich bei dieser Klasse um einen Dienst handelt. Dies ist ein spezieller Klassentyp, in dem einige Geschäftslogiken der Anwendung implementiert werden. Dank dieser Annotation stellt Spring uns anschließend mithilfe der Dependency-Injection eine Instanz dieser Klasse an den Stellen zur Verfügung, an denen sie benötigt wird. Jetzt ist es an der Zeit, den Controller zu erstellen. Eine spezielle Klasse, in der wir die Logik zur Verarbeitung von Client-Anfragen für Endpunkte (URIs) implementieren. Zur Verdeutlichung werden wir diese Klasse in Teilen erstellen. Erstellen wir zunächst die Klasse selbst und führen eine Abhängigkeit davon ein ClientService:
@RestController
public class ClientController {

   private final ClientService clientService;

   @Autowired
   public ClientController(ClientService clientService) {
       this.clientService = clientService;
   }
}
Lassen Sie uns die Anmerkungen klären: @RestController – teilt Spring mit, dass diese Klasse ein REST-Controller ist. Diese. Diese Klasse implementiert die Logik zur Verarbeitung von Client-Anfragen @Autowired – teilt Spring mit, dass an dieser Stelle eine Abhängigkeit eingefügt werden muss. Wir übergeben die Schnittstelle an den Konstruktor ClientService. Wir haben die Implementierung dieses Dienstes @Servicezuvor mit einer Anmerkung markiert, und jetzt kann Spring eine Instanz dieser Implementierung an den Controller-Konstruktor übergeben. Als nächstes implementieren wir Schritt für Schritt jede Controller-Methode, um CRUD-Operationen zu verarbeiten. Beginnen wir mit dem Erstellungsvorgang. Schreiben wir dazu eine Methode create:
@PostMapping(value = "/clients")
public ResponseEntity<?> create(@RequestBody Client client) {
   clientService.create(client);
   return new ResponseEntity<>(HttpStatus.CREATED);
}
Schauen wir uns diese Methode an: @PostMapping(value = "/clients")- Hier meinen wir, dass diese Methode POST-Anfragen an die /clients-Adresse verarbeitet. Die Methode gibt zurück ResponseEntity<?>. ResponseEntity- eine spezielle Klasse für die Rückgabe von Antworten. Damit können wir später den HTTP-Statuscode an den Client zurückgeben. Die Methode benötigt einen Parameter @RequestBody Client client. Der Wert dieses Parameters wird aus dem Anforderungshauptteil ersetzt. Die Zusammenfassung spricht darüber @RequestBody. Im Hauptteil der Methode rufen wir die Methode „create“ für den zuvor erstellten Dienst auf und übergeben sie an den in den Parametern akzeptierten Client-Controller. Dann geben wir den Status 201 Created zurück, indem wir ein neues Objekt erstellen ResponseEntityund ihm den erforderlichen Enum-Wert übergeben HttpStatus. Als nächstes implementieren wir die Operation Read: Zuerst implementieren wir die Operation zum Abrufen einer Liste aller verfügbaren Clients:
@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);
}
Beginnen wir mit der Analyse: @GetMapping(value = "/clients")- Alles ist ähnlich wie bei der Annotation @PostMapping, nur verarbeiten wir jetzt GET-Anfragen. Dieses Mal geben wir zurück ResponseEntity<List<Client>>, nur dieses Mal geben wir zusätzlich zum HTTP-Status auch den Antworttext zurück, bei dem es sich um eine Liste von Clients handelt. In Spring REST-Controllern werden alle POJO-Objekte sowie Sammlungen von POJO-Objekten, die als Antwortkörper zurückgegeben werden, automatisch in JSON serialisiert, sofern nicht ausdrücklich anders angegeben. Das passt ganz gut zu uns. Innerhalb der Methode erhalten wir mithilfe unseres Dienstes eine Liste aller Kunden. Wenn die Liste nicht null oder leer ist, geben wir als Nächstes ResponseEntitymithilfe der Klasse die Liste der Clients und den HTTP-Status 200 OK zurück. Andernfalls geben wir einfach den HTTP-Status 404 Not Found zurück. Als Nächstes implementieren wir die Möglichkeit, einen Kunden anhand seiner ID zu empfangen:
@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);
}
Neu ist, dass wir jetzt eine Pfadvariable haben. Eine Variable, die in einem URI definiert ist. value = "/clients/{id}". Wir haben es in geschweiften Klammern angegeben. Und in den Methodenparametern akzeptieren wir es intmithilfe der Annotation als Variable @PathVariable(name = "id"). Diese Methode akzeptiert Anfragen nach URIs der Form /clients/{id}, wobei stattdessen {id}ein beliebiger numerischer Wert angegeben werden kann. Dieser Wert wird anschließend an eine Variable übergeben int id– den Methodenparameter. Im Körper empfangen wir das Objekt Clientdurch unseren Dienst und nehmen es an id. Und dann geben wir analog zur Liste entweder den Status 200 OK und das Objekt selbst zurück Clientoder einfach den Status 404 Not Found, wenn idkein Client mit diesem Status im System vorhanden ist. Es müssen noch zwei Vorgänge implementiert werden – Aktualisieren und Löschen. Hier ist der Code für diese Methoden:
@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);
}
Da diese Methoden grundsätzlich nichts Neues enthalten, verzichten wir auf eine ausführliche Beschreibung. Erwähnenswert ist nur, dass die Methode updatePUT-Anfragen verarbeitet (Annotation @PutMapping) und die Methode deleteDELETE-Anfragen verarbeitet (Annotation DeleteMapping). Hier ist der vollständige Controller-Code:
@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);
   }
}
Im Ergebnis sieht die Struktur unseres Projekts so aus: Übersicht über REST.  Teil 3: Erstellen eines RESTful-Dienstes in Spring Boot – 7

Einführung und Test

Um unsere Anwendung auszuführen, führen Sie einfach die Methode mainin der Klasse aus RestExampleApplication. Und um RESTful-Webdienste zu testen, müssen Sie neue Software herunterladen.) Tatsache ist, dass GET-Anfragen ganz einfach von einem normalen Browser aus gesendet werden können, aber für POST, PUT und DELETE reicht ein normaler Browser nicht aus. Keine Sorge: Sie können Postman verwenden, um beliebige HTTP-Anfragen zu senden. Sie können es hier herunterladen . Nach dem Herunterladen und Installieren beginnen wir mit dem Testen unserer Anwendung. Öffnen Sie dazu das Programm und erstellen Sie eine neue Anfrage: Übersicht über REST.  Teil 3: Erstellen eines RESTful-Dienstes in Spring Boot – 9Klicken Sie oben links auf die Schaltfläche „Neu“. Wählen Sie als Nächstes „Anfrage“ aus: Übersicht über REST.  Teil 3: Erstellen eines RESTful-Dienstes mit Spring Boot – 10Geben Sie als Nächstes einen Namen ein und speichern Sie es. Versuchen wir nun, eine POST-Anfrage an den Server zu senden und den ersten Client zu erstellen: Übersicht über REST.  Teil 3: Erstellen eines RESTful-Dienstes in Spring Boot – 11Auf diese Weise erstellen wir mehrere Clients. Dann ändern wir den Anfragetyp in GET und senden ihn an den Server: Übersicht über REST.  Teil 3: Erstellen eines RESTful-Dienstes in Spring Boot – 12

Allgemeine Ergebnisse

Herzlichen Glückwunsch: Wir haben das Thema REST ziemlich ausführlich behandelt. Das gesamte Material erwies sich als umfangreich, aber wir hoffen, dass es für Sie nützlich sein wird:
  1. Wir haben gelernt, was REST ist.

  2. Wir haben die Geschichte von REST kennengelernt.

  3. Wir haben über die Grenzen und Prinzipien dieses Architekturstils gesprochen:

    • Überführung der Architektur in ein Client-Server-Modell;
    • mangelnde Kondition;
    • Caching;
    • Einheitlichkeit der Schnittstelle;
    • Lagen;
    • Code auf Anfrage (optionale Einschränkung).
  4. Wir haben die Vorteile untersucht, die REST bietet

  5. Wir haben im Detail untersucht, wie Server und Client über das HTTP-Protokoll miteinander interagieren.

  6. Schauen wir uns die Anfragen und Antworten genauer an. Ihre Bestandteile wurden zerlegt.

  7. Schließlich gingen wir zum Üben über und schrieben unsere eigene kleine RESTful-Anwendung in Spring Boot. Und wir haben sogar gelernt, wie man es mit dem Postman-Programm testet.

Puh. Es ist umfangreich geworden, aber es gibt trotzdem etwas zu tun als Hausaufgabe.

Hausaufgaben

Versuche Folgendes:
  1. Erstellen Sie gemäß der obigen Beschreibung Ihr eigenes Spring Boot-Projekt und implementieren Sie darin die gleiche Logik wie in der Vorlesung. Wiederholen Sie alles 1 in 1.
  2. Starten Sie es. Anwendung.
  3. Laden Sie Postman herunter und richten Sie es ein (oder ein anderes Tool zum Senden von Anfragen, sogar Curl).
  4. Testen Sie POST- und GET-Anfragen auf die gleiche Weise wie in der Vorlesung beschrieben.
  5. Testen Sie PUT- und DELETE-Anfragen selbst.
Teil 1: Was ist REST? Teil 2: Kommunikation zwischen Client und Server
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION