این بخش پایانی مرور کلی ما از REST است. در قسمت های قبل به موارد زیر پرداختیم:
روی دکمه "Next" کلیک کنید. در پنجره بعدی، "Maven Project" را به عنوان نوع پروژه مشخص کنید، "Group" و "Artifact" را مشخص کنید:
روی دکمه "Next" کلیک کنید. در پنجره بعدی باید اجزای Spring Framework لازم برای پروژه را انتخاب کنیم. بهار وب برای ما کافی است:
روی دکمه "بعدی" کلیک کنید. اکنون تنها چیزی که باقی می ماند این است که نام پروژه و مکان آن را در سیستم فایل مشخص کنید:
روی دکمه "پایان" کلیک کنید. پروژه ایجاد شده است و اکنون میتوانیم ساختار آن را ببینیم:
IDEA یک توصیفگر استقرار Maven (pom.xml) و کلاس اصلی برنامه (
روی دکمه "جدید" در گوشه سمت چپ بالا کلیک کنید. در مرحله بعد، "درخواست" را انتخاب کنید:
در مرحله بعد، نامی به آن بدهید و آن را ذخیره کنید. حالا بیایید سعی کنیم یک درخواست POST به سرور ارسال کنیم و اولین مشتری را ایجاد کنیم:
ما چندین مشتری را به این ترتیب ایجاد می کنیم. سپس نوع درخواست را به GET تغییر می دهیم و درخواست را به سرور ارسال می کنیم:

ایجاد یک پروژه
در این قسمت با استفاده از Spring Boot یک برنامه کوچک RESTful ایجاد می کنیم. برنامه ما عملیات CRUD (ایجاد، خواندن، به روز رسانی، حذف) را از مثال در قسمت قبلی نمای کلی بر روی مشتریان اجرا می کند. برای شروع، یک برنامه Spring Boot جدید از طریق منو ایجاد می کنیم: File -> New -> Project... در پنجره باز شده Spring Initializr را انتخاب کرده و Project SDK را مشخص کنید:




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 ( @PutMapping
annotation ) را مدیریت میکند و delete()
متد درخواستهای DELETE ( DeleteMapping
annotation ) را مدیریت میکند. این کد کامل برای کنترلر است:
@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);
}
}
در نتیجه ساختار پروژه ما به شرح زیر است: 
راه اندازی و آزمایش
برای شروع برنامه ما، فقطmain()
متد را در RestExampleApplication
کلاس اجرا کنید. اما برای تست وب سرویس های RESTful، باید نرم افزارهای اضافی را دانلود کنیم. واقعیت این است که درخواست های GET برای ارسال از یک مرورگر معمولی بسیار ساده است، اما یک مرورگر معمولی نمی تواند درخواست های POST، PUT و DELETE را ارسال کند. نگران نباشید: می توانید از برنامه ای به نام Postman برای ارسال هرگونه درخواست HTTP استفاده کنید. می توانید آن را از اینجا
دانلود کنید . پس از دانلود و نصب Postman، ما شروع به آزمایش برنامه خود می کنیم. برای انجام این کار، برنامه را باز کنید و یک درخواست جدید ایجاد کنید: 



خلاصه
تبریک می گویم! ما به اندازه کافی REST را پوشش داده ایم. حجم زیادی از مطالب وجود داشت، اما امیدوارم برای شما مفید بوده باشد:-
ما یاد گرفتیم که REST چیست.
-
ما در مورد چگونگی پیدایش REST یاد گرفتیم.
-
ما در مورد محدودیت ها و اصول پشت این سبک معماری صحبت کردیم:
- معماری مشتری-سرور
- بی تابعیت
- ذخیره سازی
- رابط یکنواخت
- لایه های
- کد درخواستی (اختیاری)
-
ما مزایای ارائه شده توسط REST را بررسی کردیم
-
ما به طور مفصل نحوه تعامل سرور و مشتری با یکدیگر از طریق پروتکل HTTP را بررسی کردیم.
-
ما نگاه دقیق تری به درخواست ها و پاسخ ها انداختیم. ما اجزای تشکیل دهنده آنها را تشریح کردیم.
-
در نهایت، با نوشتن برنامه کوچک RESTful خود با استفاده از Spring Boot، تجربه عملی به دست آوردیم. و ما حتی یاد گرفتیم که چگونه آن را با استفاده از Postman آزمایش کنیم.
مشق شب
موارد زیر را امتحان کنید:- طبق توضیحات بالا، پروژه Spring Boot خود را بسازید و همان منطق درس را پیاده سازی کنید. همه چیز را دقیقا تکرار کنید.
- برنامه را اجرا کنید.
- Postman (یا هر ابزار دیگری برای ارسال درخواست، به عنوان مثال، curl) را دانلود و پیکربندی کنید.
- درخواست های POST و GET را به همان روشی که در درس توضیح داده شد، آزمایش کنید.
- خودتان درخواست های PUT و DELETE را آزمایش کنید.
GO TO FULL VERSION