CodeGym /Java-blogg /Tilfeldig /Oversikt over REST. Del 3: Bygg en RESTful tjeneste på Sp...
John Squirrels
Nivå
San Francisco

Oversikt over REST. Del 3: Bygg en RESTful tjeneste på Spring Boot

Publisert i gruppen
Dette er den siste delen av vår oversikt over REST. I de foregående delene dekket vi: Oversikt over REST.  Del 3: Bygge en RESTful tjeneste på Spring Boot - 1

Opprette et prosjekt

I denne delen vil vi lage en liten RESTful-applikasjon ved å bruke Spring Boot. Vår applikasjon vil implementere CRUD-operasjoner (Create, Read, Update, Delete) på kundene fra eksemplet i forrige del av oversikten. For å starte, vil vi lage en ny Spring Boot-applikasjon via menyen: Fil -> Ny -> Prosjekt... I vinduet som åpnes, velg Spring Initializr og spesifiser Project SDK: Oversikt over REST.  Del 3: Bygge en RESTful tjeneste på Spring Boot - 2Klikk på "Neste"-knappen. I neste vindu, spesifiser "Maven Project" som prosjekttype, spesifiser "Gruppe" og "Artefakt": Oversikt over REST.  Del 3: Bygg en RESTful tjeneste på Spring Boot - 3Klikk på "Neste"-knappen. I det neste vinduet må vi velge Spring Framework-komponentene som er nødvendige for prosjektet. Spring Web vil være tilstrekkelig for oss: Oversikt over REST.  Del 3: Bygg en RESTful tjeneste på Spring Boot - 4Klikk på "Neste"-knappen. Nå gjenstår det bare å angi navnet på prosjektet og dets plassering i filsystemet: Oversikt over REST.  Del 3: Bygg en RESTful tjeneste på Spring Boot - 5Klikk på "Fullfør"-knappen. Prosjektet er opprettet, og nå kan vi se strukturen: Oversikt over REST.  Del 3: Bygg en RESTful tjeneste på Spring Boot - 6IDEA genererte en Maven deployment descriptor (pom.xml) og applikasjonens hovedklasse ( RestExampleApplication) for oss. Slik ser de ut:

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

}

Opprette REST-funksjonalitet

Vår applikasjon er et kundestyringssystem. Så det første vi må gjøre er å opprette en kundeenhet. Det vil være en POJO-klasse (vanlig gammelt Java-objekt). Lag en modelpakke inne i com.codegym.lessons.rest_examplepakken. Inne i modelpakken oppretter du 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-operasjoner på kunder. Det neste trinnet er å lage en tjeneste som skal implementere disse operasjonene. com.codegym.lessons.rest_exampleOpprett en pakke i pakken service. Og inni det, lag et CustomerServicegrensesnitt. Her er grensesnittkoden 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);
}
Deretter må vi implementere dette grensesnittet. Nå Map<Integer, Customer>vil en lagre våre kunder. Kartets nøkler vil være kunde-IDene, og verdiene vil være kundene selv. Dette gjøres for ikke å overbelaste dette eksemplet med detaljene ved å jobbe med en ekte database. Imidlertid vil vi i fremtiden kunne skrive en annen implementering av grensesnittet, som vil gjøre det mulig å koble til en ekte database. I servicepakken oppretter du en implementering av CustomerServicegrensesnittet:

@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;
   }
}
Merknaden @Serviceforteller våren at denne timen er en tjeneste. Dette er en spesiell type klasse som implementerer noe forretningsapplikasjonslogikk. Deretter, takket være denne merknaden, vil Spring bruke avhengighetsinjeksjon for å gi oss en forekomst av denne klassen på alle stedene der den er nødvendig. Nå er det på tide å lage en kontroller. Dette er en spesiell klasse hvor vi skal implementere logikken for å behandle klientforespørsler sendt til endepunkter (URI). For å gjøre alt dette klarere, vil vi opprette denne klassen trinnvis. Opprett først selve klassen og legg til en avhengighet av CustomerService:

@RestController
public class CustomerController {

   private final CustomerService customerService;

   @Autowired
   public CustomerController(CustomerService customerService) {
       this.customerService = customerService;
   }
}
La oss forklare merknadene: @RestController forteller Spring at denne klassen er en REST-kontroller. Med andre ord implementerer denne klassen logikken for å behandle klientforespørsler. @Autowired forteller Spring at en avhengighet må legges til her. Vi sender CustomerServicegrensesnittet til konstruktøren. Tidligere markerte vi implementeringen av denne tjenesten med merknaden @Service, og nå vil Spring kunne sende en forekomst av denne implementeringen til kontrollerens konstruktør. Deretter vil vi implementere hver kontrollmetode for håndtering av CRUD-operasjoner. La oss starte med opprette-operasjonen. For å gjøre dette skriver vi en createmetode:

@PostMapping(value = "/customers")
public ResponseEntity<?> create(@RequestBody Customer customer) {
   customerService.create(customer);
   return new ResponseEntity<>(HttpStatus.CREATED);
}
La oss analysere denne metoden: @PostMapping(value = "/customers")mener at denne metoden behandler POST-forespørsler sendt til adressen "/kunder". Metoden returnerer en ResponseEntity<?>. A ResponseEntityer en spesiell klasse for å returnere svar. Senere vil vi bruke den til å returnere en HTTP-statuskode til klienten. Metoden har en @RequestBody Customer customerparameter. Verdien av denne parameteren kommer fra forespørselsteksten. Merknaden @RequestBodyindikerer dette. Inne i metoden kaller vi create()metoden på den tidligere opprettede tjenesten og sender den til kundekontrolleren mottok i parameterne. Deretter returnerer vi "201 Opprettet"-statusen ved å lage et nytt ResponseEntityobjekt og sende det tilsvarende HttpStatusenum-feltet til det. Deretter implementerer vireadoperasjon: Først implementerer vi operasjonen for å få en liste over alle tilgjengelige 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);
}
La oss dykke inn: @GetMapping(value = "/customers")— alt her ligner på @PostMappingkommentaren, men nå behandler vi GET-forespørsler. Denne gangen returnerer vi en ResponseEntity<List<Customer>>, og i tillegg til en HTTP-status vil vi også returnere en svartekst, som vil være listen over kunder. I Springs REST-kontrollere er alt POJO-objekter og samlinger av POJO-objekter, som returneres som responslegemer og automatisk serialisert til JSON, med mindre annet er spesifisert. Dette passer oss perfekt. Inne i metoden bruker vi vår tjeneste for å få en liste over alle kunder. Deretter, hvis listen ikke er null og ikke tom, bruker viResponseEntityklasse for å returnere listen over kunder og HTTP-statuskoden "200 OK". Ellers returnerer vi ganske enkelt HTTP-statuskoden "404 Not Found". Nå skal vi implementere muligheten til å få en kunde ved å bruke IDen sin:

@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 banevariabelen. Variabelen er definert i URI: value = "/customers/{id}". Vi indikerer det i krøllete seler. Og vi mottar det som en intmetodeparameter ved å bruke @PathVariable(name = "id")merknaden. Denne metoden aksepterer forespørsler sendt til URIer i skjemaet /customers/{id}, der {id}representerer enhver numerisk verdi. Denne verdien sendes deretter via int idvariabelen til metodeparameteren. I kroppen får vi gjenstanden Customerved hjelp av vår tjeneste og den mottatte id. Og så, analogt med listen, returnerer vi enten "200 OK"-statusen og Customerselve objektet, eller ganske enkelt "404 Not Found"-statusen hvis systemet ikke har noen kunde med det id. Vi må fortsatt implementere to operasjoner: oppdatering og sletting. Her er koden for disse metodene:

@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);
}
Det er ikke noe vesentlig nytt i disse metodene, så vi hopper over den detaljerte beskrivelsen. Det eneste som er verdt å nevne er at update()metoden håndterer PUT-forespørsler ( @PutMappingmerknad), og delete()metoden håndterer DELETE-forespørsler ( DeleteMappingmerknad). Her er hele koden for kontrolleren:

@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 til prosjektet vårt som følger: Oversikt over REST.  Del 3: Bygge en RESTful tjeneste på Spring Boot - 7

Lansering og testing

For å starte applikasjonen vår, bare kjør main()metoden i RestExampleApplicationklassen. Men for å teste RESTful webtjenester, må vi laste ned ekstra programvare. Faktum er at GET-forespørsler er ganske enkle å sende fra en vanlig nettleser, men en vanlig nettleser kan ikke sende POST, PUT og DELETE-forespørsler. Ikke bekymre deg: du kan bruke et program kalt Postman til å sende HTTP-forespørsler. Du kan laste den ned her . Etter å ha lastet ned og installert Postman, begynner vi å teste applikasjonen vår. For å gjøre dette, åpne programmet og opprett en ny forespørsel: Oversikt over REST.  Del 3: Bygg en RESTful tjeneste på Spring Boot - 9Klikk på "Ny"-knappen i øvre venstre hjørne. Deretter velger du "Request": Oversikt over REST.  Del 3: Bygg en RESTful tjeneste på Spring Boot - 10Deretter gir du den et navn og lagrer den. La oss nå prøve å sende en POST-forespørsel til serveren og opprette den første kunden: Oversikt over REST.  Del 3: Bygge en RESTful tjeneste på Spring Boot - 11Vi skaper flere kunder på denne måten. Deretter endrer vi forespørselstypen til GET og sender forespørselen til serveren: Oversikt over REST.  Del 3: Bygg en RESTful tjeneste på Spring Boot - 12

Sammendrag

Gratulerer! Vi har dekket REST tilstrekkelig. Det var et stort volum av materiale, men forhåpentligvis var det nyttig for deg:
  1. Vi lærte hva REST er.

  2. Vi lærte om hvordan REST ble til.

  3. Vi snakket om begrensningene og prinsippene bak denne arkitektoniske stilen:

    • klient-server-arkitektur
    • statsløs
    • caching
    • enhetlig grensesnitt
    • lag
    • kode på forespørsel (valgfritt)
  4. Vi utforsket fordelene gitt av REST

  5. Vi undersøkte i detalj hvordan serveren og klienten samhandler med hverandre via HTTP-protokollen.

  6. Vi har sett nærmere på forespørsler og svar. Vi dissekerte deres bestanddeler.

  7. Til slutt fikk vi litt praktisk erfaring ved å skrive vår egen lille RESTful-applikasjon med Spring Boot. Og vi lærte til og med å teste det med Postman.

Puh. Det var mye, men det er fortsatt noe for deg å gjøre som lekser.

Hjemmelekser

Prøv følgende:
  1. Følg beskrivelsen ovenfor, lag ditt eget Spring Boot-prosjekt og implementer den samme logikken som i leksjonen. Gjenta alt nøyaktig.
  2. Start applikasjonen.
  3. Last ned og konfigurer Postman (eller et annet verktøy for å sende forespørsler, for eksempel curl).
  4. Test POST- og GET-forespørsler på samme måte som beskrevet i leksjonen.
  5. Test PUT- og DELETE-forespørsler selv.
Kommentarer
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION