CodeGym /Java blog /Tilfældig /Oversigt over REST. Del 3: Opbygning af en RESTful servic...
John Squirrels
Niveau
San Francisco

Oversigt over REST. Del 3: Opbygning af en RESTful service på Spring Boot

Udgivet i gruppen
Dette er den sidste del af vores oversigt over REST. I de foregående dele dækkede vi: Oversigt over REST.  Del 3: Opbygning af en RESTful service på Spring Boot - 1

Oprettelse af et projekt

I dette afsnit vil vi oprette en lille RESTful-applikation ved hjælp af Spring Boot. Vores applikation vil implementere CRUD-operationer (Create, Read, Update, Delete) på kunderne fra eksemplet i den foregående del af oversigten. For at starte opretter vi et nyt Spring Boot-program via menuen: Filer -> Nyt -> Projekt... I det vindue, der åbnes, skal du vælge Spring Initializr og angive Project SDK: Oversigt over REST.  Del 3: Opbygning af en RESTful service på Spring Boot - 2Klik på knappen "Næste". I det næste vindue skal du angive "Maven Project" som projekttype, angive "Gruppe" og "Artefakt": Oversigt over REST.  Del 3: Opbygning af en RESTful service på Spring Boot - 3Klik på knappen "Næste". I det næste vindue skal vi vælge de Spring Framework-komponenter, der er nødvendige for projektet. Spring Web vil være tilstrækkeligt for os: Oversigt over REST.  Del 3: Opbygning af en RESTful service på Spring Boot - 4Klik på knappen "Næste". Nu er der kun tilbage at angive navnet på projektet og dets placering i filsystemet: Oversigt over REST.  Del 3: Opbygning af en RESTful service på Spring Boot - 5Klik på knappen "Udfør". Projektet er oprettet, og nu kan vi se dets struktur: Oversigt over REST.  Del 3: Opbygning af en RESTful service på Spring Boot - 6IDEA genererede en Maven deployment descriptor (pom.xml) og applikationens hovedklasse ( RestExampleApplication) til os. Sådan ser de ud:

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);
   }

}

Oprettelse af REST-funktionalitet

Vores applikation er et kundestyringssystem. Så den første ting, vi skal gøre, er at oprette en kundeentitet. Det vil være en POJO-klasse (almindeligt gammelt Java-objekt). Opret en modelpakke inde i com.codegym.lessons.rest_examplepakken. Inde i modelpakken skal du oprette 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;
   }
}
Tjenesten vil implementere CRUD operationer på kunder. Det næste trin er at skabe en service, der vil implementere disse operationer. com.codegym.lessons.rest_exampleOpret en pakke i servicepakken. Og inden i det, opret en CustomerServicegrænseflade. Her er grænsefladekoden med kommentarer:

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);
}
Dernæst skal vi implementere denne grænseflade. Nu Map<Integer, Customer>vil en gemme vores kunder. Kortets nøgler vil være kunde-id'erne, og værdierne vil være kunderne selv. Dette gøres for ikke at overbelaste dette eksempel med detaljerne ved at arbejde med en rigtig database. Men i fremtiden vil vi være i stand til at skrive en anden implementering af grænsefladen, som gør det muligt at oprette forbindelse til en rigtig database. I servicepakken skal du oprette en implementering af grænsefladen CustomerService:

@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;
   }
}
Annoteringen @Servicefortæller foråret, at denne klasse er en tjeneste. Dette er en speciel type klasse, der implementerer noget forretningsapplikationslogik. Efterfølgende, takket være denne annotation, vil Spring bruge afhængighedsinjektion til at give os en forekomst af denne klasse alle de steder, hvor den er nødvendig. Nu er det tid til at oprette en controller. Dette er en speciel klasse, hvor vi implementerer logikken til behandling af klientanmodninger sendt til slutpunkter (URI'er). For at gøre alt dette klarere, vil vi oprette denne klasse trinvist. Først skal du oprette selve klassen og tilføje en afhængighed af CustomerService:

@RestController
public class CustomerController {

   private final CustomerService customerService;

   @Autowired
   public CustomerController(CustomerService customerService) {
       this.customerService = customerService;
   }
}
Lad os forklare annotationerne: @RestController fortæller Spring, at denne klasse er en REST-controller. Med andre ord implementerer denne klasse logikken til behandling af klientanmodninger. @Autowired fortæller Spring, at der skal tilføjes en afhængighed her. Vi videregiver CustomerServicegrænsefladen til konstruktøren. Tidligere markerede vi implementeringen af ​​denne tjeneste med annoteringen @Service, og nu vil Spring være i stand til at videregive en instans af denne implementering til controllerens konstruktør. Dernæst vil vi implementere hver controller-metode til håndtering af CRUD-operationer. Lad os starte med oprettelsesoperationen. For at gøre dette skriver vi en createmetode:

@PostMapping(value = "/customers")
public ResponseEntity<?> create(@RequestBody Customer customer) {
   customerService.create(customer);
   return new ResponseEntity<>(HttpStatus.CREATED);
}
Lad os analysere denne metode: @PostMapping(value = "/customers")betyde, at denne metode behandler POST-anmodninger sendt til adressen "/kunder". Metoden returnerer en ResponseEntity<?>. A ResponseEntityer en særlig klasse til returnering af svar. Senere vil vi bruge den til at returnere en HTTP-statuskode til klienten. Metoden har en @RequestBody Customer customerparameter. Værdien af ​​denne parameter kommer fra anmodningsteksten. Anmærkningen @RequestBodyangiver dette. Inde i metodens krop kalder vi metoden create()på den tidligere oprettede service og videregiver den, som kundecontrolleren modtog i parametrene. Derefter returnerer vi statussen "201 Oprettet" ved at oprette et nyt ResponseEntityobjekt og sende det tilsvarende HttpStatusenum-felt til det. Dernæst implementerer vireadoperation: Først implementerer vi operationen for at få en liste over alle tilgængelige kunder:

@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);
}
Lad os dykke ned i: @GetMapping(value = "/customers")— alt her ligner @PostMappingannoteringen, men nu behandler vi GET-anmodninger. Denne gang returnerer vi en ResponseEntity<List<Customer>>, og udover en HTTP-status returnerer vi også et svarlegeme, som vil være listen over kunder. I Springs REST-controllere er alt POJO-objekter og samlinger af POJO-objekter, som returneres som svarlegemer og automatisk serialiseres til JSON, medmindre andet er angivet. Dette passer os perfekt. Inde i metoden bruger vi vores service til at få en liste over alle kunder. Dernæst, hvis listen ikke er null og ikke tom, så bruger viResponseEntityklasse for at returnere listen over kunder og HTTP-statuskoden "200 OK". Ellers returnerer vi blot HTTP-statuskoden "404 Not Found". Nu vil vi implementere muligheden for at få en kunde ved at bruge dens ID:

@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);
}
En ny ting her er stivariablen. Variablen er defineret i URI'en: value = "/customers/{id}". Vi angiver det med krøllede seler. Og vi modtager det som en intmetodeparameter ved hjælp af @PathVariable(name = "id")annoteringen. Denne metode accepterer anmodninger sendt til URI'er i formen /customers/{id}, hvor {id}repræsenterer enhver numerisk værdi. Denne værdi overføres efterfølgende via int idvariablen til metodeparameteren. I kroppen får vi genstanden Customerved hjælp af vores service og den modtagne id. Og så, analogt med listen, returnerer vi enten "200 OK"-statussen og Customerselve objektet, eller blot "404 Not Found"-statussen, hvis systemet ikke har nogen kunde med det id. Vi mangler stadig at implementere to operationer: Opdater og slet. Her er koden til disse metoder:

@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);
}
Der er intet væsentligt nyt i disse metoder, så vi springer den detaljerede beskrivelse over. Det eneste der er værd at nævne er, at update()metoden håndterer PUT-anmodninger ( @PutMappingannotation), og delete()metoden håndterer DELETE-anmodninger ( DeleteMappingannotation). Her er den fulde kode til controlleren:

@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);
   }
}
Som et resultat er strukturen af ​​vores projekt som følger: Oversigt over REST.  Del 3: Opbygning af en RESTful service på Spring Boot - 7

Lancering og test

For at starte vores applikation skal du bare køre main()metoden i RestExampleApplicationklassen. Men for at teste RESTful webtjenester, er vi nødt til at downloade yderligere software. Faktum er, at GET-anmodninger er ret enkle at sende fra en almindelig browser, men en almindelig browser kan ikke sende POST-, PUT- og DELETE-anmodninger. Bare rolig: du kan bruge et program kaldet Postman til at sende alle HTTP-anmodninger. Du kan downloade den her . Efter at have downloadet og installeret Postman, begynder vi at teste vores applikation. For at gøre dette skal du åbne programmet og oprette en ny anmodning: Oversigt over REST.  Del 3: Opbygning af en RESTful service på Spring Boot - 9Klik på knappen "Ny" i øverste venstre hjørne. Vælg derefter "Request": Oversigt over REST.  Del 3: Opbygning af en RESTful service på Spring Boot - 10Giv det derefter et navn og gem det. Lad os nu prøve at sende en POST-anmodning til serveren og oprette den første kunde: Oversigt over REST.  Del 3: Opbygning af en RESTful service på Spring Boot - 11Vi skaber flere kunder på denne måde. Så ændrer vi anmodningstypen til GET og sender anmodningen til serveren: Oversigt over REST.  Del 3: Opbygning af en RESTful service på Spring Boot - 12

Resumé

Tillykke! Vi har dækket REST tilstrækkeligt. Der var en stor mængde materiale, men forhåbentlig var det nyttigt for dig:
  1. Vi lærte, hvad REST er.

  2. Vi lærte om, hvordan REST opstod.

  3. Vi talte om begrænsningerne og principperne bag denne arkitektoniske stil:

    • klient-server arkitektur
    • statsløs
    • caching
    • ensartet interface
    • lag
    • kode efter behov (valgfrit)
  4. Vi undersøgte fordelene ved REST

  5. Vi undersøgte i detaljer, hvordan serveren og klienten interagerer med hinanden via HTTP-protokollen.

  6. Vi har set nærmere på anmodninger og svar. Vi dissekere deres bestanddele.

  7. Endelig fik vi lidt praktisk erfaring ved at skrive vores egen lille RESTful-applikation ved hjælp af Spring Boot. Og vi lærte endda at teste det ved hjælp af Postman.

Pyha. Det var meget, men der er stadig noget for dig at lave som hjemmearbejde.

Lektier

Prøv følgende:
  1. Følg beskrivelsen ovenfor, opret dit eget Spring Boot-projekt og implementer den samme logik som i lektionen. Gentag alt nøjagtigt.
  2. Start applikationen.
  3. Download og konfigurer Postman (eller ethvert andet værktøj til at sende anmodninger, for eksempel curl).
  4. Test POST- og GET-anmodninger på samme måde som beskrevet i lektionen.
  5. Test selv PUT- og DELETE-anmodninger.
Kommentarer
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION