CodeGym /จาวาบล็อก /สุ่ม /ภาพรวมของ REST ตอนที่ 3: สร้างบริการ RESTful บน Spring Bo...
John Squirrels
ระดับ
San Francisco

ภาพรวมของ REST ตอนที่ 3: สร้างบริการ RESTful บน Spring Boot

เผยแพร่ในกลุ่ม
นี่คือส่วนสุดท้ายของภาพรวมของ REST ในส่วนก่อนหน้านี้ เราได้กล่าวถึง: ภาพรวมของ REST  ตอนที่ 3: สร้างบริการ RESTful บน Spring Boot - 1

การสร้างโครงการ

ในส่วนนี้ เราจะสร้างแอปพลิเคชัน RESTful ขนาดเล็กโดยใช้ Spring Boot แอปพลิเคชันของเราจะใช้การดำเนินการ CRUD (สร้าง อ่าน อัปเดต ลบ) กับลูกค้าจากตัวอย่างในส่วนก่อนหน้าของภาพรวม ในการเริ่มต้น เราจะสร้างแอปพลิเคชัน Spring Boot ใหม่ผ่านเมนู: ไฟล์ -> ใหม่ -> โครงการ... ในหน้าต่างที่เปิดขึ้น ให้เลือก Spring Initializr และระบุ Project SDK: ภาพรวมของ REST  ตอนที่ 3: สร้างบริการ RESTful บน Spring Boot - 2คลิกปุ่ม "ถัดไป" ในหน้าต่างถัดไป ระบุ "Maven Project" เป็นประเภทโครงการ ระบุ "Group" และ "Artifact": ภาพรวมของ REST  ตอนที่ 3: สร้างบริการ RESTful บน Spring Boot - 3คลิกปุ่ม "Next" ในหน้าต่างถัดไป เราต้องเลือกส่วนประกอบ Spring Framework ที่จำเป็นสำหรับโครงการ Spring Web จะเพียงพอสำหรับเรา: ภาพรวมของ REST  ตอนที่ 3: สร้างบริการ RESTful บน Spring Boot - 4คลิกปุ่ม "ถัดไป" ตอนนี้สิ่งที่เหลืออยู่คือการระบุชื่อของโครงการและตำแหน่งในระบบไฟล์: ภาพรวมของ REST  ตอนที่ 3: สร้างบริการ RESTful บน Spring Boot - 5คลิกปุ่ม "เสร็จสิ้น" โครงการถูกสร้างขึ้น และตอนนี้เราสามารถเห็นโครงสร้างของมัน: ภาพรวมของ REST  ตอนที่ 3: สร้างบริการ RESTful บน Spring Boot - 6IDEA สร้างตัวอธิบายการปรับใช้ Maven (pom.xml) และคลาสหลักของแอปพลิเคชัน ( RestExampleApplication) ให้เรา นี่คือลักษณะที่ปรากฏ:

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>
ส่วนที่เหลือตัวอย่างแอปพลิเคชัน:

@SpringBootApplication
public class RestExampleApplication {

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

}

การสร้างฟังก์ชัน REST

แอปพลิเคชันของเราคือระบบการจัดการลูกค้า ดังนั้น สิ่งแรกที่เราต้องทำคือสร้างเอนทิตีลูกค้า มันจะเป็นคลาส POJO (วัตถุ Java เก่าธรรมดา) สร้างmodelแพ็คเกจภายในcom.codegym.lessons.rest_exampleแพ็คเกจ ภายในmodelแพ็คเกจ สร้าง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;
   }
}
บริการจะใช้การดำเนินการ CRUD กับลูกค้า ขั้นตอนต่อไปคือการสร้างบริการที่จะใช้การดำเนินการเหล่านี้ ในcom.codegym.lessons.rest_exampleแพ็คเกจ สร้างserviceแพ็คเกจ และภายในนั้นให้สร้างCustomerServiceส่วนต่อประสาน นี่คือรหัสอินเทอร์เฟซพร้อมความคิดเห็น:

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);
}
ต่อไป เราต้องใช้อินเทอร์เฟซนี้ ตอนนี้Map<Integer, Customer>จะเก็บลูกค้าของเรา คีย์ของแผนที่จะเป็นรหัสลูกค้า และค่าต่างๆ จะเป็นตัวลูกค้าเอง สิ่งนี้ทำเพื่อไม่ให้โอเวอร์โหลดตัวอย่างนี้ด้วยลักษณะเฉพาะของการทำงานกับฐานข้อมูลจริง อย่างไรก็ตาม ในอนาคตเราจะสามารถเขียนการใช้งานอินเทอร์เฟซอื่นได้ ซึ่งจะทำให้สามารถเชื่อมต่อกับฐานข้อมูลจริงได้ ในserviceแพ็คเกจ สร้างการใช้งาน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;
   }
}
คำ@Serviceอธิบายประกอบบอกสปริงว่าคลาสนี้เป็นบริการ นี่คือคลาสประเภทพิเศษที่ใช้ตรรกะของแอปพลิเคชันทางธุรกิจบางอย่าง ต่อจากนั้น ด้วยคำอธิบายประกอบนี้ Spring จะใช้การพึ่งพาการฉีดเพื่อให้อินสแตนซ์ของคลาสนี้แก่เราในทุกที่ที่จำเป็น ตอนนี้ได้เวลาสร้างคอนโทรลเลอร์แล้ว นี่คือคลาสพิเศษที่เราจะใช้ตรรกะสำหรับการประมวลผลคำขอของไคลเอ็นต์ที่ส่งไปยังจุดสิ้นสุด (URI) เพื่อให้ชัดเจนยิ่งขึ้น เราจะสร้างคลาสนี้ทีละน้อย ขั้นแรก สร้างคลาสเองและเพิ่มการอ้างอิงในCustomerService:

@RestController
public class CustomerController {

   private final CustomerService customerService;

   @Autowired
   public CustomerController(CustomerService customerService) {
       this.customerService = customerService;
   }
}
มาอธิบายคำอธิบายประกอบกัน: @RestControllerบอก Spring ว่าคลาสนี้เป็นตัวควบคุม REST กล่าวอีกนัยหนึ่ง คลาสนี้ใช้ตรรกะสำหรับการประมวลผลคำขอของไคลเอ็นต์ @Autowiredบอก Spring ว่าจำเป็นต้องเพิ่มการพึ่งพาที่นี่ เราส่ง ส่วนต่อ CustomerServiceประสานไปยังตัวสร้าง ก่อนหน้านี้ เราทำเครื่องหมายการใช้งานบริการนี้ด้วย@Serviceคำอธิบายประกอบ และตอนนี้ Spring จะสามารถส่งอินสแตนซ์ของการใช้งานนี้ไปยังตัวสร้างของคอนโทรลเลอร์ได้ ต่อไป เราจะใช้วิธีการควบคุมแต่ละวิธีสำหรับการจัดการการทำงานของ CRUD เริ่มต้นด้วยการดำเนินการสร้าง ในการทำเช่นนี้ เราเขียนcreateวิธีการ:

@PostMapping(value = "/customers")
public ResponseEntity<?> create(@RequestBody Customer customer) {
   customerService.create(customer);
   return new ResponseEntity<>(HttpStatus.CREATED);
}
มาวิเคราะห์วิธีนี้กัน: @PostMapping(value = "/customers")หมายความว่าวิธีนี้จะประมวลผลคำขอ POST ที่ส่งไปยังที่อยู่ "/customers" เมธอดจะคืนค่า a ResponseEntity<?>. A ResponseEntityเป็นคลาสพิเศษสำหรับการตอบกลับ ในภายหลัง เราจะใช้เพื่อส่งคืนรหัสสถานะ HTTP ให้กับลูกค้า วิธีการมี@RequestBody Customer customerพารามิเตอร์ ค่าของพารามิเตอร์นี้มาจากเนื้อหาคำขอ คำ@RequestBodyอธิบายประกอบระบุสิ่งนี้ ภายในเนื้อหาของเมธอด เราเรียกcreate()เมธอดบนบริการที่สร้างไว้ก่อนหน้านี้ และส่งต่อไปยังตัวควบคุมที่ลูกค้าได้รับในพารามิเตอร์ จากนั้นเราจะส่งคืนสถานะ "201 สร้างแล้ว" โดยสร้างResponseEntityวัตถุใหม่และส่งHttpStatusผ่านฟิลด์ enum ที่สอดคล้องกัน ต่อไปเราจะดำเนินการreadการดำเนินการ: ขั้นแรก เราจะดำเนินการเพื่อรับรายชื่อลูกค้าที่มีอยู่ทั้งหมด:

@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")— ทุกอย่างที่นี่คล้ายกับ@PostMappingคำอธิบายประกอบ แต่ตอนนี้เรากำลังประมวลผลคำขอ GET ครั้งนี้เราส่งคืน a ResponseEntity<List<Customer>>และนอกเหนือจากสถานะ HTTP แล้ว เราจะส่งคืนเนื้อหาตอบกลับด้วย ซึ่งจะเป็นรายชื่อลูกค้า ในตัวควบคุม REST ของ Spring ทุกอย่างคือออบเจกต์ POJO และคอลเล็กชันของออบเจ็กต์ POJO ซึ่งส่งคืนเป็นเนื้อหาการตอบสนองและจัดลำดับเป็น JSON โดยอัตโนมัติ เว้นแต่จะระบุไว้เป็นอย่างอื่น สิ่งนี้เหมาะกับเราอย่างสมบูรณ์แบบ ภายในวิธีการ เราใช้บริการของเราเพื่อรับรายชื่อลูกค้าทั้งหมด ต่อไป หากรายการไม่เป็นโมฆะและไม่ว่างเปล่า เราจะใช้ResponseEntityคลาสเพื่อส่งคืนรายชื่อลูกค้าและรหัสสถานะ HTTP "200 ตกลง" มิฉะนั้น เราจะส่งคืนรหัสสถานะ HTTP "404 ไม่พบ" ตอนนี้เราจะใช้ความสามารถในการรับลูกค้าโดยใช้ 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);
}
สิ่งใหม่อย่างหนึ่งที่นี่คือตัวแปรเส้นทาง ตัวแปรถูกกำหนดใน URI value = "/customers/{id}": เราระบุไว้ในวงเล็บปีกกา และเราได้รับเป็นintพารามิเตอร์เมธอดโดยใช้@PathVariable(name = "id")คำอธิบายประกอบ วิธีนี้จะยอมรับคำขอที่ส่งไปยัง URI ในรูปแบบ/customers/{id}ซึ่ง{id}แทนค่าตัวเลขใดๆ ค่านี้จะถูกส่งต่อผ่านint idตัวแปรไปยังพารามิเตอร์เมธอด ในร่างกาย เราได้รับวัตถุCustomerโดยใช้บริการของเราและที่ได้idรับ จากนั้นโดยการเปรียบเทียบกับรายการ เราจะส่งคืนสถานะ "200 ตกลง" และตัวCustomerวัตถุเอง หรือเรียกง่ายๆ ว่าสถานะ "404 ไม่พบ" หากระบบไม่มีลูกค้าidด้วย เรายังต้องใช้การดำเนินการสองอย่าง: อัปเดตและลบ นี่คือรหัสสำหรับวิธีการเหล่านี้:

@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);
}
วิธีการเหล่านี้ไม่มีอะไรใหม่เป็นหลัก ดังนั้นเราจะข้ามคำอธิบายโดยละเอียดไป สิ่งเดียวที่ควรกล่าวถึงคือupdate()เมธอดจัดการคำขอ PUT ( @PutMappingคำอธิบายประกอบ) และdelete()เมธอดจัดการคำขอ DELETE ( DeleteMappingคำอธิบายประกอบ) นี่คือรหัสเต็มสำหรับคอนโทรลเลอร์:

@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);
   }
}
เป็นผลให้โครงสร้างของโครงการของเราเป็นดังนี้: ภาพรวมของ REST  ตอนที่ 3: สร้างบริการ RESTful บน Spring Boot - 7

การเปิดตัวและการทดสอบ

ในการเริ่มแอปพลิเคชันของเรา ให้เรียกใช้main()เมธอดในRestExampleApplicationคลาส แต่เพื่อทดสอบบริการเว็บ RESTful เราจำเป็นต้องดาวน์โหลดซอฟต์แวร์เพิ่มเติม ความจริงก็คือคำขอ GET นั้นค่อนข้างง่ายที่จะส่งจากเบราว์เซอร์ทั่วไป แต่เบราว์เซอร์ทั่วไปไม่สามารถส่งคำขอ POST, PUT และ DELETE ได้ ไม่ต้องกังวล คุณสามารถใช้โปรแกรมที่ชื่อว่าบุรุษไปรษณีย์เพื่อส่งคำขอ HTTP คุณสามารถดาวน์โหลดได้ที่นี่ หลังจากดาวน์โหลดและติดตั้ง Postman แล้ว เราจะเริ่มทดสอบแอปพลิเคชันของเรา ในการทำเช่นนี้ ให้เปิดโปรแกรมและสร้างคำขอใหม่: ภาพรวมของ REST  ตอนที่ 3: สร้างบริการ RESTful บน Spring Boot - 9คลิกปุ่ม "ใหม่" ที่มุมซ้ายบน จากนั้นเลือก "คำขอ": ภาพรวมของ REST  ตอนที่ 3: สร้างบริการ RESTful บน Spring Boot - 10จากนั้นตั้งชื่อและบันทึก ตอนนี้ลองส่งคำขอ POST ไปยังเซิร์ฟเวอร์และสร้างลูกค้ารายแรก: ภาพรวมของ REST  ตอนที่ 3: สร้างบริการ RESTful บน Spring Boot - 11เราสร้างลูกค้าจำนวนมากด้วยวิธีนี้ จากนั้นเราเปลี่ยนประเภทคำขอเป็น GET และส่งคำขอไปยังเซิร์ฟเวอร์: ภาพรวมของ REST  ตอนที่ 3: สร้างบริการ RESTful บน Spring Boot - 12

สรุป

ยินดีด้วย! เราได้พักผ่อนเพียงพอแล้ว มีเนื้อหาจำนวนมาก แต่หวังว่าจะเป็นประโยชน์สำหรับคุณ:
  1. เราได้เรียนรู้ว่า REST คืออะไร

  2. เราได้เรียนรู้ว่า REST เกิดขึ้นมาได้อย่างไร

  3. เราได้พูดคุยเกี่ยวกับข้อจำกัดและหลักการเบื้องหลังรูปแบบสถาปัตยกรรมนี้:

    • สถาปัตยกรรมไคลเอ็นต์เซิร์ฟเวอร์
    • ไร้สัญชาติ
    • เก็บเอาไว้
    • อินเตอร์เฟซที่เหมือนกัน
    • ชั้น
    • รหัสตามความต้องการ (ไม่บังคับ)
  4. เราได้สำรวจประโยชน์ที่ได้รับจาก REST

  5. เราได้ตรวจสอบโดยละเอียดว่าเซิร์ฟเวอร์และไคลเอนต์โต้ตอบกันอย่างไรผ่านโปรโตคอล HTTP

  6. เราได้ตรวจสอบคำขอและการตอบสนองอย่างใกล้ชิดยิ่งขึ้น เราผ่าส่วนประกอบของมันออก

  7. สุดท้าย เราได้รับประสบการณ์จริงจากการเขียนแอปพลิเคชัน RESTful ขนาดเล็กของเราเองโดยใช้ Spring Boot และเรายังได้เรียนรู้วิธีทดสอบโดยใช้บุรุษไปรษณีย์

วุ้ย. นั่นเป็นจำนวนมาก แต่ก็ยังมีบางอย่างให้คุณทำการบ้าน

การบ้าน

ลองดังต่อไปนี้:
  1. ทำตามคำอธิบายด้านบน สร้างโครงการ Spring Boot ของคุณเองและใช้ตรรกะเดียวกับในบทเรียน ทำซ้ำทุกอย่างถูกต้อง
  2. เปิดแอปพลิเคชัน
  3. ดาวน์โหลดและกำหนดค่าบุรุษไปรษณีย์ (หรือเครื่องมืออื่นๆ สำหรับส่งคำขอ เช่น curl)
  4. ทดสอบคำขอ POST และ GET ด้วยวิธีเดียวกับที่อธิบายไว้ในบทเรียน
  5. ทดสอบคำขอ PUT และ DELETE ด้วยตัวคุณเอง
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION