CodeGym /Java-Blog /Random-DE /Übersicht über REST. Teil 3: Aufbau eines RESTful-Dienste...
John Squirrels
Level 41
San Francisco

Übersicht über REST. Teil 3: Aufbau eines RESTful-Dienstes auf Spring Boot

Veröffentlicht in der Gruppe Random-DE
Dies ist der letzte Teil unseres Überblicks über REST. In den vorherigen Teilen haben wir Folgendes behandelt: Übersicht über REST.  Teil 3: Aufbau eines RESTful-Dienstes auf Spring Boot – 1

Ein Projekt erstellen

In diesem Abschnitt erstellen wir eine kleine RESTful-Anwendung mit Spring Boot. Unsere Anwendung implementiert CRUD-Vorgänge (Erstellen, Lesen, Aktualisieren, Löschen) für die Kunden aus dem Beispiel im vorherigen Teil der Übersicht. Zunächst erstellen wir eine neue Spring Boot-Anwendung über das Menü: Datei -> Neu -> Projekt... Wählen Sie im sich öffnenden Fenster Spring Initializr aus und geben Sie das Projekt-SDK an: Übersicht über REST.  Teil 3: Aufbau eines RESTful-Dienstes auf Spring Boot – 2Klicken Sie auf die Schaltfläche „Weiter“. Im nächsten Fenster geben Sie als Projekttyp „Maven Project“ an, legen „Group“ und „Artifact“ fest: Übersicht über REST.  Teil 3: Aufbau eines RESTful-Dienstes auf Spring Boot – 3Klicken Sie auf die Schaltfläche „Next“. Im nächsten Fenster müssen wir die für das Projekt notwendigen Spring Framework-Komponenten auswählen. Spring Web wird uns ausreichen: Übersicht über REST.  Teil 3: Aufbau eines RESTful-Dienstes auf Spring Boot – 4Klicken Sie auf die Schaltfläche „Weiter“. Jetzt müssen Sie nur noch den Namen des Projekts und seinen Speicherort im Dateisystem angeben: Übersicht über REST.  Teil 3: Aufbau eines RESTful-Dienstes auf Spring Boot – 5Klicken Sie auf die Schaltfläche „Fertig stellen“. Das Projekt ist erstellt und jetzt können wir seine Struktur sehen: IDEA hat für uns Übersicht über REST.  Teil 3: Aufbau eines RESTful-Dienstes auf Spring Boot – 6einen Maven-Bereitstellungsdeskriptor (pom.xml) und die Hauptklasse ( ) der Anwendung generiert . RestExampleApplicationSo sehen sie aus:

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>
RestExampleApplication:

@SpringBootApplication
public class RestExampleApplication {

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

}

REST-Funktionalität erstellen

Bei unserer Anwendung handelt es sich um ein Kundenmanagementsystem. Als Erstes müssen wir also eine Kundenentität erstellen. Es wird eine POJO-Klasse (einfaches altes Java-Objekt) sein. Erstellen Sie ein modelPaket innerhalb des com.codegym.lessons.rest_examplePakets. modelErstellen Sie im Paket Folgendes 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;
   }
}
Der Dienst implementiert CRUD-Operationen für Kunden. Der nächste Schritt besteht darin, einen Dienst zu erstellen, der diese Vorgänge implementiert. Erstellen Sie im com.codegym.lessons.rest_examplePaket ein servicePaket. Und darin eine CustomerServiceSchnittstelle erstellen. Hier ist der Schnittstellencode mit Kommentaren:

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);
}
Als nächstes müssen wir diese Schnittstelle implementieren. Jetzt Map<Integer, Customer>werden unsere Kunden ein Lager haben. Die Schlüssel der Karte sind die Kunden-IDs und die Werte sind die Kunden selbst. Dies geschieht, um dieses Beispiel nicht mit den Besonderheiten der Arbeit mit einer echten Datenbank zu überladen. In Zukunft werden wir jedoch in der Lage sein, eine weitere Implementierung der Schnittstelle zu schreiben, die es ermöglicht, eine Verbindung zu einer echten Datenbank herzustellen. Erstellen Sie im servicePaket eine Implementierung der CustomerServiceSchnittstelle:

@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;
   }
}
Die @ServiceAnnotation teilt Spring mit, dass es sich bei dieser Klasse um einen Dienst handelt. Dies ist ein spezieller Klassentyp, der eine gewisse Geschäftsanwendungslogik implementiert. Anschließend wird Spring dank dieser Annotation die Abhängigkeitsinjektion verwenden, um uns an allen Stellen, an denen sie benötigt wird, eine Instanz dieser Klasse bereitzustellen. Jetzt ist es an der Zeit, einen Controller zu erstellen. Dies ist eine spezielle Klasse, in der wir die Logik zur Verarbeitung von Client-Anfragen implementieren, die an Endpunkte (URIs) gesendet werden. Um dies alles klarer zu machen, werden wir diese Klasse inkrementell erstellen. Erstellen Sie zunächst die Klasse selbst und fügen Sie eine Abhängigkeit hinzu von CustomerService:

@RestController
public class CustomerController {

   private final CustomerService customerService;

   @Autowired
   public CustomerController(CustomerService customerService) {
       this.customerService = customerService;
   }
}
Lassen Sie uns die Anmerkungen erklären: @RestController teilt Spring mit, dass diese Klasse ein REST-Controller ist. Mit anderen Worten: Diese Klasse implementiert die Logik zur Verarbeitung von Client-Anfragen. @Autowired teilt Spring mit, dass hier eine Abhängigkeit hinzugefügt werden muss. Wir übergeben die CustomerServiceSchnittstelle an den Konstruktor. Zuvor haben wir die Implementierung dieses Dienstes mit der @ServiceAnnotation markiert, und jetzt kann Spring eine Instanz dieser Implementierung an den Konstruktor des Controllers übergeben. Als Nächstes implementieren wir jede Controller-Methode zur Handhabung von CRUD-Operationen. Beginnen wir mit dem Erstellungsvorgang. Dazu schreiben wir eine createMethode:

@PostMapping(value = "/customers")
public ResponseEntity<?> create(@RequestBody Customer customer) {
   customerService.create(customer);
   return new ResponseEntity<>(HttpStatus.CREATED);
}
Lassen Sie uns diese Methode analysieren: @PostMapping(value = "/customers")Dies bedeutet, dass diese Methode POST-Anfragen verarbeitet, die an die Adresse „/customers“ gesendet werden. Die Methode gibt eine zurück ResponseEntity<?>. A ResponseEntityist eine spezielle Klasse für die Rückgabe von Antworten. Später werden wir es verwenden, um einen HTTP-Statuscode an den Client zurückzugeben. Die Methode hat einen @RequestBody Customer customerParameter. Der Wert dieses Parameters stammt aus dem Anfragetext. Die @RequestBodyAnmerkung weist darauf hin. Innerhalb des Methodenkörpers rufen wir die create()Methode für den zuvor erstellten Dienst auf und übergeben sie an den Kundencontroller, den wir in den Parametern erhalten haben. Anschließend geben wir den Status „201 Created“ zurück, indem wir ein neues ResponseEntityObjekt erstellen und HttpStatusihm das entsprechende Enum-Feld übergeben. Als nächstes implementieren wir dasreadOperation: Zuerst implementieren wir die Operation, um eine Liste aller verfügbaren Kunden zu erhalten:

@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);
}
Lassen Sie uns eintauchen: @GetMapping(value = "/customers")– Hier ähnelt alles der @PostMappingAnnotation, aber jetzt verarbeiten wir GET-Anfragen. Dieses Mal geben wir ein zurück ResponseEntity<List<Customer>>und zusätzlich zum HTTP-Status geben wir auch einen Antworttext zurück, bei dem es sich um die Liste der Kunden handelt. In den REST-Controllern von Spring handelt es sich ausschließlich um POJO-Objekte und Sammlungen von POJO-Objekten, die als Antwortkörper zurückgegeben und automatisch in JSON serialisiert werden, sofern nicht anders angegeben. Das passt perfekt zu uns. Innerhalb der Methode nutzen wir unseren Service, um eine Liste aller Kunden zu erhalten. Wenn die Liste nicht null und nicht leer ist, verwenden wir als Nächstes dieResponseEntityKlasse, um die Liste der Kunden und den HTTP-Statuscode „200 OK“ zurückzugeben. Andernfalls geben wir einfach den HTTP-Statuscode „404 Not Found“ zurück. Jetzt werden wir die Möglichkeit implementieren, einen Kunden mithilfe seiner ID zu erreichen:

@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);
}
Neu ist hier die Pfadvariable. Die Variable ist im URI definiert: value = "/customers/{id}". Wir geben es in geschweiften Klammern an. Und wir erhalten es als intMethodenparameter mithilfe der @PathVariable(name = "id")Annotation. Diese Methode akzeptiert Anfragen, die an URIs im Format gesendet werden /customers/{id}, wobei {id}ein beliebiger numerischer Wert steht. Dieser Wert wird anschließend über die int idVariable an den Methodenparameter übergeben. Im Körper erhalten wir das CustomerObjekt mithilfe unseres Dienstes und der empfangenen id. Und dann geben wir analog zur Liste entweder den Status „200 OK“ und das CustomerObjekt selbst zurück oder einfach den Status „404 Not Found“, wenn das System damit keinen Kunden hat id. Wir müssen noch zwei Vorgänge implementieren: Aktualisieren und Löschen. Hier ist der Code für diese Methoden:

@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);
}
Da diese Methoden grundsätzlich nichts Neues enthalten, überspringen wir die ausführliche Beschreibung. Erwähnenswert ist nur, dass die update()Methode PUT-Anfragen ( @PutMappingAnnotation) und die delete()Methode DELETE-Anfragen ( DeleteMappingAnnotation) verarbeitet. Hier ist der vollständige Code für den Controller:

@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);
   }
}
Daraus ergibt sich folgender Aufbau unseres Projektes: Übersicht über REST.  Teil 3: Aufbau eines RESTful-Dienstes auf Spring Boot – 7

Starten und testen

Um unsere Anwendung zu starten, führen Sie einfach die main()Methode in der RestExampleApplicationKlasse aus. Aber um RESTful-Webdienste zu testen, müssen wir zusätzliche Software herunterladen. Tatsache ist, dass GET-Anfragen ganz einfach von einem normalen Browser aus gesendet werden können, ein gewöhnlicher Browser jedoch keine POST-, PUT- und DELETE-Anfragen senden kann. Keine Sorge: Sie können ein Programm namens Postman verwenden, um beliebige HTTP-Anfragen zu senden. Sie können es hier herunterladen . Nachdem wir Postman heruntergeladen und installiert haben, beginnen wir mit dem Testen unserer Anwendung. Öffnen Sie dazu das Programm und erstellen Sie eine neue Anfrage: Übersicht über REST.  Teil 3: Aufbau eines RESTful-Dienstes auf Spring Boot – 9Klicken Sie oben links auf die Schaltfläche „Neu“. Als nächstes wählen Sie „Anfrage“: Übersicht über REST.  Teil 3: Aufbau eines RESTful-Dienstes auf Spring Boot – 10Geben Sie als Nächstes einen Namen und speichern Sie es. Versuchen wir nun, eine POST-Anfrage an den Server zu senden und den ersten Kunden zu erstellen: Übersicht über REST.  Teil 3: Aufbau eines RESTful-Dienstes auf Spring Boot – 11Auf diese Weise schaffen wir mehrere Kunden. Dann ändern wir den Anfragetyp in GET und senden die Anfrage an den Server: Übersicht über REST.  Teil 3: Aufbau eines RESTful-Dienstes auf Spring Boot – 12

Zusammenfassung

Glückwunsch! Wir haben REST ausreichend abgedeckt. Es gab eine große Menge an Material, aber hoffentlich war es für Sie nützlich:
  1. Wir haben gelernt, was REST ist.

  2. Wir haben erfahren, wie REST entstanden ist.

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

    • Client-Server-Architektur
    • staatenlos
    • Caching
    • einheitliche Schnittstelle
    • Lagen
    • Code auf Anfrage (optional)
  4. Wir haben die Vorteile von REST untersucht

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

  6. Wir haben uns die Anfragen und Antworten genauer angeschaut. Wir haben ihre Bestandteile zerlegt.

  7. Schließlich haben wir praktische Erfahrungen gesammelt, indem wir unsere eigene kleine RESTful-Anwendung mit Spring Boot geschrieben haben. Und wir haben sogar gelernt, wie man es mit Postman testet.

Puh. Das war viel, aber es gibt noch etwas als Hausaufgabe für dich.

Hausaufgaben

Versuche Folgendes:
  1. Erstellen Sie gemäß der obigen Beschreibung Ihr eigenes Spring Boot-Projekt und implementieren Sie dieselbe Logik wie in der Lektion. Wiederholen Sie alles genau.
  2. Anwendung starten.
  3. Laden Sie Postman herunter und konfigurieren Sie es (oder ein anderes Tool zum Senden von Anfragen, z. B. Curl).
  4. Testen Sie POST- und GET-Anfragen auf die gleiche Weise wie in der Lektion beschrieben.
  5. Testen Sie PUT- und DELETE-Anfragen selbst.
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION