CodeGym /Java blogg /Slumpmässig /Översikt över REST. Del 3: Bygga en RESTful tjänst på Spr...
John Squirrels
Nivå
San Francisco

Översikt över REST. Del 3: Bygga en RESTful tjänst på Spring Boot

Publicerad i gruppen
Detta är den sista delen av vår översikt över REST. I de tidigare delarna täckte vi: Översikt över REST.  Del 3: Bygga en RESTful tjänst på Spring Boot - 1

Skapa ett projekt

I det här avsnittet kommer vi att skapa en liten RESTful-applikation med Spring Boot. Vår applikation kommer att implementera CRUD-operationer (Create, Read, Update, Delete) på kunderna från exemplet i föregående del av översikten. Till att börja med skapar vi en ny Spring Boot-applikation via menyn: Arkiv -> Nytt -> Projekt... I fönstret som öppnas, välj Spring Initializr och ange Project SDK: Översikt över REST.  Del 3: Bygga en RESTful tjänst på Spring Boot - 2Klicka på knappen "Nästa". I nästa fönster, ange "Maven Project" som projekttyp, ange "Group" och "Artifact": Översikt över REST.  Del 3: Bygga en RESTful tjänst på Spring Boot - 3Klicka på "Next"-knappen. I nästa fönster måste vi välja de Spring Framework-komponenter som är nödvändiga för projektet. Spring Web kommer att räcka för oss: Översikt över REST.  Del 3: Bygga en RESTful tjänst på Spring Boot - 4Klicka på knappen "Nästa". Nu återstår bara att ange projektets namn och dess plats i filsystemet: Översikt över REST.  Del 3: Bygga en RESTful tjänst på Spring Boot - 5Klicka på knappen "Slutför". Projektet är skapat och nu kan vi se dess struktur: Översikt över REST.  Del 3: Bygga en RESTful tjänst på Spring Boot - 6IDEA genererade en Maven-deployment descriptor (pom.xml) och applikationens huvudklass ( ) RestExampleApplicationåt oss. Så här 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);
   }

}

Skapa REST-funktionalitet

Vår applikation är ett kundhanteringssystem. Så det första vi behöver göra är att skapa en kundenhet. Det kommer att vara en POJO-klass (vanligt gammalt Java-objekt). Skapa ett modelpaket inuti com.codegym.lessons.rest_examplepaketet. Inuti modelpaketet skapar 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;
   }
}
Tjänsten kommer att implementera CRUD-verksamhet på kunder. Nästa steg är att skapa en tjänst som kommer att implementera dessa operationer. com.codegym.lessons.rest_exampleSkapa ett servicepaket i paketet. Och inuti det, skapa ett CustomerServicegränssnitt. Här är gränssnittskoden 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);
}
Därefter måste vi implementera detta gränssnitt. Nu Map<Integer, Customer>kommer en att lagra våra kunder. Kartans nycklar kommer att vara kund-id:n, och värdena kommer att vara kunderna själva. Detta görs för att inte överbelasta detta exempel med detaljerna för att arbeta med en riktig databas. Men i framtiden kommer vi att kunna skriva ytterligare en implementering av gränssnittet, vilket gör det möjligt att ansluta till en riktig databas. serviceSkapa en implementering av gränssnittet i paketet 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;
   }
}
Anteckningen @Serviceberättar för våren att denna klass är en tjänst. Detta är en speciell typ av klass som implementerar viss affärsapplikationslogik. Därefter, tack vare denna annotering, kommer Spring att använda beroendeinjektion för att förse oss med en instans av den här klassen på alla platser där den behövs. Nu är det dags att skapa en kontroller. Detta är en specialklass där vi kommer att implementera logiken för att behandla klientförfrågningar som skickas till slutpunkter (URI). För att göra allt detta tydligare kommer vi att skapa den här klassen stegvis. Skapa först själva klassen och lägg till ett beroende av CustomerService:

@RestController
public class CustomerController {

   private final CustomerService customerService;

   @Autowired
   public CustomerController(CustomerService customerService) {
       this.customerService = customerService;
   }
}
Låt oss förklara kommentarerna: @RestController säger till Spring att den här klassen är en REST-kontroller. Med andra ord implementerar den här klassen logiken för att behandla klientförfrågningar. @Autowired säger till Spring att ett beroende måste läggas till här. Vi skickar gränssnittet CustomerServicetill konstruktören. Tidigare markerade vi implementeringen av den här tjänsten med anteckningen, @Serviceoch nu kommer Spring att kunna skicka en instans av denna implementering till kontrollenhetens konstruktör. Därefter kommer vi att implementera varje kontrollmetod för att hantera CRUD-operationer. Låt oss börja med skapa operationen. För att göra detta skriver vi en createmetod:

@PostMapping(value = "/customers")
public ResponseEntity<?> create(@RequestBody Customer customer) {
   customerService.create(customer);
   return new ResponseEntity<>(HttpStatus.CREATED);
}
Låt oss analysera denna metod: @PostMapping(value = "/customers")menar att den här metoden behandlar POST-förfrågningar som skickas till adressen "/kunder". Metoden returnerar en ResponseEntity<?>. A ResponseEntityär en specialklass för att returnera svar. Senare kommer vi att använda den för att returnera en HTTP-statuskod till klienten. Metoden har en @RequestBody Customer customerparameter. Värdet på denna parameter kommer från förfrågan. Anteckningen @RequestBodyindikerar detta. Inuti metoden anropar vi create()metoden på den tidigare skapade tjänsten och skickar den till kundkontrollanten som tagits emot i parametrarna. Sedan returnerar vi statusen "201 Skapad" genom att skapa ett nytt ResponseEntityobjekt och skicka motsvarande HttpStatusuppräkningsfält till det. Därefter kommer vi att implementerareadoperation: Först implementerar vi operationen för att få en lista över alla tillgängliga 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);
}
Låt oss dyka in: @GetMapping(value = "/customers")— allt här liknar anteckningen @PostMapping, men nu behandlar vi GET-förfrågningar. Den här gången returnerar vi en ResponseEntity<List<Customer>>, och förutom en HTTP-status kommer vi även att returnera en svarskropp, som kommer att vara listan över kunder. I Springs REST-kontroller är allt POJO-objekt och samlingar av POJO-objekt, som returneras som svarskroppar och serialiseras automatiskt till JSON, om inget annat anges. Detta passar oss perfekt. Inuti metoden använder vi vår tjänst för att få en lista över alla kunder. Därefter, om listan inte är null och inte tom, använder viResponseEntityklass för att returnera listan över kunder och HTTP-statuskoden "200 OK". Annars returnerar vi helt enkelt HTTP-statuskoden "404 Not Found". Nu kommer vi att implementera möjligheten att få en kund med hjälp av dess 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 sak här är sökvägsvariabeln. Variabeln definieras i URI:n: value = "/customers/{id}". Vi anger det i lockiga hängslen. Och vi får den som en intmetodparameter med hjälp av @PathVariable(name = "id")anteckningen. Den här metoden accepterar förfrågningar som skickas till URI:er i formen , /customers/{id}där {id}representerar vilket numeriskt värde som helst. Detta värde överförs sedan via int idvariabeln till metodparametern. I kroppen får vi föremålet Customermed hjälp av vår tjänst och det mottagna id. Och sedan, i analogi med listan, returnerar vi antingen statusen "200 OK" och Customersjälva objektet, eller helt enkelt statusen "404 Not Found" om systemet inte har någon kund med det id. Vi behöver fortfarande implementera två operationer: uppdatera och ta bort. Här är koden för dessa 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);
}
Det finns inget väsentligt nytt i dessa metoder, så vi hoppar över den detaljerade beskrivningen. Det enda som är värt att nämna är att update()metoden hanterar PUT-förfrågningar ( @PutMappingannotation), och delete()metoden hanterar DELETE-förfrågningar ( DeleteMappingannotation). Här är hela koden för kontrollenheten:

@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 ett resultat är strukturen för vårt projekt som följer: Översikt över REST.  Del 3: Bygga en RESTful tjänst på Spring Boot - 7

Lansering och testning

För att starta vår applikation, kör bara main()metoden i RestExampleApplicationklassen. Men för att testa RESTful webbtjänster måste vi ladda ner ytterligare programvara. Faktum är att GET-förfrågningar är ganska enkla att skicka från en vanlig webbläsare, men en vanlig webbläsare kan inte skicka POST-, PUT- och DELETE-förfrågningar. Oroa dig inte: du kan använda ett program som heter Postman för att skicka alla HTTP-förfrågningar. Du kan ladda ner den här . Efter att ha laddat ner och installerat Postman börjar vi testa vår applikation. För att göra detta, öppna programmet och skapa en ny begäran: Översikt över REST.  Del 3: Bygga en RESTful tjänst på Spring Boot - 9Klicka på knappen "Ny" i det övre vänstra hörnet. Välj sedan "Begäran": Översikt över REST.  Del 3: Bygga en RESTful tjänst på Spring Boot - 10Ge det sedan ett namn och spara det. Låt oss nu försöka skicka en POST-förfrågan till servern och skapa den första kunden: Översikt över REST.  Del 3: Bygga en RESTful tjänst på Spring Boot - 11Vi skapar flera kunder på detta sätt. Sedan ändrar vi förfrågningstypen till GET och skickar förfrågan till servern: Översikt över REST.  Del 3: Bygga en RESTful tjänst på Spring Boot - 12

Sammanfattning

Grattis! Vi har täckt REST tillräckligt. Det fanns en stor mängd material, men förhoppningsvis var det användbart för dig:
  1. Vi lärde oss vad REST är.

  2. Vi lärde oss om hur REST uppstod.

  3. Vi pratade om begränsningarna och principerna bakom denna arkitektoniska stil:

    • klient-server-arkitektur
    • statslös
    • cachelagring
    • enhetligt gränssnitt
    • skikten
    • kod på begäran (valfritt)
  4. Vi undersökte fördelarna med REST

  5. Vi undersökte i detalj hur servern och klienten interagerar med varandra via HTTP-protokollet.

  6. Vi tittade närmare på förfrågningar och svar. Vi dissekerade deras beståndsdelar.

  7. Slutligen fick vi lite praktisk erfarenhet genom att skriva vår egen lilla RESTful-applikation med Spring Boot. Och vi lärde oss till och med hur man testar det med Postman.

Puh. Det var mycket, men det finns fortfarande något för dig att göra som läxa.

Läxa

Prova följande:
  1. Följ beskrivningen ovan, skapa ditt eget Spring Boot-projekt och implementera samma logik som i lektionen. Upprepa allt exakt.
  2. Starta applikationen.
  3. Ladda ner och konfigurera Postman (eller något annat verktyg för att skicka förfrågningar, till exempel curl).
  4. Testa POST- och GET-förfrågningar på samma sätt som beskrivs i lektionen.
  5. Testa PUT- och DELETE-förfrågningar själv.
Kommentarer
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION