CodeGym /Java Blog /Willekeurig /Overzicht van REST. Deel 3: Een RESTful-service bouwen op...
John Squirrels
Niveau 41
San Francisco

Overzicht van REST. Deel 3: Een RESTful-service bouwen op Spring Boot

Gepubliceerd in de groep Willekeurig
Dit is het laatste deel van ons overzicht van REST. In de vorige delen hebben we het gehad over: Overzicht van REST.  Deel 3: Een RESTful-service bouwen op Spring Boot - 1

Een project maken

In deze sectie zullen we een kleine RESTful-applicatie maken met behulp van Spring Boot. Onze applicatie zal CRUD-bewerkingen (Create, Read, Update, Delete) implementeren op de klanten uit het voorbeeld in het vorige deel van het overzicht. Om te beginnen maken we een nieuwe Spring Boot-toepassing via het menu: Bestand -> Nieuw -> Project... Selecteer in het geopende venster Spring Initializr en specificeer de Project SDK: Overzicht van REST.  Deel 3: Een RESTful-service bouwen op Spring Boot - 2Klik op de knop "Volgende". Geef in het volgende venster "Maven Project" op als het projecttype, specificeer de "Groep" en "Artefact": Overzicht van REST.  Deel 3: Een RESTful-service bouwen op Spring Boot - 3Klik op de knop "Volgende". In het volgende venster moeten we de Spring Framework-componenten selecteren die nodig zijn voor het project. Voor ons is Spring Web voldoende: Overzicht van REST.  Deel 3: Een RESTful-service bouwen op Spring Boot - 4Klik op de knop "Volgende". Nu hoeft u alleen nog de naam van het project en de locatie ervan in het bestandssysteem aan te geven: Overzicht van REST.  Deel 3: Een RESTful-service bouwen op Spring Boot - 5Klik op de knop "Voltooien". Het project is gemaakt en nu kunnen we de structuur ervan zien: Overzicht van REST.  Deel 3: Een RESTful-service bouwen op Spring Boot - 6IDEA heeft een Maven-implementatiedescriptor (pom.xml) en de hoofdklasse van de toepassing ( RestExampleApplication) voor ons gegenereerd. Zo zien ze eruit:

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

@SpringBootApplication
public class RestExampleApplication {

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

}

REST-functionaliteit maken

Onze applicatie is een klantbeheersysteem. Het eerste dat we dus moeten doen, is een klantentiteit maken. Het wordt een POJO-klasse (gewoon oud Java-object). Maak een modelpakket binnen het com.codegym.lessons.rest_examplepakket. Maak in het modelpakket het volgende aan 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;
   }
}
De service zal CRUD-bewerkingen op klanten implementeren. De volgende stap is het maken van een service die deze bewerkingen zal implementeren. Maak in het com.codegym.lessons.rest_examplepakket een servicepakket aan. En maak daarbinnen een CustomerServiceinterface. Hier is de interfacecode met commentaar:

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);
}
Vervolgens moeten we deze interface implementeren. Nu Map<Integer, Customer>zal een winkel onze klanten. De sleutels van de kaart zijn de klant-ID's en de waarden zijn de klanten zelf. Dit is gedaan om dit voorbeeld niet te overladen met de details van het werken met een echte database. In de toekomst zullen we echter een andere implementatie van de interface kunnen schrijven, die het mogelijk zal maken om verbinding te maken met een echte database. serviceMaak in het pakket een implementatie van de CustomerServiceinterface:

@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;
   }
}
De @Serviceannotatie vertelt de lente dat deze les een service is. Dit is een speciaal type klasse dat bepaalde logica van bedrijfstoepassingen implementeert. Vervolgens zal Spring, dankzij deze annotatie, afhankelijkheidsinjectie gebruiken om ons een instantie van deze klasse te geven op alle plaatsen waar deze nodig is. Nu is het tijd om een ​​controller te maken. Dit is een speciale klasse waarin we de logica implementeren voor het verwerken van klantverzoeken die naar eindpunten (URI's) worden verzonden. Om dit allemaal duidelijker te maken, zullen we deze klasse stapsgewijs maken. Maak eerst de klasse zelf en voeg een afhankelijkheid toe van CustomerService:

@RestController
public class CustomerController {

   private final CustomerService customerService;

   @Autowired
   public CustomerController(CustomerService customerService) {
       this.customerService = customerService;
   }
}
Laten we de annotaties uitleggen: @RestController vertelt Spring dat deze klasse een REST-controller is. Met andere woorden, deze klasse implementeert de logica voor het verwerken van klantverzoeken. @Autowired vertelt Spring dat hier een afhankelijkheid moet worden toegevoegd. We geven de CustomerServiceinterface door aan de constructor. Eerder hebben we de implementatie van deze service gemarkeerd met de @Serviceannotatie, en nu kan Spring een exemplaar van deze implementatie doorgeven aan de constructor van de controller. Vervolgens zullen we elke controllermethode implementeren voor het afhandelen van CRUD-bewerkingen. Laten we beginnen met de create-bewerking. Om dit te doen, schrijven we een createmethode:

@PostMapping(value = "/customers")
public ResponseEntity<?> create(@RequestBody Customer customer) {
   customerService.create(customer);
   return new ResponseEntity<>(HttpStatus.CREATED);
}
Laten we deze methode analyseren: @PostMapping(value = "/customers")bedoel dat deze methode POST-verzoeken verwerkt die naar het adres "/customers" zijn verzonden. De methode retourneert een ResponseEntity<?>. A ResponseEntityis een speciale klasse voor het retourneren van antwoorden. Later zullen we het gebruiken om een ​​HTTP-statuscode terug te sturen naar de client. De methode heeft een @RequestBody Customer customerparameter. De waarde van deze parameter is afkomstig van de aanvraaginstantie. De @RequestBodyannotatie geeft dit aan. Binnen de body van de methode roepen we de create()methode aan op de eerder gemaakte service en geven deze door aan de klantcontroller die is ontvangen in de parameters. Vervolgens geven we de status "201 Gemaakt" terug door een nieuw ResponseEntityobject te maken en het overeenkomstige HttpStatusopsommingsveld eraan door te geven. Vervolgens implementeren we dereadoperatie: Eerst zullen we de operatie implementeren om een ​​lijst van alle beschikbare klanten te krijgen:

@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);
}
Laten we eens kijken: @GetMapping(value = "/customers")— alles is hier vergelijkbaar met de @PostMappingannotatie, maar nu verwerken we GET-verzoeken. Deze keer retourneren we een ResponseEntity<List<Customer>>, en naast een HTTP-status retourneren we ook een antwoordtekst, die de lijst met klanten zal zijn. In de REST-controllers van Spring zijn alles POJO-objecten en verzamelingen van POJO-objecten, die worden geretourneerd als antwoordlichamen en automatisch worden geserialiseerd in JSON, tenzij anders aangegeven. Dit past perfect bij ons. Binnen de methode gebruiken we onze service om een ​​lijst van alle klanten te krijgen. Als de lijst vervolgens niet null en niet leeg is, gebruiken we deResponseEntityclass om de lijst met klanten en de HTTP-statuscode "200 OK" te retourneren. Anders retourneren we gewoon de HTTP-statuscode "404 Not Found". Nu gaan we de mogelijkheid implementeren om een ​​klant zijn ID te laten gebruiken:

@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);
}
Een nieuw ding hier is de padvariabele. De variabele wordt gedefinieerd in de URI: value = "/customers/{id}". We geven het tussen accolades aan. En we ontvangen het als een intmethodeparameter met behulp van de @PathVariable(name = "id")annotatie. Deze methode accepteert verzoeken die naar URI's worden verzonden in de vorm /customers/{id}, waarbij {id}staat voor een numerieke waarde. Deze waarde wordt vervolgens via de int idvariabele doorgegeven aan de methodeparameter. In het lichaam krijgen we het Customerobject met behulp van onze service en het ontvangen id. En dan, naar analogie met de lijst, geven we ofwel de status "200 OK" en het Customerobject zelf terug, of gewoon de status "404 Niet gevonden" als het systeem daar geen klant mee heeft id. We moeten nog twee bewerkingen uitvoeren: bijwerken en verwijderen. Hier is de code voor deze 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);
}
Er is niets wezenlijk nieuws aan deze methoden, dus we zullen de gedetailleerde beschrijving overslaan. Het enige dat het vermelden waard is, is dat de update()methode PUT-verzoeken ( annotatie) afhandelt @PutMapping, en de delete()methode DELETE-verzoeken ( DeleteMappingannotatie). Hier is de volledige code voor de 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);
   }
}
De opbouw van ons project ziet er dan ook als volgt uit: Overzicht van REST.  Deel 3: Een RESTful-service bouwen op Spring Boot - 7

Lanceren en testen

Om onze applicatie te starten, voert u gewoon de main()methode in de RestExampleApplicationklas uit. Maar om RESTful-webservices te testen, moeten we aanvullende software downloaden. Feit is dat GET-verzoeken vrij eenvoudig te verzenden zijn vanuit een gewone browser, maar een gewone browser kan geen POST-, PUT- en DELETE-verzoeken verzenden. Maak je geen zorgen: je kunt een programma genaamd Postman gebruiken om HTTP-verzoeken te verzenden. Je kunt het hier downloaden . Na het downloaden en installeren van Postman beginnen we met het testen van onze applicatie. Open hiervoor het programma en maak een nieuwe aanvraag aan: Overzicht van REST.  Deel 3: Een RESTful-service bouwen op Spring Boot - 9Klik op de knop "Nieuw" in de linkerbovenhoek. Selecteer vervolgens "Verzoek": Overzicht van REST.  Deel 3: Een RESTful-service bouwen op Spring Boot - 10Geef het vervolgens een naam en sla het op. Laten we nu proberen een POST-verzoek naar de server te sturen en de eerste klant aan te maken: Overzicht van REST.  Deel 3: Een RESTful-service bouwen op Spring Boot - 11Zo creëren we meerdere klanten. Vervolgens wijzigen we het verzoektype in GET en sturen we het verzoek naar de server: Overzicht van REST.  Deel 3: Een RESTful-service bouwen op Spring Boot - 12

Samenvatting

Gefeliciteerd! We hebben REST voldoende afgedekt. Er was een grote hoeveelheid materiaal, maar hopelijk was het nuttig voor u:
  1. We hebben geleerd wat REST is.

  2. We leerden hoe REST is ontstaan.

  3. We spraken over de beperkingen van en principes achter deze bouwstijl:

    • client-server-architectuur
    • staatloos
    • cachen
    • uniforme interface
    • lagen
    • code op aanvraag (optioneel)
  4. We hebben de voordelen van REST onderzocht

  5. We hebben in detail onderzocht hoe de server en client met elkaar communiceren via het HTTP-protocol.

  6. We hebben de verzoeken en reacties onder de loep genomen. We hebben hun samenstellende delen ontleed.

  7. Ten slotte hebben we wat praktische ervaring opgedaan door onze eigen kleine RESTful-applicatie te schrijven met behulp van Spring Boot. En we hebben zelfs geleerd hoe we het kunnen testen met Postman.

Opluchting. Dat was veel, maar er is nog steeds iets dat je als huiswerk kunt doen.

Huiswerk

Probeer het volgende:
  1. Maak volgens de bovenstaande beschrijving uw eigen Spring Boot-project en implementeer dezelfde logica als in de les. Herhaal alles precies.
  2. Start de applicatie.
  3. Download en configureer Postman (of een andere tool voor het verzenden van verzoeken, bijvoorbeeld curl).
  4. Test POST- en GET-verzoeken op dezelfde manier als beschreven in de les.
  5. Test zelf PUT- en DELETE-verzoeken.
Opmerkingen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION