CodeGym /مدونة جافا /Random-AR /نظرة عامة على الراحة. الجزء 3: إنشاء خدمة RESTful على Spr...
John Squirrels
مستوى
San Francisco

نظرة عامة على الراحة. الجزء 3: إنشاء خدمة RESTful على Spring Boot

نشرت في المجموعة
هذا هو الجزء الأخير من نظرة عامة على REST. تناولنا في الأجزاء السابقة: نظرة عامة على الراحة.  الجزء 3: إنشاء خدمة RESTful على Spring Boot - 1

إنشاء مشروع

في هذا القسم، سنقوم بإنشاء تطبيق RESTful صغير باستخدام Spring Boot. سيقوم تطبيقنا بتنفيذ عمليات CRUD (الإنشاء والقراءة والتحديث والحذف) على العملاء من المثال الموجود في الجزء السابق من النظرة العامة. للبدء، سنقوم بإنشاء تطبيق Spring Boot جديد من خلال القائمة: ملف -> جديد -> مشروع... في النافذة التي تفتح، حدد Spring Initializr وحدد Project SDK: نظرة عامة على الراحة.  الجزء 3: بناء خدمة RESTful على Spring Boot - 2انقر فوق الزر "التالي". في النافذة التالية، حدد "Maven Project" كنوع المشروع، وحدد "المجموعة" و"القطعة الأثرية": نظرة عامة على الراحة.  الجزء 3: بناء خدمة RESTful على Spring Boot - 3انقر فوق الزر "التالي". في النافذة التالية، نحتاج إلى تحديد مكونات Spring Framework اللازمة للمشروع. سيكون Spring Web كافيًا بالنسبة لنا: نظرة عامة على الراحة.  الجزء 3: إنشاء خدمة RESTful على Spring Boot - 4انقر فوق الزر "التالي". الآن كل ما تبقى هو الإشارة إلى اسم المشروع وموقعه في نظام الملفات: نظرة عامة على الراحة.  الجزء 3: إنشاء خدمة RESTful على Spring Boot - 5انقر فوق الزر "إنهاء". تم إنشاء المشروع، والآن يمكننا رؤية هيكله: نظرة عامة على الراحة.  الجزء 3: إنشاء خدمة RESTful على Spring Boot - 6قامت IDEA بإنشاء واصف نشر 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>
تطبيق RestExample:
@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 حقن التبعية لتزويدنا بمثيل لهذه الفئة في جميع الأماكن التي نحتاج إليها. الآن حان الوقت لإنشاء وحدة تحكم. هذه فئة خاصة حيث سنقوم بتنفيذ منطق معالجة طلبات العميل المرسلة إلى نقاط النهاية (URIs). لجعل كل هذا أكثر وضوحا، سنقوم بإنشاء هذا الفصل بشكل تدريجي. أولاً، قم بإنشاء الفصل نفسه وأضف التبعية إلى 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". تقوم الطريقة بإرجاع ملف ResponseEntity<?>. A ResponseEntityهي فئة خاصة لإرجاع الاستجابات. وسنستخدمه لاحقًا لإرجاع رمز حالة HTTP إلى العميل. الطريقة لديها @RequestBody Customer customerمعلمة. تأتي قيمة هذه المعلمة من نص الطلب. والتعليق @RequestBodyيدل على ذلك. داخل نص الطريقة، نستدعي الطريقة create()على الخدمة التي تم إنشاؤها مسبقًا ونمررها إلى وحدة تحكم العميل التي تتلقاها في المعلمات. ثم نعيد الحالة "تم الإنشاء 201" عن طريق إنشاء ResponseEntityكائن جديد وتمرير HttpStatusحقل التعداد المقابل إليه. بعد ذلك، سنقوم بتنفيذ 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. هذه المرة نعيد ResponseEntity<List<Customer>>، وبالإضافة إلى حالة HTTP، سنعيد أيضًا نص الاستجابة، والذي سيكون قائمة العملاء. في وحدات تحكم Spring's REST، كل شيء عبارة عن كائنات POJO ومجموعات من كائنات POJO، والتي يتم إرجاعها كأجسام استجابة وتسلسلها تلقائيًا إلى JSON، ما لم ينص على خلاف ذلك. وهذا يناسبنا تماما. داخل الطريقة، نستخدم خدمتنا للحصول على قائمة بجميع العملاء. بعد ذلك، إذا لم تكن القائمة فارغة وليست فارغة، فإننا نستخدم الفئة ResponseEntityلإرجاع قائمة العملاء ورمز حالة HTTP "200 OK". وبخلاف ذلك، فإننا ببساطة نعيد رمز حالة HTTP "404 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);
}
شيء واحد جديد هنا هو متغير المسار. يتم تعريف المتغير في URI: value = "/customers/{id}". ونشير إليه بالأقواس المتعرجة. ونستقبلها كمعلمة intطريقة باستخدام @PathVariable(name = "id")التعليق التوضيحي. ستقبل هذه الطريقة الطلبات المرسلة إلى معرفات URI في النموذج /customers/{id}، حيث {id}يمثل أي قيمة رقمية. يتم بعد ذلك تمرير هذه القيمة عبر int idالمتغير إلى معلمة الطريقة. في الجسم، نحصل على Customerالكائن باستخدام خدمتنا والمستلمة id. وبعد ذلك، قياسًا على القائمة، نعيد إما الحالة "200 OK" والكائن Customerنفسه، أو ببساطة الحالة "404 Not Found" إذا لم يكن لدى النظام عميل لديه ذلك 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()وتتعامل الطريقة مع طلبات الحذف ( 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);
   }
}
ونتيجة لذلك، فإن هيكل مشروعنا هو كما يلي: نظرة عامة على الراحة.  الجزء 3: إنشاء خدمة RESTful على Spring Boot - 7

الإطلاق والاختبار

لبدء تطبيقنا، فقط قم بتشغيل main()الطريقة في RestExampleApplicationالفصل. ولكن لاختبار خدمات الويب RESTful، نحتاج إلى تنزيل برامج إضافية. الحقيقة هي أن طلبات GET من السهل جدًا إرسالها من متصفح عادي، لكن المتصفح العادي لا يمكنه إرسال طلبات POST وPUT وDELETE. لا تقلق: يمكنك استخدام برنامج يسمى Postman لإرسال أي طلبات HTTP. يمكنك تحميله من هنا . بعد تنزيل Postman وتثبيته، نبدأ في اختبار تطبيقنا. للقيام بذلك، افتح البرنامج وأنشئ طلبًا جديدًا: نظرة عامة على الراحة.  الجزء 3: بناء خدمة RESTful على Spring Boot - 9انقر فوق الزر "جديد" في الزاوية اليسرى العليا. بعد ذلك، حدد "طلب": نظرة عامة على الراحة.  الجزء 3: بناء خدمة RESTful على Spring Boot - 10بعد ذلك، أعطه اسمًا واحفظه. لنحاول الآن إرسال طلب POST إلى الخادم وإنشاء العميل الأول: نظرة عامة على الراحة.  الجزء 3: بناء خدمة RESTful على Spring Boot - 11نقوم بإنشاء العديد من العملاء بهذه الطريقة. ثم نقوم بتغيير نوع الطلب إلى GET وإرسال الطلب إلى الخادم: نظرة عامة على الراحة.  الجزء 3: بناء خدمة RESTful على Spring Boot - 12

ملخص

تهانينا! لقد قمنا بتغطية REST بما فيه الكفاية. كان هناك كمية كبيرة من المواد، ولكن نأمل أن تكون مفيدة لك:
  1. لقد تعلمنا ما هو REST.

  2. لقد تعلمنا كيف ظهرت REST إلى الوجود.

  3. تحدثنا عن القيود والمبادئ الكامنة وراء هذا النمط المعماري:

    • بنية خادم العميل
    • عديمي الجنسية
    • التخزين المؤقت
    • واجهة موحدة
    • طبقات
    • الرمز عند الطلب (اختياري)
  4. لقد استكشفنا الفوائد التي تقدمها REST

  5. لقد درسنا بالتفصيل كيفية تفاعل الخادم والعميل مع بعضهما البعض عبر بروتوكول HTTP.

  6. لقد ألقينا نظرة فاحصة على الطلبات والاستجابات. قمنا بتشريح الأجزاء المكونة لها.

  7. أخيرًا، حصلنا على بعض الخبرة العملية من خلال كتابة تطبيق RESTful الصغير الخاص بنا باستخدام Spring Boot. وتعلمنا أيضًا كيفية اختباره باستخدام Postman.

أوف. لقد كان ذلك كثيرًا، ولكن لا يزال هناك شيء عليك القيام به كواجب منزلي.

العمل في المنزل

حاول القيام بما يلي:
  1. باتباع الوصف أعلاه، قم بإنشاء مشروع Spring Boot الخاص بك وقم بتنفيذ نفس المنطق كما في الدرس. كرر كل شيء بالضبط.
  2. بدء تطبيق.
  3. قم بتنزيل وتكوين Postman (أو أي أداة أخرى لإرسال الطلبات، على سبيل المثال، Curl).
  4. اختبر طلبات POST وGET بنفس الطريقة الموضحة في الدرس.
  5. اختبر طلبات PUT وDELETE بنفسك.
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION