CodeGym /وبلاگ جاوا /Random-FA /نمای کلی REST. قسمت 3: ایجاد یک سرویس RESTful در Spring B...
John Squirrels
مرحله
San Francisco

نمای کلی REST. قسمت 3: ایجاد یک سرویس RESTful در Spring Boot

در گروه منتشر شد
این بخش پایانی مرور کلی ما از REST است. در قسمت های قبل به موارد زیر پرداختیم: نمای کلی REST.  قسمت 3: ایجاد یک سرویس RESTful در Spring Boot - 1

ایجاد یک پروژه

در این قسمت با استفاده از Spring Boot یک برنامه کوچک RESTful ایجاد می کنیم. برنامه ما عملیات CRUD (ایجاد، خواندن، به روز رسانی، حذف) را از مثال در قسمت قبلی نمای کلی بر روی مشتریان اجرا می کند. برای شروع، یک برنامه Spring Boot جدید از طریق منو ایجاد می کنیم: File -> New -> Project... در پنجره باز شده Spring Initializr را انتخاب کرده و Project SDK را مشخص کنید: نمای کلی REST.  قسمت 3: ایجاد یک سرویس RESTful در Spring Boot - 2روی دکمه "Next" کلیک کنید. در پنجره بعدی، "Maven Project" را به عنوان نوع پروژه مشخص کنید، "Group" و "Artifact" را مشخص کنید: نمای کلی REST.  قسمت 3: ایجاد یک سرویس RESTful در Spring Boot - 3روی دکمه "Next" کلیک کنید. در پنجره بعدی باید اجزای Spring Framework لازم برای پروژه را انتخاب کنیم. بهار وب برای ما کافی است: نمای کلی 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>
RestExampleApplication:
@SpringBootApplication
public class RestExampleApplication {

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

}

ایجاد قابلیت REST

برنامه ما یک سیستم مدیریت مشتری است. بنابراین، اولین کاری که باید انجام دهیم این است که یک موجودیت مشتری ایجاد کنیم. این یک کلاس POJO (شیء قدیمی جاوا) خواهد بود. یک 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 می گوید که این کلاس یک سرویس است. این نوع خاصی از کلاس است که برخی از منطق برنامه های تجاری را پیاده سازی می کند. متعاقباً، به لطف این حاشیه‌نویسی، 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()متد را روی سرویس ایجاد شده قبلی فراخوانی می کنیم و آن را به کنترل کننده مشتری در پارامترها ارسال می کنیم. ResponseEntityسپس با ایجاد یک شی جدید و ارسال HttpStatusفیلد enum مربوطه به آن، وضعیت "201 Created" را برمی گردانیم . در مرحله بعد، عملیات را اجرا می کنیم 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 ( @PutMappingannotation ) را مدیریت می‌کند و delete()متد درخواست‌های DELETE ( DeleteMappingannotation ) را مدیریت می‌کند. این کد کامل برای کنترلر است:
@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 را ارسال کند. نگران نباشید: می توانید از برنامه ای به نام Postman برای ارسال هرگونه درخواست 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

خلاصه

تبریک می گویم! ما به اندازه کافی 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