JavaRush /Java Blogu /Random-AZ /REST-ə ümumi baxış. Hissə 3: Spring Boot-da RESTful Servi...

REST-ə ümumi baxış. Hissə 3: Spring Boot-da RESTful Service yaradılması

Qrupda dərc edilmişdir
Bu REST təhlilinin son hissəsidir. Əvvəlki hissələrdə: REST-ə ümumi baxış.  3-cü hissə: Spring Boot-da RESTful Xidmətin yaradılması - 1

Layihənin yaradılması

Bu bölmədə Spring Boot-dan istifadə edərək kiçik RESTful tətbiqi yaradacağıq. Tətbiqimiz təhlilin son hissəsindəki nümunədən müştərilər üzərində CRUD (Yarat, Oxu, Yenilə, Sil) əməliyyatlarını həyata keçirəcək . Əvvəlcə File -> New -> Project menyusu vasitəsilə yeni Spring Boot proqramı yaradaq ... Açılan pəncərədə Spring Initializr seçin və Project SDK-nı təyin edin: REST-ə ümumi baxış.  3-cü hissə: Spring Boot-da RESTful Xidmətin yaradılması - 2Next düyməsini sıxın. Növbəti pəncərədə Maven layihə növünü göstərin, Qrupu və Artefaktı təyin edin: REST-ə ümumi baxış.  3-cü hissə: Spring Boot-da RESTful Service yaradılması - 3Next düyməsini basın. Növbəti pəncərədə layihə üçün lazım olan Spring Framework komponentlərini seçməliyik. Spring Web bizim üçün kifayət edəcək: REST-ə ümumi baxış.  3-cü hissə: Spring Boot-da RESTful Xidmətin yaradılması - 4Next düyməsini basın. Bundan sonra, layihənin adını və fayl sistemindəki yerini təyin etmək qalır: REST-ə ümumi baxış.  3-cü hissə: Spring Boot-da RESTful Xidmətin yaradılması - 5Finish düyməsini basın. Layihə yaradıldı, indi onun strukturunu görə bilərik: REST-ə ümumi baxış.  3-cü hissə: Spring Boot-da RESTful Service yaradılması - 6IDEA bizim üçün Maven qurma sisteminin yerləşdirmə deskriptorunu - pom.xml və əsas tətbiq sinfini yaratdı: RestExampleApplication. Budur onların kodu:
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 funksionallığının yaradılması

Tətbiqimiz müştəriləri idarə edir. Beləliklə, etməli olduğumuz ilk şey müştəri qurumu yaratmaqdır. Bu POJO sinfi olacaq. modelPaket daxilində paket yaradaq com.javarush.lectures.rest_example. Paket daxilində modelbir sinif yaradaq 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;
   }
}
Xidmət müştəri üzərində CRUD əməliyyatlarını həyata keçirəcək. Növbəti addım bu əməliyyatları həyata keçirəcək xidmətin yaradılmasıdır. Paketdə com.javarush.lectures.rest_examplebir paket yaradacağıq service, onun içərisində bir interfeys yaradacağıq ClientService. Budur şərhlərlə interfeys kodu:
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);
}
Sonra bu interfeysin tətbiqini yaratmalıyıq. İndi o, müştəri deposu kimi çıxış edəcək Map<Integer, Client>. Kart açarı müştəri identifikatoru, dəyər isə müştərinin özü olacaq. Bu, nümunəni verilənlər bazası ilə işləmək xüsusiyyətləri ilə çox yükləməmək üçün edildi. Bununla belə, gələcəkdə biz real verilənlər bazasını birləşdirməyin mümkün olacağı interfeysin başqa bir tətbiqini yaza biləcəyik. Paketdə serviceinterfeysin tətbiqini yaradacağıq 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;
   }
}
Annotasiya @ServiceBahara bu sinfin bir xidmət olduğunu bildirir. Bu, tətbiqin bəzi iş məntiqinin həyata keçirildiyi xüsusi bir sinif növüdür. Sonradan, bu annotasiya sayəsində Spring bizə Dependency Injection istifadə edərək lazım olan yerlərdə bu sinfin bir nümunəsini təqdim edəcəkdir. İndi nəzarətçi yaratmağın vaxtı gəldi. Son nöqtələr (URI) üçün müştəri sorğularını emal etmək üçün məntiqi tətbiq etdiyimiz xüsusi sinif. Daha aydın olması üçün bu sinfi hissə-hissə yaradacağıq. Əvvəlcə sinfin özünü yaradaq və ondan asılılıq təqdim edək ClientService:
@RestController
public class ClientController {

   private final ClientService clientService;

   @Autowired
   public ClientController(ClientService clientService) {
       this.clientService = clientService;
   }
}
Annotasiyaları aydınlaşdıraq: @RestController - Bahara bu sinfin REST nəzarətçisi olduğunu bildirir. Bunlar. bu sinif müştəri sorğularını emal etmək üçün məntiqi həyata keçirəcək @Autowired - Bahara deyir ki, bu yerə asılılıq yeridilməlidir. Biz interfeysi konstruktora keçirik ClientService. Biz bu xidmətin həyata keçirilməsini daha əvvəl annotasiya ilə qeyd etmişdik @Servicevə indi Spring bu tətbiqin nümunəsini nəzarətçi konstruktoruna ötürə biləcək. Sonra, CRUD əməliyyatlarını emal etmək üçün hər bir nəzarətçi metodunu addım-addım tətbiq edəcəyik. Yarat əməliyyatı ilə başlayaq. Bunun üçün bir üsul yazaq create:
@PostMapping(value = "/clients")
public ResponseEntity<?> create(@RequestBody Client client) {
   clientService.create(client);
   return new ResponseEntity<>(HttpStatus.CREATED);
}
Bu metoda nəzər salaq: @PostMapping(value = "/clients")- burada biz bu metodun /clients ünvanına POST sorğularını emal etdiyini nəzərdə tuturuq.Metod qaytarır ResponseEntity<?>. ResponseEntity- cavabların qaytarılması üçün xüsusi sinif. Bundan istifadə edərək daha sonra HTTP status kodunu müştəriyə qaytara bilərik. Metod bir parametr alır @RequestBody Client client, bu parametrin dəyəri sorğu orqanından əvəz olunur. Abstrakt bu barədə danışır @RequestBody. Metodun gövdəsinin daxilində biz əvvəllər yaradılmış xidmətdə yaratma metodunu çağırırıq və parametrlərdə qəbul edilmiş müştəri nəzarətçisinə ötürürük. ResponseEntitySonra yeni obyekt yaradaraq ona lazım olan enum dəyərini ötürməklə 201 Created statusunu qaytarırıq HttpStatus. Sonra əməliyyatı həyata keçiririk Read: Birincisi, bütün mövcud müştərilərin siyahısını əldə etmək əməliyyatını həyata keçiririk:
@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);
}
Təhlil etməyə başlayaq: @GetMapping(value = "/clients")- hər şey annotasiyaya bənzəyir @PostMapping, yalnız indi biz GET sorğularını emal edirik. Bu dəfə biz qayıdırıq ResponseEntity<List<Client>>, yalnız bu dəfə HTTP statusuna əlavə olaraq müştərilərin siyahısı olacaq cavab orqanını da qaytaracağıq. Spring REST kontrollerlərində bütün POJO obyektləri, eləcə də cavab orqanı kimi qaytarılan POJO obyektlərinin kolleksiyaları başqa cür göstərilmədiyi təqdirdə avtomatik olaraq JSON-da seriallaşdırılır. Bu bizə çox yaraşır. Metod daxilində xidmətimizdən istifadə edərək bütün müştərilərin siyahısını əldə edirik. Sonra, əgər siyahı boş və ya boş deyilsə, biz ResponseEntitysinifdən istifadə edərək müştərilərin siyahısını və HTTP statusunu 200 OK qaytarırıq. Əks halda, biz sadəcə HTTP statusunu qaytarırıq 404 Tapılmadı. Bundan sonra, müştərini şəxsiyyət vəsiqəsi ilə qəbul etmək imkanını həyata keçirəcəyik:
@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);
}
Yeni bir şey odur ki, indi yol dəyişənimiz var. URI-də müəyyən edilmiş dəyişən. value = "/clients/{id}". Bunu əyri mötərizələrdə göstərdik. Metod parametrlərində isə intannotasiyadan istifadə edərək onu dəyişən kimi qəbul edirik @PathVariable(name = "id"). Bu üsul formanın uri üçün sorğuları qəbul edəcək /clients/{id}, bunun əvəzinə {id}hər hansı bir ədədi dəyər ola bilər. Bu dəyər sonradan dəyişənə - metod parametrinə ötürülür int id. Bədəndə Clientxidmətimizdən istifadə edərək obyekti alırıq və qəbul edirik id. Və sonra, siyahıya bənzətməklə, sistemdə bununla bağlı müştəri yoxdursa , ya 200 OK statusunu və obyektin özünü Client, ya da sadəcə 404 Tapılmadı statusunu qaytarırıq. idİki əməliyyatı həyata keçirmək qalır - Yeniləmə və Sil. Bu üsullar üçün kod budur:
@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);
}
Bu üsullarda mahiyyətcə yeni heç nə yoxdur, ona görə də ətraflı təsviri atlayacağıq. Qeyd etməyə dəyər yeganə şey metodun updatePUT sorğularını (annotasiya @PutMapping) və metodun deleteDELETE sorğularını (annotasiya DeleteMapping) emal etməsidir. Budur tam nəzarətçi kodu:
@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);
   }
}
Nəticədə layihəmizin strukturu belə görünür: REST-ə ümumi baxış.  3-cü hissə: Spring Boot-da RESTful Xidmətin yaradılması - 7

Başlayın və sınaqdan keçirin

Tətbiqimizi işə salmaq üçün mainsinifdə metodu işə salmaq kifayətdir RestExampleApplication. Və RESTful veb xidmətlərini sınaqdan keçirmək üçün yeni proqram təminatı yükləməlisiniz) Fakt budur ki, GET sorğularını adi brauzerdən göndərmək olduqca asandır, lakin POST, PUT və DELETE üçün adi brauzer kifayət etmir. Narahat olmayın: istənilən HTTP sorğularını göndərmək üçün Postman istifadə edə bilərsiniz. Siz onu buradan yükləyə bilərsiniz . Yüklədikdən və quraşdırdıqdan sonra tətbiqimizi sınaqdan keçirməyə başlayırıq. Bunun üçün proqramı açın və yeni sorğu yaradın: REST-ə ümumi baxış.  3-cü hissə: Spring Boot-da RESTful Service yaradılması - 9Yuxarı sol küncdəki Yeni düyməsini sıxın. Sonra, Sorğu seçin: REST-ə ümumi baxış.  3-cü hissə: Spring Boot ilə RESTful Xidmətin yaradılması - 10Sonra, ona bir ad verin və yadda saxlayın. İndi serverə POST sorğusu göndərməyə və birinci müştəri yaratmağa çalışaq: REST-ə ümumi baxış.  3-cü hissə: Spring Boot-da RESTful Xidmətin yaradılması - 11Biz bu şəkildə bir neçə müştəri yaradırıq. Sonra sorğu növünü GET olaraq dəyişib serverə göndəririk: REST-ə ümumi baxış.  3-cü hissə: Spring Boot-da RESTful Service yaradılması - 12

Ümumi nəticələr

Təbrik edirik: REST mövzusunu kifayət qədər əhatə etdik. Bütün materiallar həcmli oldu, amma ümid edirik ki, sizin üçün faydalı olacaq:
  1. REST-in nə olduğunu öyrəndik.

  2. REST-in tarixi ilə tanış olduq.

  3. Bu memarlıq üslubunun məhdudiyyətləri və prinsipləri haqqında danışdıq:

    • arxitekturanın müştəri-server modelinə gətirilməsi;
    • vəziyyətin olmaması;
    • keşləmə;
    • interfeysin vahidliyi;
    • təbəqələr;
    • tələb üzrə kod (isteğe bağlı məhdudiyyət).
  4. REST-in təmin etdiyi üstünlükləri araşdırdıq

  5. HTTP protokolundan istifadə edərək server və müştərinin bir-biri ilə necə qarşılıqlı əlaqədə olduğunu ətraflı araşdırdıq.

  6. Gəlin sorğu və cavablara daha yaxından nəzər salaq. Onların komponentləri sökülüb.

  7. Nəhayət, təcrübəyə keçdik və Spring Boot-da öz kiçik RESTful tətbiqimizi yazdıq. Və hətta Postman proqramından istifadə edərək onu sınamağı öyrəndik.

vay. Həcmli olduğu ortaya çıxdı, amma buna baxmayaraq ev tapşırığı olaraq ediləcək bir şey var.

Ev tapşırığı

Aşağıdakıları sınayın:
  1. Yuxarıdakı təsvirdən sonra öz Spring Boot layihənizi yaradın və orada mühazirədəki kimi məntiqi tətbiq edin. Hər şeyi 1-də 1-də təkrarlayın.
  2. Onu işə salın. tətbiq.
  3. Postman (və ya sorğu göndərmək üçün hər hansı digər alət, hətta qıvrım) yükləyin və quraşdırın.
  4. POST və GET sorğularını mühazirədə təsvir olunduğu kimi sınaqdan keçirin.
  5. PUT və DELETE sorğularını özünüz yoxlayın.
1-ci hissə: REST nədir 2-ci hissə: Müştəri və server arasında əlaqə
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION