JavaRush /مدونة جافا /Random-AR /نظرة عامة على الراحة. الجزء 3: إنشاء خدمة RESTful في Spri...

نظرة عامة على الراحة. الجزء 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، وحدد المجموعة والقطعة الأثرية: نظرة عامة على الراحة.  الجزء 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.javarush.lectures</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. لنقم بإنشاء حزمة modelداخل حزمة com.javarush.lectures.rest_example. modelلنقم بإنشاء فئة داخل الحزمة Client:
public class Client {

   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.javarush.lectures.rest_exampleسوف نقوم بإنشاء حزمة service، بداخلها سوف نقوم بإنشاء واجهة ClientService. إليك رمز الواجهة مع التعليقات:
public interface ClientService {

   /**
    * Создает нового клиента
    * @param client - клиент для создания
    */
   void create(Client client);

   /**
    * returns список всех имеющихся клиентов
    * @return список клиентов
    */
   List<client> readAll();

   /**
    * returns клиента по его ID
    * @param id - ID клиента
    * @return - an object клиента с заданным ID
    */
   Client read(int id);

   /**
    * Обновляет клиента с заданным ID,
    * в соответствии с переданным клиентом
    * @param client - клиент в соответсвии с которым нужно обновить данные
    * @param id - id клиента которого нужно обновить
    * @return - true если данные были обновлены, иначе false
    */
   boolean update(Client client, int id);

   /**
    * Удаляет клиента с заданным ID
    * @param id - id клиента, которого нужно удалить
    * @return - true если клиент был удален, иначе false
    */
   boolean delete(int id);
}
بعد ذلك نحتاج إلى إنشاء تطبيق لهذه الواجهة. الآن سوف يكون بمثابة مستودع العميل Map<Integer, Client>. سيكون مفتاح البطاقة هو معرف العميل، وستكون القيمة هي العميل نفسه. تم ذلك حتى لا يتم تحميل المثال بتفاصيل العمل مع قاعدة البيانات. ومع ذلك، في المستقبل سنكون قادرين على كتابة تطبيق آخر للواجهة حيث سيكون من الممكن توصيل قاعدة بيانات حقيقية. في الحزمة serviceسنقوم بإنشاء تطبيق للواجهة ClientService:
@Service
public class ClientServiceImpl implements ClientService {

   // Хранorще клиентов
   private static final Map<Integer, Client> CLIENT_REPOSITORY_MAP = new HashMap<>();

   // Переменная для генерации ID клиента
   private static final AtomicInteger CLIENT_ID_HOLDER = new AtomicInteger();

   @Override
   public void create(Client client) {
       final int clientId = CLIENT_ID_HOLDER.incrementAndGet();
       client.setId(clientId);
       CLIENT_REPOSITORY_MAP.put(clientId, client);
   }

   @Override
   public List<Client> readAll() {
       return new ArrayList<>(CLIENT_REPOSITORY_MAP.values());
   }

   @Override
   public Client read(int id) {
       return CLIENT_REPOSITORY_MAP.get(id);
   }

   @Override
   public boolean update(Client client, int id) {
       if (CLIENT_REPOSITORY_MAP.containsKey(id)) {
           client.setId(id);
           CLIENT_REPOSITORY_MAP.put(id, client);
           return true;
       }

       return false;
   }

   @Override
   public boolean delete(int id) {
       return CLIENT_REPOSITORY_MAP.remove(id) != null;
   }
}
يخبر التعليق التوضيحي @ServiceSpring أن هذه الفئة عبارة عن خدمة. هذا نوع خاص من الفئات يتم فيه تنفيذ بعض منطق الأعمال الخاص بالتطبيق. بعد ذلك، بفضل هذا التعليق التوضيحي، سيزودنا Spring بمثيل لهذه الفئة في الأماكن التي تكون هناك حاجة إليها باستخدام Dependency Solution. الآن حان الوقت لإنشاء وحدة التحكم. فئة خاصة ننفذ فيها منطق معالجة طلبات العميل لنقاط النهاية (URIs). لتوضيح الأمر أكثر، سنقوم بإنشاء هذا الفصل على أجزاء. أولاً، لنقم بإنشاء الفصل نفسه ونقدم التبعية له ClientService:
@RestController
public class ClientController {

   private final ClientService clientService;

   @Autowired
   public ClientController(ClientService clientService) {
       this.clientService = clientService;
   }
}
دعونا نوضح التعليقات التوضيحية: @RestController - يخبر Spring أن هذه الفئة عبارة عن وحدة تحكم REST. أولئك. ستنفذ هذه الفئة منطق معالجة طلبات العميل @Autowired - تخبر Spring أنه يجب حقن التبعية في هذا المكان. نقوم بتمرير الواجهة إلى المنشئ ClientService. لقد وضعنا علامة على تنفيذ هذه الخدمة بتعليق توضيحي @Serviceسابقًا، والآن سيتمكن Spring من تمرير مثيل لهذا التنفيذ إلى مُنشئ وحدة التحكم. بعد ذلك، سنقوم خطوة بخطوة بتنفيذ كل طريقة تحكم لمعالجة عمليات CRUD. لنبدأ بعملية الإنشاء. للقيام بذلك، دعونا نكتب طريقة create:
@PostMapping(value = "/clients")
public ResponseEntity<?> create(@RequestBody Client client) {
   clientService.create(client);
   return new ResponseEntity<>(HttpStatus.CREATED);
}
لننظر إلى هذه الطريقة: @PostMapping(value = "/clients")- نعني هنا أن هذه الطريقة تعالج طلبات POST إلى عنوان /clients، وترجع الطريقة ResponseEntity<?>. ResponseEntity- فئة خاصة لإرجاع الردود. باستخدامه، يمكننا لاحقًا إعادة رمز حالة HTTP إلى العميل. تأخذ الطريقة معلمة @RequestBody Client client، ويتم استبدال قيمة هذه المعلمة من نص الطلب. الملخص يتحدث عن هذا @RequestBody. داخل نص الطريقة، نسمي طريقة الإنشاء على الخدمة التي تم إنشاؤها مسبقًا ونمررها إلى وحدة تحكم العميل المقبولة في المعلمات. ثم نعيد الحالة 201 التي تم إنشاؤها عن طريق إنشاء كائن جديد ResponseEntityوتمرير قيمة التعداد المطلوبة إليه HttpStatus. بعد ذلك نقوم بتنفيذ العملية Read: أولا نقوم بتنفيذ عملية الحصول على قائمة بجميع العملاء المتاحين:
@GetMapping(value = "/clients")
public ResponseEntity<List<Client>> read() {
   final List<Client> clients = clientService.readAll();

   return clients != null &&  !clients.isEmpty()
           ? new ResponseEntity<>(clients, HttpStatus.OK)
           : new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
لنبدأ التحليل: @GetMapping(value = "/clients")- كل شيء مشابه للتعليق التوضيحي @PostMapping، الآن فقط نقوم بمعالجة طلبات GET. نعود هذه المرة ResponseEntity<List<Client>>، هذه المرة فقط، بالإضافة إلى حالة HTTP، سنعيد أيضًا نص الاستجابة، والذي سيكون عبارة عن قائمة العملاء. في وحدات تحكم Spring REST، يتم إجراء تسلسل تلقائي لجميع كائنات POJO، بالإضافة إلى مجموعات كائنات POJO التي يتم إرجاعها كأجسام استجابة، إلى JSON ما لم يُنص على خلاف ذلك صراحةً. نحن سعداء جدا بهذا. داخل الطريقة، باستخدام خدمتنا، نحصل على قائمة بجميع العملاء. بعد ذلك، إذا لم تكن القائمة فارغة أو فارغة، فإننا نعيد ResponseEntityقائمة العملاء وحالة HTTP 200 OK باستخدام الفئة. وبخلاف ذلك، فإننا ببساطة نعيد حالة HTTP 404 Not Found. بعد ذلك، سنقوم بتنفيذ القدرة على الحصول على العميل عن طريق هويته:
@GetMapping(value = "/clients/{id}")
public ResponseEntity<Client> read(@PathVariable(name = "id") int id) {
   final Client client = clientService.read(id);

   return client != null
           ? new ResponseEntity<>(client, HttpStatus.OK)
           : new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
الشيء الجديد هو أن لدينا الآن متغير المسار. متغير تم تعريفه في URI. value = "/clients/{id}". وقد أشرنا إليه بالأقواس المتعرجة. وفي معلمات الطريقة نقبله كمتغير intباستخدام التعليق التوضيحي @PathVariable(name = "id"). ستقبل هذه الطريقة طلبات uri للنموذج /clients/{id}، حيث {id}يمكن أن تكون هناك أي قيمة رقمية بدلاً من ذلك. يتم بعد ذلك تمرير هذه القيمة إلى متغير int id— معلمة الطريقة. في الجسم نستقبل الكائن Clientباستخدام خدمتنا ونقبله id. وبعد ذلك، قياسًا على القائمة، نعيد إما الحالة 200 موافق والكائن نفسه Client، أو ببساطة الحالة 404 غير موجود، إذا idلم يكن هناك عميل بهذا في النظام. يبقى تنفيذ عمليتين - التحديث والحذف. إليك الكود الخاص بهذه الطرق:
@PutMapping(value = "/clients/{id}")
public ResponseEntity<?> update(@PathVariable(name = "id") int id, @RequestBody Client client) {
   final boolean updated = clientService.update(client, id);

   return updated
           ? new ResponseEntity<>(HttpStatus.OK)
           : new ResponseEntity<>(HttpStatus.NOT_MODIFIED);
}

@DeleteMapping(value = "/clients/{id}")
public ResponseEntity<?> delete(@PathVariable(name = "id") int id) {
   final boolean deleted = clientService.delete(id);

   return deleted
           ? new ResponseEntity<>(HttpStatus.OK)
           : new ResponseEntity<>(HttpStatus.NOT_MODIFIED);
}
لا يوجد شيء جديد بشكل أساسي في هذه الأساليب، لذلك سوف نتخطى الوصف التفصيلي. الشيء الوحيد الجدير بالذكر هو أن الطريقة updateتعالج طلبات PUT (التعليق التوضيحي @PutMapping)، وتقوم الطريقة deleteبمعالجة طلبات الحذف (التعليق التوضيحي DeleteMapping). إليك رمز التحكم الكامل:
@RestController
public class ClientController {

   private final ClientService clientService;

   @Autowired
   public ClientController(ClientService clientService) {
       this.clientService = clientService;
   }

   @PostMapping(value = "/clients")
   public ResponseEntity<?> create(@RequestBody Client client) {
       clientService.create(client);
       return new ResponseEntity<>(HttpStatus.CREATED);
   }

   @GetMapping(value = "/clients")
   public ResponseEntity<List<Client>> read() {
       final List<client> clients = clientService.readAll();

       return clients != null &&  !clients.isEmpty()
               ? new ResponseEntity<>(clients, HttpStatus.OK)
               : new ResponseEntity<>(HttpStatus.NOT_FOUND);
   }

   @GetMapping(value = "/clients/{id}")
   public ResponseEntity<Client> read(@PathVariable(name = "id") int id) {
       final Client client = clientService.read(id);

       return client != null
               ? new ResponseEntity<>(client, HttpStatus.OK)
               : new ResponseEntity<>(HttpStatus.NOT_FOUND);
   }

   @PutMapping(value = "/clients/{id}")
   public ResponseEntity<?> update(@PathVariable(name = "id") int id, @RequestBody Client client) {
       final boolean updated = clientService.update(client, id);

       return updated
               ? new ResponseEntity<>(HttpStatus.OK)
               : new ResponseEntity<>(HttpStatus.NOT_MODIFIED);
   }

   @DeleteMapping(value = "/clients/{id}")
   public ResponseEntity<?> delete(@PathVariable(name = "id") int id) {
       final boolean deleted = clientService.delete(id);

       return deleted
               ? new ResponseEntity<>(HttpStatus.OK)
               : new ResponseEntity<>(HttpStatus.NOT_MODIFIED);
   }
}
ونتيجة لذلك، يبدو هيكل مشروعنا كما يلي: نظرة عامة على الراحة.  الجزء 3: إنشاء خدمة RESTful في Spring Boot - 7

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

لتشغيل تطبيقنا، ما عليك سوى تشغيل الطريقة الموجودة mainفي الفصل RestExampleApplication. ومن أجل اختبار خدمات الويب RESTful، تحتاج إلى تنزيل برنامج جديد) الحقيقة هي أن طلبات GET من السهل جدًا إرسالها من متصفح عادي، ولكن بالنسبة للنشر والوضع والحذف، فإن المتصفح العادي لا يكفي. لا تقلق: يمكنك استخدام Postman لإرسال أي طلبات HTTP. يمكنك تحميل البرنامج من هنا . بعد التنزيل والتثبيت، نبدأ في اختبار تطبيقنا. للقيام بذلك، افتح البرنامج وقم بإنشاء طلب جديد: نظرة عامة على الراحة.  الجزء 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

النتائج العامة

تهانينا: لقد تناولنا موضوع REST تمامًا. تبين أن جميع المواد ضخمة، لكننا نأمل أن تكون مفيدة لك:
  1. لقد تعلمنا ما هو REST.

  2. تعرفنا على تاريخ REST.

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

    • جلب الهندسة المعمارية إلى نموذج خادم العميل؛
    • نقص الحالة
    • التخزين المؤقت؛
    • توحيد الواجهة
    • طبقات؛
    • رمز عند الطلب (تقييد اختياري).
  4. لقد درسنا المزايا التي توفرها REST

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

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

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

أوف. اتضح أنها ضخمة، ولكن مع ذلك هناك شيء يجب القيام به كواجب منزلي.

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

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