CodeGym /Java Blog /Random /Pangkalahatang-ideya ng REST. Bahagi 3: Pagbuo ng isang R...
John Squirrels
Antas
San Francisco

Pangkalahatang-ideya ng REST. Bahagi 3: Pagbuo ng isang RESTful na serbisyo sa Spring Boot

Nai-publish sa grupo
Ito ang huling bahagi ng aming pangkalahatang-ideya ng REST. Sa mga nakaraang bahagi, tinakpan namin: Pangkalahatang-ideya ng REST.  Bahagi 3: Pagbuo ng isang RESTful na serbisyo sa Spring Boot - 1

Paggawa ng proyekto

Sa seksyong ito, gagawa kami ng isang maliit na RESTful application gamit ang Spring Boot. Ipapatupad ng aming application ang mga operasyon ng CRUD (Gumawa, Magbasa, Mag-update, Magtanggal) sa mga customer mula sa halimbawa sa nakaraang bahagi ng pangkalahatang-ideya. Upang magsimula, gagawa kami ng bagong Spring Boot application sa pamamagitan ng menu: File -> New -> Project... Sa bubukas na window, piliin ang Spring Initializr at tukuyin ang Project SDK: Pangkalahatang-ideya ng REST.  Bahagi 3: Pagbuo ng isang RESTful na serbisyo sa Spring Boot - 2I-click ang "Next" button. Sa susunod na window, tukuyin ang "Maven Project" bilang uri ng proyekto, tukuyin ang "Group" at "Artifact": Pangkalahatang-ideya ng REST.  Bahagi 3: Pagbuo ng isang RESTful na serbisyo sa Spring Boot - 3I-click ang "Next" button. Sa susunod na window, kailangan nating piliin ang mga bahagi ng Spring Framework na kinakailangan para sa proyekto. Ang Spring Web ay magiging sapat para sa amin: Pangkalahatang-ideya ng REST.  Bahagi 3: Pagbuo ng isang RESTful na serbisyo sa Spring Boot - 4I-click ang "Next" button. Ngayon ang natitira na lang ay ipahiwatig ang pangalan ng proyekto at ang lokasyon nito sa file system: Pangkalahatang-ideya ng REST.  Bahagi 3: Pagbuo ng isang RESTful na serbisyo sa Spring Boot - 5I-click ang pindutang "Tapos na". Nagawa ang proyekto, at ngayon ay makikita na natin ang istruktura nito: Pangkalahatang-ideya ng REST.  Bahagi 3: Pagbuo ng isang RESTful na serbisyo sa Spring Boot - 6Ang IDEA ay nakabuo ng isang Maven deployment descriptor (pom.xml) at ang pangunahing klase ng application ( RestExampleApplication) para sa atin. Narito kung ano ang hitsura nila:

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

}

Gumagawa ng REST functionality

Ang aming aplikasyon ay isang sistema ng pamamahala ng customer. Kaya, ang unang bagay na kailangan nating gawin ay lumikha ng entity ng customer. Ito ay magiging isang klase ng POJO (plain old Java object). Lumikha ng isang modelpakete sa loob ng com.codegym.lessons.rest_examplepakete. Sa loob ng modelpackage, lumikha ng 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;
   }
}
Ipapatupad ng serbisyo ang mga operasyon ng CRUD sa mga customer. Ang susunod na hakbang ay lumikha ng isang serbisyo na magpapatupad ng mga operasyong ito. Sa com.codegym.lessons.rest_examplepakete, lumikha ng isang servicepakete. At sa loob nito, lumikha ng isang CustomerServiceinterface. Narito ang interface code na may mga komento:

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);
}
Susunod, kailangan nating ipatupad ang interface na ito. Ngayon ay Map<Integer, Customer>mag-iimbak ang aming mga customer. Ang mga susi ng mapa ay ang mga customer ID, at ang mga halaga ay ang mga customer mismo. Ginagawa ito upang hindi ma-overload ang halimbawang ito sa mga detalye ng pagtatrabaho sa isang tunay na database. Gayunpaman, sa hinaharap ay makakapagsulat kami ng isa pang pagpapatupad ng interface, na gagawing posible na kumonekta sa isang tunay na database. Sa servicepackage, lumikha ng pagpapatupad ng 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;
   }
}
Ang @Serviceanotasyon ay nagsasabi sa tagsibol na ang klase na ito ay isang serbisyo. Ito ay isang espesyal na uri ng klase na nagpapatupad ng ilang logic ng application ng negosyo. Kasunod nito, salamat sa anotasyong ito, gagamit ang Spring ng dependency injection upang magbigay sa amin ng isang instance ng klase na ito sa lahat ng lugar kung saan ito kinakailangan. Ngayon ay oras na upang lumikha ng isang controller. Ito ay isang espesyal na klase kung saan ipapatupad namin ang lohika para sa pagproseso ng mga kahilingan ng kliyente na ipinadala sa mga endpoint (URI). Upang gawing mas malinaw ang lahat, gagawin namin ang klase na ito nang paunti-unti. Una, lumikha ng klase mismo at magdagdag ng dependency sa CustomerService:

@RestController
public class CustomerController {

   private final CustomerService customerService;

   @Autowired
   public CustomerController(CustomerService customerService) {
       this.customerService = customerService;
   }
}
Ipaliwanag natin ang mga anotasyon: @RestController ay nagsasabi sa Spring na ang klase na ito ay isang REST controller. Sa madaling salita, ipinapatupad ng klase na ito ang lohika para sa pagproseso ng mga kahilingan ng kliyente. @Autowired ay nagsasabi sa Spring na ang isang dependency ay kailangang idagdag dito. Ipinapasa namin ang CustomerServiceinterface sa tagabuo. Mas maaga, minarkahan namin ang pagpapatupad ng serbisyong ito gamit ang @Serviceanotasyon, at ngayon ay maipapasa ng Spring ang isang instance ng pagpapatupad na ito sa constructor ng controller. Susunod, ipapatupad namin ang bawat paraan ng controller para sa paghawak ng mga operasyon ng CRUD. Magsimula tayo sa paggawa ng operasyon. Upang gawin ito, sumulat kami ng isang createpamamaraan:

@PostMapping(value = "/customers")
public ResponseEntity<?> create(@RequestBody Customer customer) {
   customerService.create(customer);
   return new ResponseEntity<>(HttpStatus.CREATED);
}
Suriin natin ang paraang ito: @PostMapping(value = "/customers")ibig sabihin, pinoproseso ng paraang ito ang mga kahilingan sa POST na ipinadala sa address na "/customers". Ang pamamaraan ay nagbabalik ng isang ResponseEntity<?>. Ang A ResponseEntityay isang espesyal na klase para sa pagbabalik ng mga tugon. Mamaya, gagamitin namin ito para magbalik ng HTTP status code sa client. Ang pamamaraan ay may isang @RequestBody Customer customerparameter. Ang value ng parameter na ito ay nagmumula sa request body. Ang @RequestBodyanotasyon ay nagpapahiwatig nito. Sa loob ng katawan ng pamamaraan, tinatawag namin ang create()pamamaraan sa naunang nilikha na serbisyo at ipasa ito sa customer controller na natanggap sa mga parameter. Pagkatapos ay ibabalik namin ang status na "201 Created" sa pamamagitan ng paglikha ng isang bagong ResponseEntityobject at pagpasa sa kaukulang HttpStatusfield ng enum dito. Susunod, ipapatupad natin angreadpagpapatakbo: Una, ipapatupad namin ang operasyon para makakuha ng listahan ng lahat ng available na customer:

@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);
}
Sumisid tayo: @GetMapping(value = "/customers")— lahat ng narito ay katulad ng @PostMappinganotasyon, ngunit ngayon ay pinoproseso namin ang mga kahilingan sa GET. Sa pagkakataong ito, ibinabalik namin ang isang ResponseEntity<List<Customer>>, at bilang karagdagan sa isang HTTP status, magbabalik din kami ng isang response body, na siyang magiging listahan ng mga customer. Sa REST controllers ng Spring, lahat ay POJO object at koleksyon ng POJO objects, na ibinalik bilang mga response body at awtomatikong naka-serialize sa JSON, maliban kung tinukoy. Ito ay ganap na nababagay sa amin. Sa loob ng pamamaraan, ginagamit namin ang aming serbisyo upang makakuha ng listahan ng lahat ng mga customer. Susunod, kung ang listahan ay hindi null at walang laman, pagkatapos ay gagamitin namin angResponseEntityclass upang ibalik ang listahan ng mga customer at ang "200 OK" HTTP status code. Kung hindi, ibabalik lang namin ang "404 Not Found" HTTP status code. Ngayon ay ipapatupad namin ang kakayahang makakuha ng customer gamit ang ID nito:

@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);
}
Isang bagong bagay dito ay ang path variable. Ang variable ay tinukoy sa URI: value = "/customers/{id}". Ipinapahiwatig namin ito sa mga kulot na braces. At natatanggap namin ito bilang isang intparameter ng pamamaraan gamit ang @PathVariable(name = "id")anotasyon. Ang pamamaraang ito ay tatanggap ng mga kahilingang ipinadala sa mga URI sa form /customers/{id}, kung saan {id}kumakatawan sa anumang numerong halaga. Ang halagang ito ay kasunod na ipinapasa sa pamamagitan ng int idvariable sa parameter ng pamamaraan. Sa katawan, nakukuha namin ang Customerbagay gamit ang aming serbisyo at ang natanggap id. At pagkatapos, sa pamamagitan ng pagkakatulad sa listahan, ibinabalik namin ang alinman sa "200 OK" na katayuan at ang Customermismong bagay, o simpleng "404 Not Found" na status kung ang system ay walang customer na may ganoong id. Kailangan pa rin nating ipatupad ang dalawang operasyon: i-update at tanggalin. Narito ang code para sa mga pamamaraang ito:

@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);
}
Walang talagang bago sa mga pamamaraang ito, kaya laktawan namin ang detalyadong paglalarawan. Ang tanging bagay na dapat banggitin ay ang update()pamamaraan ay humahawak sa mga kahilingan ng PUT ( @PutMappingannotation), at ang delete()pamamaraan ay humahawak ng mga kahilingan sa DELETE ( DeleteMappingannotation). Narito ang buong code para sa 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);
   }
}
Bilang resulta, ang istraktura ng aming proyekto ay ang mga sumusunod: Pangkalahatang-ideya ng REST.  Bahagi 3: Pagbuo ng isang RESTful na serbisyo sa Spring Boot - 7

Paglulunsad at pagsubok

Upang simulan ang aming aplikasyon, patakbuhin lamang ang main()pamamaraan sa RestExampleApplicationklase. Ngunit para subukan ang RESTful web services, kailangan naming mag-download ng karagdagang software. Ang katotohanan ay ang mga kahilingan sa GET ay medyo simple upang ipadala mula sa isang ordinaryong browser, ngunit ang isang ordinaryong browser ay hindi maaaring magpadala ng mga kahilingan sa POST, PUT at DELETE. Huwag mag-alala: maaari kang gumamit ng isang program na tinatawag na Postman upang magpadala ng anumang mga kahilingan sa HTTP. Maaari mong i-download ito dito . Pagkatapos mag-download at mag-install ng Postman, sinimulan naming subukan ang aming application. Upang gawin ito, buksan ang programa at lumikha ng bagong kahilingan: Pangkalahatang-ideya ng REST.  Bahagi 3: Pagbuo ng isang RESTful na serbisyo sa Spring Boot - 9I-click ang pindutang "Bago" sa kaliwang sulok sa itaas. Susunod, piliin ang "Kahilingan": Pangkalahatang-ideya ng REST.  Bahagi 3: Pagbuo ng isang RESTful na serbisyo sa Spring Boot - 10Susunod, bigyan ito ng pangalan at i-save ito. Ngayon subukan nating magpadala ng POST na kahilingan sa server at gawin ang unang customer: Pangkalahatang-ideya ng REST.  Bahagi 3: Pagbuo ng isang RESTful na serbisyo sa Spring Boot - 11Lumilikha kami ng ilang mga customer sa ganitong paraan. Pagkatapos ay binago namin ang uri ng kahilingan sa GET at ipadala ang kahilingan sa server: Pangkalahatang-ideya ng REST.  Bahagi 3: Pagbuo ng isang RESTful na serbisyo sa Spring Boot - 12

Buod

Binabati kita! Sapat na naming sakop ang REST. Mayroong malaking dami ng materyal, ngunit sana ay kapaki-pakinabang ito para sa iyo:
  1. Natutunan namin kung ano ang REST.

  2. Nalaman namin kung paano nagkaroon ng REST.

  3. Napag-usapan namin ang tungkol sa mga limitasyon ng at mga prinsipyo sa likod ng istilong arkitektura na ito:

    • arkitektura ng client-server
    • walang estado
    • pag-cache
    • pare-parehong interface
    • mga layer
    • code on demand (opsyonal)
  4. Ginalugad namin ang mga benepisyong ibinigay ng REST

  5. Sinuri namin nang detalyado kung paano nakikipag-ugnayan ang server at kliyente sa isa't isa sa pamamagitan ng HTTP protocol.

  6. Pinagmasdan naming mabuti ang mga kahilingan at tugon. Pinaghiwa-hiwalay namin ang kanilang mga bahagi.

  7. Sa wakas, nakakuha kami ng ilang praktikal na karanasan sa pamamagitan ng pagsulat ng aming sariling maliit na RESTful application gamit ang Spring Boot. At natutunan pa namin kung paano subukan ito gamit ang Postman.

Phew. Marami iyon, ngunit mayroon ka pa ring dapat gawin bilang takdang-aralin.

Takdang aralin

Subukan ang sumusunod:
  1. Kasunod ng paglalarawan sa itaas, lumikha ng iyong sariling proyekto sa Spring Boot at ipatupad ang parehong lohika tulad ng sa aralin. Ulitin ang lahat nang eksakto.
  2. Ilunsad ang application.
  3. I-download at i-configure ang Postman (o anumang iba pang tool para sa pagpapadala ng mga kahilingan, halimbawa, curl).
  4. Subukan ang mga kahilingan sa POST at GET sa parehong paraan na inilarawan sa aralin.
  5. Subukan ang PUT at DELETE na mga kahilingan sa iyong sarili.
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION