Ин қисми ниҳоии таҳлor REST мебошад. Дар қисмҳои қаблӣ:
Эҷоди лоиҳа
Дар ин бахш мо бо истифода аз Spring Boot як барномаи хурди RESTful эҷод мекунем. Замимаи мо амалиёти CRUD (Эҷод, Хондан, Навсозӣ, Нест кардан) -ро дар мизоҷ аз мисоли қисми охирини таҳлил амалӣ хоҳад кард. Аввалан, биёед барномаи нави Spring Boot-ро тавассути менюи File -> New -> Project созем... Дар равзанаи кушодашуда Spring Initializr-ро интихоб намуда Project SDK-ро муайян кунед: Тугмаи Next-ро пахш кунед. Дар равзанаи навбатӣ намуди лоиҳаи Maven-ро муайян кунед, Гурӯҳ ва Артефактро муайян кунед: Тугмаи Next-ро пахш кунед. Дар равзанаи навбатӣ, мо бояд ҷузъҳои Spring Framework-ро, ки барои лоиҳа заруранд, интихоб кунем. Веби баҳорӣ барои мо кофӣ хоҳад буд: Тугмаи Ояндаро пахш кунед. Баъдан, танҳо муайян кардани номи лоиҳа ва ҷойгиршавии он дар системаи файлӣ боқӣ мемонад: Тугмаи Finish -ро пахш кунед. Лоиҳа сохта шудааст, ҳоло мо метавонем сохтори онро бубинем: IDEA барои мо дескриптори густариши системаи Maven build - 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>
RestExampleApplication:
@SpringBootApplication
public class RestExampleApplication {
public static void main(String[] args) {
SpringApplication.run(RestExampleApplication.class, args);
}
}
Эҷоди функсияи REST
Замимаи мо мизоҷонро идора мекунад. Пас, аввалин чизе, ки мо бояд анҷом диҳем, эҷоди як ширкати муштарӣ аст. Ин синфи POJO хоҳад буд. Биёедmodel
дар дохor баста баста эҷод кунем com.javarush.lectures.rest_example
. Биёед дар дохor баста 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
, ки дар дохor он интерфейс эҷод мекунем 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>
. Калиди корт ID муштарӣ хоҳад буд ва арзиш худи муштарӣ хоҳад буд. Ин барои он анҷом дода шуд, ки мисолро бо хусусиятҳои кор бо базаи маълумот аз ҳад зиёд пур накунед. Аммо, дар оянда мо метавонем татбиқи дигари интерфейсро нависем, ки дар он пойгоҳи додаҳои воқеиро пайваст кардан мумкин аст. Дар баста 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;
}
}
Эзоҳ @Service
ба Баҳор мегӯяд, ки ин синф хидмат аст. Ин як навъи махсуси синф аст, ки дар он баъзе мантиқи тиҷоратии барнома амалӣ карда мешавад. Минбаъд, ба шарофати ин эзоҳ, Spring ба мо намунаи ин синфро дар ҷойҳое пешкаш мекунад, ки он бо истифода аз Injection Dependency лозим аст. Ҳоло вақти сохтани контроллер аст. Синфи махсусе, ки дар он мо мантиқи коркарди дархостҳои муштариро барои нуқтаҳои ниҳоӣ (URI) амалӣ месозем. Барои равшантар кардани он, мо ин синфро қисмҳо эҷод мекунем. Аввалан, биёед худи синфро эҷод кунем ва аз он вобастагӣ ҷорӣ кунем ClientService
:
@RestController
public class ClientController {
private final ClientService clientService;
@Autowired
public ClientController(ClientService clientService) {
this.clientService = clientService;
}
}
Биёед эзоҳҳоро равшан кунем: @RestController - ба Spring мегӯяд, ки ин синф контролери REST аст. Онхое. ин синф мантиқи коркарди дархостҳои муштариёнро амалӣ хоҳад кард @Autowired - ба Баҳор мегӯяд, ки вобастагӣ бояд дар ин ҷой ворид карда шавад. Мо интерфейсро ба конструктор мегузорем 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
. Дар дохor бадани метод, мо усули эҷодро дар хидмати қаблан сохташуда меномем ва ба он контролери муштарӣ, ки дар параметрҳо қабул шудааст, мегузарем. Сипас, мо ҳолати 201 Сохташударо тавассути эҷоди an objectи нав 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, ҳама an objectҳои POJO, инчунин коллексияи an objectҳои POJO, ки ҳамчун мақомоти ҷавобӣ баргардонида мешаванд, ба таври худкор ба JSON силсила карда мешаванд, агар тартиби дигаре мушаххас нашуда бошад. Ин ба мо хеле мувофик аст. Дар дохor усул, бо истифода аз хидмати мо, мо рӯйхати ҳамаи муштариёнро мегирем. Баъдан, агар рӯйхат холӣ ё холӣ набошад, мо ResponseEntity
бо истифода аз синф рӯйхати муштариён ва ҳолати HTTP 200 OK -ро бармегардонем. Дар акси ҳол, мо танҳо ҳолати HTTP-ро бармегардонем 404 ёфт нашуд. Минбаъд, мо қобorяти қабули муштариро аз рӯи ID-и ӯ татбиқ хоҳем кард:
@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
- параметри усул интиқол дода мешавад. Дар бадан мо an objectро Client
бо истифода аз хидмати худ қабул мекунем ва қабул мекунем id
. Ва он гоҳ, дар муқоиса бо рӯйхат, мо ҳолати 200 OK ва худи an objectро бармегардонем 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-ро коркард мекунад (annotation @PutMapping
) ва метод delete
дархостҳои DELETE-ро коркард мекунад (annotation 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);
}
}
Дар натиҷа сохтори лоиҳаи мо чунин менамояд:
Оғоз ва озмоиш
Барои иҷро кардани замимаи мо, танҳо методроmain
дар синф иҷро кунед RestExampleApplication
. Ва барои санҷидани хидматҳои веби RESTful, шумо бояд нармафзори навро зеркашӣ кунед) Гап дар он аст, ки дархостҳои GET аз браузери муқаррарӣ фиристодан хеле осон аст, аммо барои POST, PUT ва DELETE браузери муқаррарӣ кофӣ нест. Парво накунед: шумо метавонед Postman-ро барои фиристодани ҳама гуна дархостҳои HTTP истифода баред. Шумо метавонед онро аз ин ҷо зеркашӣ кунед . Пас аз зеркашӣ ва насб, мо озмоиши замимаи худро оғоз мекунем. Барои ин, барномаро кушоед ва дархости нав эҷод кунед: Тугмаи Навро дар кунҷи чапи боло пахш кунед. Баъдан, дархостро интихоб кунед: Баъдан, ба он ном диҳед ва онро захира кунед. Биёед ҳоло кӯшиш кунем, ки дархости POST-ро ба server фиристем ва муштарии аввалро эҷод кунем: Мо бо ин роҳ якчанд муштариро эҷод мекунем. Сипас, мо навъи дархостро ба GET иваз мекунем ва онро ба server мефиристем:
Натиҷаҳои умумӣ
Табрик мекунем: мо мавзӯи REST-ро фаро гирифтем. Ҳама маводҳо ҳаҷм буданд, аммо мо умедворем, ки он барои шумо муфид хоҳад буд:-
Мо фаҳмидем, ки REST чист.
-
Мо бо таърихи REST шинос шудем.
-
Мо дар бораи маҳдудиятҳо ва принсипҳои ин услуби меъморӣ сӯҳбат кардем:
- овардани меъморӣ ба модели муштарӣ-server;
- набудани шароит;
- кэш;
- яксонии интерфейс;
- қабатҳо;
- code оид ба дархост (маҳдудияти ихтиёрӣ).
-
Мо бартариҳоеро, ки REST таъмин мекунад, тафтиш кардем
-
Мо ба таври муфассал дида баромадем, ки чӣ гуна server ва муштарӣ бо истифода аз протоколи HTTP бо ҳамдигар ҳамкорӣ мекунанд.
-
Биёед ба дархостҳо ва посухҳо муфассалтар назар андозем. Компонентхои онхо чудо карда шуданд.
-
Ниҳоят, мо ба амалия гузаштем ва барномаи хурди RESTful-и худро дар Spring Boot навиштем. Ва мо ҳатто бо истифода аз барномаи Postman чӣ гуна санҷидани онро омӯхтем.
Вазифаи хонагӣ
Инҳоро санҷед:- Пас аз тавсифи дар боло тавсифшуда, лоиҳаи Spring Boot-и худро эҷод кунед ва ҳамон мантиқи дар лексияро дар он татбиқ кунед. Ҳама чизро 1 дар 1 такрор кунед.
- Онро оғоз кунед. ариза.
- Почтачин (ё ягон асбоби дигар барои фиристодани дархостҳо, ҳатто curl) -ро зеркашӣ ва насб кунед.
- Дархостҳои POST ва GET-ро ҳамон тавре, ки дар лексия тавсиф шудааст, санҷед.
- Дархостҳои PUT ва DELETE -ро худатон санҷед.
GO TO FULL VERSION