Bu REST tahlilining yakuniy qismi. Oldingi qismlarda:
Loyiha yaratish
Ushbu bo'limda biz Spring Boot yordamida kichik RESTful ilovasini yaratamiz. Bizning ilovamiz tahlilning oxirgi qismidagi misoldan mijozlarga CRUD (Yaratish, o'qish, yangilash, o'chirish) operatsiyalarini amalga oshiradi . Avval File -> New -> Project menyusi orqali yangi Spring Boot ilovasini yaratamiz ... Ochilgan oynada Spring Initializr ni tanlaymiz va Project SDK ni belgilaymiz: Keyingi tugmasini bosing. Keyingi oynada Maven loyihasi turini belgilang, Guruh va Artifaktni belgilang: Keyingi tugmasini bosing. Keyingi oynada biz loyiha uchun zarur bo'lgan Spring Framework komponentlarini tanlashimiz kerak. Spring Web biz uchun etarli bo'ladi: Keyingi tugmasini bosing. Keyinchalik, faqat loyiha nomini va uning fayl tizimidagi o'rnini ko'rsatish qoladi: Finish tugmasini bosing. Loyiha yaratildi, endi biz uning tuzilishini ko'rishimiz mumkin: IDEA biz uchun Maven qurish tizimini joylashtirish deskriptorini - pom.xml va asosiy dastur sinfini yaratdi:RestExampleApplication
. Mana ularning kodi:
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>
RestExampleApplication:
@SpringBootApplication
public class RestExampleApplication {
public static void main(String[] args) {
SpringApplication.run(RestExampleApplication.class, args);
}
}
REST funksiyasini yaratish
Bizning ilovamiz mijozlarni boshqaradi. Shunday qilib, biz qilishimiz kerak bo'lgan birinchi narsa - mijoz sub'ektini yaratish. Bu POJO sinfi bo'ladi.model
Keling , paket ichida paket yarataylik com.javarush.lectures.rest_example
. Paket ichida model
sinf yaratamiz 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;
}
}
Xizmat mijozda CRUD operatsiyalarini amalga oshiradi. Keyingi qadam bu operatsiyalarni amalga oshiradigan xizmatni yaratishdir. Paketda com.javarush.lectures.rest_example
biz paket yaratamiz service
, uning ichida interfeys yaratamiz ClientService
. Mana sharhlar bilan interfeys kodi:
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);
}
Keyinchalik biz ushbu interfeysning amalga oshirilishini yaratishimiz kerak. Endi u mijoz ombori sifatida ishlaydi Map<Integer, Client>
. Karta kaliti mijoz identifikatori bo'ladi va qiymat mijozning o'zi bo'ladi. Bu ma'lumotlar bazasi bilan ishlashning o'ziga xos xususiyatlari bilan misolni ortiqcha yuklamaslik uchun qilingan. Biroq, kelajakda biz haqiqiy ma'lumotlar bazasini ulash mumkin bo'lgan interfeysning yana bir ilovasini yozishimiz mumkin. Paketda service
biz interfeysning amalga oshirilishini yaratamiz 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;
}
}
Izoh @Service
Bahorga bu sinf xizmat ekanligini aytadi. Bu ilovaning ba'zi biznes mantiqlari amalga oshiriladigan maxsus sinf turi. Keyinchalik, ushbu izoh tufayli, Spring bizga Dependency Injection yordamida kerak bo'lgan joylarda ushbu sinfning namunasini taqdim etadi. Endi boshqaruvchini yaratish vaqti keldi. Biz so'nggi nuqtalar (URI) uchun mijoz so'rovlarini qayta ishlash mantiqini amalga oshiradigan maxsus sinf. Aniqroq qilish uchun biz ushbu sinfni qismlarga ajratamiz. Birinchidan, sinfning o'zini yaratamiz va unga bog'liqlikni kiritamiz ClientService
:
@RestController
public class ClientController {
private final ClientService clientService;
@Autowired
public ClientController(ClientService clientService) {
this.clientService = clientService;
}
}
Izohlarga aniqlik kiritamiz: @RestController - Springga bu sinf REST kontrolleri ekanligini aytadi. Bular. bu sinf mijoz so'rovlarini qayta ishlash mantiqini amalga oshiradi @Autowired - Bahorga bu joyga qaramlikni kiritish kerakligini aytadi. Biz interfeysni konstruktorga o'tkazamiz ClientService
. Biz ushbu xizmatni amalga oshirishni avvalroq izoh bilan belgilagan edik @Service
va endi Spring ushbu amalga oshirishning namunasini kontroller konstruktoriga o'tkazishi mumkin bo'ladi. Keyinchalik, CRUD operatsiyalarini qayta ishlash uchun har bir kontroller usulini bosqichma-bosqich amalga oshiramiz. Yaratish operatsiyasidan boshlaylik. Buning uchun usulni yozamiz create
:
@PostMapping(value = "/clients")
public ResponseEntity<?> create(@RequestBody Client client) {
clientService.create(client);
return new ResponseEntity<>(HttpStatus.CREATED);
}
Keling, ushbu usulni ko'rib chiqaylik: @PostMapping(value = "/clients")
- bu erda biz ushbu usul POST so'rovlarini /clients manziliga qayta ishlashni nazarda tutamiz.Usul qaytaradi ResponseEntity<?>
. ResponseEntity
- javoblarni qaytarish uchun maxsus sinf. Undan foydalanib, HTTP holat kodini keyinchalik mijozga qaytarishimiz mumkin. Usul parametrni oladi @RequestBody Client client
, bu parametrning qiymati so'rov tanasidan almashtiriladi. Abstrakt bu haqda gapiradi @RequestBody
. Usul tanasi ichida biz avval yaratilgan xizmatda yaratish usulini chaqiramiz va parametrlarda qabul qilingan mijoz nazoratchisiga o'tamiz. ResponseEntity
Keyin yangi ob'ekt yaratish va unga kerakli enum qiymatini o'tkazish orqali 201 Created holatini qaytaramiz HttpStatus
. Keyinchalik, biz operatsiyani amalga oshiramiz Read
: Birinchidan, biz barcha mavjud mijozlar ro'yxatini olish operatsiyasini amalga oshiramiz:
@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);
}
Tahlilni boshlaymiz: @GetMapping(value = "/clients")
- hamma narsa izohga o'xshaydi @PostMapping
, faqat hozir biz GET so'rovlarini qayta ishlaymiz. Bu safar biz qaytamiz ResponseEntity<List<Client>>
, faqat bu safar, HTTP holatiga qo'shimcha ravishda, mijozlar ro'yxati bo'lgan javob organini ham qaytaramiz. Spring REST kontrollerlarida barcha POJO ob'ektlari, shuningdek javob organlari sifatida qaytariladigan POJO ob'ektlari to'plamlari, agar boshqacha ko'rsatilmagan bo'lsa, avtomatik ravishda JSONga seriyalashtiriladi. Bu bizga juda mos keladi. Usul ichida bizning xizmatimizdan foydalanib, biz barcha mijozlarning ro'yxatini olamiz. Keyinchalik, agar ro'yxat null yoki bo'sh bo'lmasa, biz ResponseEntity
sinfdan foydalanib, mijozlar ro'yxatini va HTTP holatini 200 OK qaytaramiz. Aks holda, biz shunchaki HTTP holatini qaytaramiz 404 topilmadi. Keyinchalik, mijozni uning identifikatori bo'yicha qabul qilish imkoniyatini amalga oshiramiz:
@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);
}
Yangi narsa shundaki, bizda endi yo'l o'zgaruvchisi mavjud. URI da aniqlangan o'zgaruvchi. value = "/clients/{id}"
. Biz buni jingalak qavslarda ko'rsatdik. Va usul parametrlarida biz int
izoh yordamida uni o'zgaruvchi sifatida qabul qilamiz @PathVariable(name = "id")
. Bu usul formaning uri so'rovlarini qabul qiladi /clients/{id}
, buning o'rniga {id}
har qanday raqamli qiymat bo'lishi mumkin. Bu qiymat keyinchalik o'zgaruvchiga int id
- usul parametriga o'tkaziladi. Tanada biz ob'ektni Client
xizmatimizdan foydalanib qabul qilamiz va qabul qilamiz id
. Va keyin, ro'yxatga o'xshatib, biz 200 OK holatini va ob'ektning o'zini Client
yoki oddiygina 404 topilmadi holatini qaytaramiz, agar id
tizimda bunday mijoz bo'lmasa. Ikkita operatsiyani bajarish qoladi - Yangilash va O'chirish. Mana bu usullar uchun kod:
@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);
}
Ushbu usullarda yangi narsa yo'q, shuning uchun biz batafsil tavsifni o'tkazib yuboramiz. Shuni ta'kidlash kerakki, usul update
PUT so'rovlarini qayta ishlaydi (annotatsiya @PutMapping
) va usul delete
DELETE so'rovlarini qayta ishlaydi (annotatsiya DeleteMapping
). Mana to'liq kontroller kodi:
@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);
}
}
Natijada, loyihamizning tuzilishi quyidagicha ko'rinadi:
Ishga tushirish va sinovdan o'tkazish
Ilovamizni ishga tushirish uchunmain
sinfdagi usulni ishga tushirish kifoya RestExampleApplication
. Va RESTful veb-xizmatlarini sinab ko'rish uchun siz yangi dasturiy ta'minotni yuklab olishingiz kerak) Gap shundaki, GET so'rovlarini oddiy brauzerdan yuborish juda oson, ammo POST, PUT va DELETE uchun oddiy brauzer etarli emas. Xavotir olmang: har qanday HTTP so'rovlarini yuborish uchun Postman dan foydalanishingiz mumkin. Bu yerdan yuklab olishingiz mumkin . Yuklab olish va o'rnatishdan so'ng biz dasturimizni sinab ko'rishni boshlaymiz. Buning uchun dasturni oching va yangi so'rov yarating: Yuqori chap burchakdagi Yangi tugmasini bosing. Keyin, So'rovni tanlang: Keyin, unga nom bering va uni saqlang. Keling, serverga POST so'rovini yuborishga harakat qilaylik va birinchi mijozni yaratamiz: Biz shu tarzda bir nechta mijozlarni yaratamiz. Keyin so'rov turini GET ga o'zgartiramiz va uni serverga yuboramiz:
Umumiy natijalar
Tabriklaymiz: biz REST mavzusini to'liq qamrab oldik. Barcha materiallar hajmli bo'lib chiqdi, ammo bu siz uchun foydali bo'ladi deb umid qilamiz:-
Biz REST nima ekanligini bilib oldik.
-
Biz REST tarixi bilan tanishdik.
-
Biz ushbu me'moriy uslubning cheklovlari va tamoyillari haqida gaplashdik:
- arxitekturani mijoz-server modeliga olib kelish;
- holatning yo'qligi;
- keshlash;
- interfeysning bir xilligi;
- qatlamlar;
- talab bo'yicha kod (ixtiyoriy cheklash).
-
Biz REST taqdim etgan afzalliklarni ko'rib chiqdik
-
Biz HTTP protokoli yordamida server va mijozning bir-birlari bilan qanday o'zaro aloqalarini batafsil ko'rib chiqdik.
-
Keling, so'rovlar va javoblarni batafsil ko'rib chiqaylik. Ularning tarkibiy qismlari demontaj qilingan.
-
Nihoyat, biz amaliyotga o'tdik va Spring Boot-da o'zimizning RESTful dasturimizni yozdik. Va biz hatto Postman dasturi yordamida uni qanday sinab ko'rishni o'rgandik.
Uy vazifasi
Quyidagilarni sinab ko'ring:- Yuqoridagi tavsifdan so'ng, o'zingizning Spring Boot loyihangizni yarating va unda ma'ruzadagi kabi mantiqni amalga oshiring. Hammasini 1 dan 1 marta takrorlang.
- Uni ishga tushiring. ilova.
- Yuklab oling va sozlang Postman (yoki so'rovlarni yuborish uchun boshqa vosita, hatto curl).
- POST va GET so'rovlarini ma'ruzada ko'rsatilgan tarzda sinab ko'ring.
- PUT va DELETE so‘rovlarini o‘zingiz sinab ko‘ring.
GO TO FULL VERSION