โค้ดยิม/จาวาบล็อก/สุ่ม/ภาพรวมของ 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 ด้วยตัวคุณเอง
ความคิดเห็น
  • เป็นที่นิยม
  • ใหม่
  • เก่า
คุณต้องลงชื่อเข้าใช้เพื่อแสดงความคิดเห็น
หน้านี้ยังไม่มีความคิดเห็นใด ๆ