Buka pelajaran "Membuat Klien REST di Musim Semi"

Dan lagi, hari baik! Segera, kami akan memulai pelatihan untuk grup berikutnya, "Developer on the Spring Framework" , sehubungan dengan kami mengadakan pelajaran terbuka, yang telah menjadi tradisi untuk mengantisipasi peluncuran. Di webinar ini, kami berbicara tentang mengembangkan klien REST menggunakan Spring, dan juga belajar secara rinci tentang teknologi seperti Spring Cache, Spring Retry dan Hystrix.

Dosen: Yuri Dvorzhetsky - pelatih di Luxoft Training Center, pengembang utama, kandidat ilmu fisika dan matematika.

Webinar dihadiri oleh audiens yang sama sekali berbeda, mengevaluasi pengetahuan mereka tentang Spring dalam 0-6 poin pada skala 10 poin, namun, dilihat dari ulasannya, pelajaran terbuka tampaknya berguna bahkan untuk pengguna yang berpengalaman.



Beberapa kata tentang Spring 5

Seperti yang Anda ketahui, Spring Framework adalah kerangka kerja universal dan cukup populer untuk platform Java. Pegas terdiri dari banyak sub-proyek atau modul, yang memungkinkan Anda untuk menyelesaikan banyak masalah. Bahkan, ini adalah kumpulan besar "kerangka kerja dalam kerangka", misalnya, hanya beberapa dari mereka:

  • Spring IoC + AOP = Konteks,
  • Spring JDBC,
  • ORM musim semi,
  • Data Pegas (ini adalah seluruh rangkaian proyek),
  • Spring MVC, Spring WebFlux,
  • Keamanan musim semi
  • Spring Cloud (ini adalah satu set sub-proyek yang bahkan lebih besar)
  • Batch musim semi,
  • Boot musim semi.


Spring menggantikan pemrograman dengan beberapa tugas untuk konfigurasi, tetapi mengonfigurasi terkadang berubah menjadi mimpi buruk. Untuk membuat aplikasi tingkat produksi dengan cepat, mereka menggunakan Spring Boot . Ini adalah kerangka kerja khusus yang berisi serangkaian starter ('starter'), yang menyederhanakan konfigurasi kerangka Spring dan teknologi lainnya.

Untuk menunjukkan beberapa fitur Spring, tema situs pemblokiran adalah sempurna, karena sekarang modis)). Jika Anda ingin berpartisipasi aktif dalam pelajaran dan latihan, disarankan untuk mengunduh repositori dengan kode server yang disarankan guru. Kami menggunakan perintah berikut:

git clone git@github.com:ydvorzhetskiy/sb-server.git

Selanjutnya, jalankan saja, misalnya, seperti ini:

mvnw spring-boot:run

Prestasi terbesar dari Spring Boot adalah kemampuan untuk memulai server dengan hanya menjalankan kelas Utama di IntelliJ IDEA.

File BlockedSite.java berisi kode sumber kami:

 package ru.otus.demoserver.domain; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; @Entity public class BlockedSite { @Id @GeneratedValue private int id; private String url; 


Dan di sini adalah isi dari kontroler BlockedSitesController.java:

 package ru.otus.demoserver.rest; @RestController public class BlockedSitesController { private final Logger logger = LoggerFactory.getLogger(BlockedSitesController.class); private final BlockedSitesRepository repository; public BlockedSitesController(BlockedSitesRepository repository) { this.repository = repository; } @GetMapping("/blocked-sites") public List<BlockedSite> blockedSites() { logger.info("Request has been performed"); return repository.findAll(); } } 



Perhatikan juga basis data bersarang di 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 http://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.1.2.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>ru.otus</groupId> <artifactId>demo-server</artifactId> <version>0.0.1-SNAPSHOT</version> <url>demo-server</url> <description>Demo project for Spring Boot</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-data-jpa</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> 

Sekarang, dengan cara yang sederhana dan bersahaja, kami menyimpan dua situs yang diblokir (DemoServerApplication.java) ke dalam basis data kami melalui repositori:

 package ru.otus.demoserver; @SpringBootApplication public class DemoServerApplication { public static void main(String[] args) { ApplicationContext ctx = SpringApplication.run(DemoServerApplication.class, args); BlockedSitesRepository repository = ctx.getBean(BlockedSitesRepository.class); repository.save(new BlockedSite("https://telegram.org/")); repository.save(new BlockedSite("https://azure.microsoft.com/")); } } 

Tetap memulai server menggunakan Spring Boot dan membuka URL yang sesuai pada host lokal (localhost:8080/blocked-sites) . Pada saat yang sama, server kami akan mengembalikan kepada kami daftar situs yang kami blokir, yaitu situs-situs yang kami tambahkan melalui database.

Nah, saatnya untuk menulis klien ke server ini. Tetapi sebelum beralih ke ini, Anda perlu mengingat sesuatu.

Retret teoretis

Mari kita daftar beberapa metode HTTP (kata kerja):

  • DAPATKAN - mendapatkan entitas atau daftar;
  • POST - pembuatan entitas;
  • PUT - ubah entitas;
  • PATCH - perubahan entitas (RFC -...);
  • HAPUS - hapus entitas;
  • KEPALA, PILIHAN - metode β€œrumit” untuk mendukung protokol HTTP dan layanan REST secara umum;
  • TRACE adalah metode usang yang tidak digunakan.

Seseorang tidak dapat tidak mengingat properti penting seperti idempotensi . Secara sederhana, tidak peduli berapa kali Anda menerapkan operasi, hasilnya akan sama seperti jika Anda hanya menerapkannya sekali. Misalnya, Anda menyapa seorang pria di pagi hari, mengatakan "Halo!" Akibatnya, teman Anda masuk ke status "halo" :-). Dan jika Anda mengatakan "Halo!" Kepadanya beberapa kali di siang hari, tidak ada yang akan berubah, dia akan tetap dalam kondisi yang sama.

Sekarang, mari kita pikirkan tentang metode HTTP mana di atas yang idempoten? Tentu saja, dipahami bahwa Anda mengamati semantik. Jika Anda tidak tahu, maka guru akan memberi tahu Anda lebih banyak tentang ini, mulai dari menit ke-26 video.

SISA

Untuk menulis pengontrol REST, Anda perlu mengingat apa itu REST:

  • REST - Transfer Negara Representatif;
  • Ini adalah gaya arsitektur, bukan standar;
  • itu sebenarnya adalah seperangkat prinsip-batasan;
  • REST sudah lama sekali, tetapi istilah itu muncul relatif baru-baru ini;
  • Aplikasi web bergaya REST disebut RESTful, API-nya dalam hal ini adalah RESTful API (antonimnya Stateful);
  • REST sekarang disebut apa pun yang mereka inginkan ...

Pertama, jika kita berbicara tentang interaksi dalam bentuk client-server, maka itu perlu dibangun dalam bentuk permintaan-respons. Ya, interaksi tidak selalu dibangun dengan cara ini, tetapi sekarang interaksi ini sangat umum, dan untuk aplikasi web hal lain terlihat sangat aneh. Tapi, misalnya, soket web - ini bukan REST.

Kedua, batasan paling penting dalam REST adalah kurangnya status klien di server. Diasumsikan bahwa klien selalu melewati keadaan yang diperlukan ke server dengan setiap permintaan, yaitu keadaan disimpan di sisi klien, dan tidak ada sesi di server.

Bagaimana cara menulis klien di Spring

Untuk melanjutkan, pertimbangkan dan jalankan klien (gunakan tautan ke repositori):

 git clone git@github.com:ydvorzhetskiy/sb-client.git 

 mvnw spring-boot:run 

Ini adalah aplikasi klien dan konsol yang sudah ditulis, bukan server web.

Kami melihat dependensi:

 <?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 http://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.1.2.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>ru.otus</groupId> <artifactId>demo-client</artifactId> <version>0.0.1-SNAPSHOT</version> <url>demo-client</url> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <!--   RestTemplate,    - --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>5.1.4.RELEASE</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.9.8</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.9.8</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.8</version> </dependency> <!-- Cache --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <!-- Retry --> <dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> </dependency> <!-- Hystrix --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> <version>2.0.2.RELEASE</version> </dependency> <dependency> <groupId>com.netflix.hystrix</groupId> <artifactId>hystrix-javanica</artifactId> <version>1.5.12</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> 

Klien memiliki konfigurasi:

1. RestTemplateConfig.java

 package ru.otus.democlient.config; @Configuration public class RestTemplateConfig { @Bean public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) { return restTemplateBuilder .setConnectTimeout(Duration.ofSeconds(2)) .setReadTimeout(Duration.ofSeconds(3)) .build(); } 

2. CacheConfig.java

 package ru.otus.democlient.config; @Configuration public class CacheConfig { @Bean public CacheManager cacheManager() { return new ConcurrentMapCacheManager("sites"); } } 

Dan di sini adalah isi dari file SiteServiceRest.java:

 package ru.otus.democlient.service; import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; import org.springframework.beans.factory.annotation.Value; import org.springframework.cache.annotation.Cacheable; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpMethod; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import java.util.Collections; import java.util.List; @Service public class SiteServiceRest implements SiteService { private final RestTemplate restTemplate; private final String serverUrl; public SiteServiceRest( RestTemplate restTemplate, @Value("${application.server.url}") String serverUrl ) { this.restTemplate = restTemplate; this.serverUrl = serverUrl; } @Override public List<SiteInfo> findAllBlockedSites() { return restTemplate.exchange( serverUrl + "/blocked-sites", HttpMethod.GET, null, new ParameterizedTypeReference<List<SiteInfo>>() { } ).getBody(); } public List<SiteInfo> getDefaultSites() { return Collections.singletonList(new SiteInfo() {{ setUrl("http://vk.com/"); }}); } } 

Ringkas sedikit:

  1. Permintaan dilakukan melalui RestTemplate.
  2. RestTemplate dapat dikustomisasi, dan ini adalah kacang biasa.
  3. Jackson digunakan untuk memetakan JSON menjadi objek.
  4. Berikutnya - hanya penerbangan mewah Anda (detail tentang peluncuran klien ada di video).

Kolega, webinar itu ternyata sangat informatif, oleh karena itu, agar tidak ketinggalan apa pun, lebih baik untuk menontonnya secara keseluruhan. Anda akan mencoba API nyata "dalam pertempuran", menambahkan @Cacheable ke layanan, bekerja dengan Spring Retry, belajar tentang Hystrix dan banyak lagi. Kami juga mengundang Anda ke Spring Open Day , yang akan segera diadakan.

Dan, seperti biasa, kami menunggu komentar Anda tentang pelajaran terbuka yang lalu!

Source: https://habr.com/ru/post/id440046/


All Articles