Pengenalan HATEOAS Musim Semi

REST Teratas

Saya baru sahaja mengumumkan kursus Learn Spring yang baru , yang berfokus pada asas-asas Spring 5 dan Spring Boot 2:

>> SEMAK KURSUS

1. Gambaran keseluruhan

Artikel ini menerangkan proses membuat perkhidmatan web REST yang didorong oleh hypermedia menggunakan projek Spring HATEOAS.

2. Musim bunga-HATEOAS

Projek Spring HATEOAS adalah perpustakaan API yang dapat kita gunakan untuk membuat representasi REST dengan mudah yang mengikuti prinsip HATEOAS (Hypertext sebagai Engine of Application State).

Secara umum, prinsip ini menyiratkan bahawa API harus memandu klien melalui aplikasi dengan mengembalikan maklumat yang relevan mengenai langkah-langkah yang mungkin berikutnya, bersama dengan setiap respons.

Dalam artikel ini, kita akan membina contoh menggunakan Spring HATEOAS dengan tujuan untuk melepaskan pelanggan dan pelayan, dan secara teorinya membenarkan API mengubah skema URI tanpa mematahkan klien.

3. Persiapan

Pertama, mari tambah pergantungan Spring HATEOAS:

 org.springframework.boot spring-boot-starter-hateoas 2.1.4.RELEASE 

Sekiranya kami tidak menggunakan Spring Boot, kami boleh menambahkan perpustakaan berikut ke projek kami:

 org.springframework.hateoas spring-hateoas 0.25.1.RELEASE   org.springframework.plugin spring-plugin-core 1.2.0.RELEASE 

Seperti biasa, kita dapat mencari versi terbaru HATEOAS starter, spring-hateoas dan spring-plugin-core dependencies di Maven Central.

Seterusnya, kami mempunyai sumber Pelanggan tanpa sokongan Spring HATEOAS:

public class Customer { private String customerId; private String customerName; private String companyName; // standard getters and setters } 

Dan kami mempunyai kelas pengawal tanpa sokongan Spring HATEOAS:

@RestController @RequestMapping(value = "/customers") public class CustomerController { @Autowired private CustomerService customerService; @GetMapping("/{customerId}") public Customer getCustomerById(@PathVariable String customerId) { return customerService.getCustomerDetail(customerId); } } 

Akhirnya, perwakilan sumber Pelanggan :

{ "customerId": "10A", "customerName": "Jane", "customerCompany": "ABC Company" } 

4. Menambah Sokongan HATEOAS

Dalam projek Spring HATEOAS, kita tidak perlu mencari konteks Servlet atau menggabungkan jalur pemboleh ubah ke URI asas.

Sebaliknya, Spring HATEOAS menawarkan tiga abstraksi untuk membuat URI - RepresentationModel, Link, dan WebMvcLinkBuilder . Kita boleh menggunakannya untuk membuat metadata dan mengaitkannya dengan perwakilan sumber.

4.1. Menambah Sokongan Hypermedia ke Sumber

Projek ini menyediakan kelas asas yang disebut RepresentationModel untuk diwarisi ketika membuat perwakilan sumber:

public class Customer extends RepresentationModel { private String customerId; private String customerName; private String companyName; // standard getters and setters } 

The Pelanggan sumber bermula dari RepresentationModel kelas untuk mewarisi add () kaedah . Oleh itu, setelah kita membuat pautan, kita dapat dengan mudah menetapkan nilai itu ke perwakilan sumber tanpa menambahkan medan baru padanya.

4.2. Membuat Pautan

Spring HATEOAS menyediakan objek Pautan untuk menyimpan metadata (lokasi atau URI sumber).

Pertama, kami akan membuat pautan mudah secara manual:

Link link = new Link("//localhost:8080/spring-security-rest/api/customers/10A"); 

The Link objek berikut yang Atom sintaks link dan terdiri daripada rel yang mengenal pasti berhubung dengan sumber dan href atribut yang link itu sendiri.

Inilah rupa sumber Pelanggan sekarang kerana ia mengandungi pautan baru:

{ "customerId": "10A", "customerName": "Jane", "customerCompany": "ABC Company", "_links":{ "self":{ "href":"//localhost:8080/spring-security-rest/api/customers/10A" } } } 

URI yang dikaitkan dengan tindak balas layak sebagai pautan diri . Semantik hubungan diri jelas - ia hanyalah lokasi kanonik yang boleh diakses sumbernya.

4.3. Membuat Pautan yang Lebih Baik

Satu lagi abstraksi yang sangat penting yang ditawarkan oleh perpustakaan adalah yang WebMvcLinkBuilder - yang memudahkan URI membina dengan mengelakkan berkod keras pautan.

Coretan berikut menunjukkan membina pautan diri pelanggan menggunakan kelas WebMvcLinkBuilder :

linkTo(CustomerController.class).slash(customer.getCustomerId()).withSelfRel(); 

Mari kita lihat:

  • kaedah linkTo () memeriksa kelas pengawal dan memperoleh pemetaan akarnya
  • kaedah slash () menambah nilai customerId sebagai pemboleh ubah laluan pautan
  • akhirnya, withSelfMethod () melayakkan hubungan sebagai pautan diri

5. Perhubungan

Pada bahagian sebelumnya, kami telah menunjukkan hubungan merujuk diri. Walau bagaimanapun, sistem yang lebih kompleks mungkin melibatkan hubungan lain juga.

Contohnya, pelanggan boleh mempunyai hubungan dengan pesanan. Mari kita model kelas Order sebagai sumber juga:

public class Order extends RepresentationModel { private String orderId; private double price; private int quantity; // standard getters and setters } 

Pada tahap ini, kita dapat memperluas CustomerController dengan kaedah yang mengembalikan semua pesanan pelanggan tertentu:

@GetMapping(value = "/{customerId}/orders", produces = { "application/hal+json" }) public CollectionModel getOrdersForCustomer(@PathVariable final String customerId) { List orders = orderService.getAllOrdersForCustomer(customerId); for (final Order order : orders) { Link selfLink = linkTo(methodOn(CustomerController.class) .getOrderById(customerId, order.getOrderId())).withSelfRel(); order.add(selfLink); } Link link = linkTo(methodOn(CustomerController.class) .getOrdersForCustomer(customerId)).withSelfRel(); CollectionModel result = new CollectionModel(orders, link); return result; } 

Kaedah kami mengembalikan objek CollectionModel untuk mematuhi jenis pengembalian HAL, serta pautan "_self" untuk setiap pesanan dan senarai penuh.

Perkara penting yang perlu diperhatikan di sini adalah bahawa hyperlink untuk pesanan pelanggan bergantung pada pemetaan kaedah getOrdersForCustomer () . Kami akan merujuk jenis pautan ini sebagai pautan kaedah dan menunjukkan bagaimana WebMvcLinkBuilder dapat membantu dalam pembuatannya.

6. Pautan ke Kaedah Pengawal

The WebMvcLinkBuilder menawarkan sokongan yang kaya untuk Pengawal Spring MVC. Contoh rancangan berikut bagaimana untuk membina HATEOAS hiperpautan berdasarkan getOrdersForCustomer () kaedah yang CustomerController kelas:

Link ordersLink = linkTo(methodOn(CustomerController.class) .getOrdersForCustomer(customerId)).withRel("allOrders"); 

The methodOn () mendapat pemetaan kaedah dengan membuat dummy doa kaedah sasaran pada pengawal proksi dan menetapkan IDpelanggan sebagai pembolehubah jalan daripada URI.

7. Spring HATEOAS dalam Aksi

Mari letakkan pautan kendiri dan pautan kaedah bersama-sama dalam kaedah getAllCustomers () :

@GetMapping(produces = { "application/hal+json" }) public CollectionModel getAllCustomers() { List allCustomers = customerService.allCustomers(); for (Customer customer : allCustomers) { String customerId = customer.getCustomerId(); Link selfLink = linkTo(CustomerController.class).slash(customerId).withSelfRel(); customer.add(selfLink); if (orderService.getAllOrdersForCustomer(customerId).size() > 0) { Link ordersLink = linkTo(methodOn(CustomerController.class) .getOrdersForCustomer(customerId)).withRel("allOrders"); customer.add(ordersLink); } } Link link = linkTo(CustomerController.class).withSelfRel(); CollectionModel result = new CollectionModel(allCustomers, link); return result; }

Seterusnya, mari kita gunakan kaedah getAllCustomers () :

curl //localhost:8080/spring-security-rest/api/customers 

Dan periksa hasilnya:

{ "_embedded": { "customerList": [{ "customerId": "10A", "customerName": "Jane", "companyName": "ABC Company", "_links": { "self": { "href": "//localhost:8080/spring-security-rest/api/customers/10A" }, "allOrders": { "href": "//localhost:8080/spring-security-rest/api/customers/10A/orders" } } },{ "customerId": "20B", "customerName": "Bob", "companyName": "XYZ Company", "_links": { "self": { "href": "//localhost:8080/spring-security-rest/api/customers/20B" }, "allOrders": { "href": "//localhost:8080/spring-security-rest/api/customers/20B/orders" } } },{ "customerId": "30C", "customerName": "Tim", "companyName": "CKV Company", "_links": { "self": { "href": "//localhost:8080/spring-security-rest/api/customers/30C" } } }] }, "_links": { "self": { "href": "//localhost:8080/spring-security-rest/api/customers" } } }

Dalam setiap perwakilan sumber, terdapat pautan diri dan pautan allOrders untuk mengekstrak semua pesanan pelanggan. Sekiranya pelanggan tidak mempunyai pesanan, maka pautan untuk pesanan tidak akan muncul.

Contoh ini menunjukkan bagaimana Spring HATEOAS memupuk kebolehtemuan API dalam perkhidmatan web yang lain. Sekiranya pautan itu ada, pelanggan boleh mengikutinya dan mendapatkan semua pesanan untuk pelanggan:

curl //localhost:8080/spring-security-rest/api/customers/10A/orders 
{ "_embedded": { "orderList": [{ "orderId": "001A", "price": 150, "quantity": 25, "_links": { "self": { "href": "//localhost:8080/spring-security-rest/api/customers/10A/001A" } } },{ "orderId": "002A", "price": 250, "quantity": 15, "_links": { "self": { "href": "//localhost:8080/spring-security-rest/api/customers/10A/002A" } } }] }, "_links": { "self": { "href": "//localhost:8080/spring-security-rest/api/customers/10A/orders" } } }

8. Kesimpulannya

Dalam tutorial ini, kami telah membincangkan bagaimana membina perkhidmatan web Spring REST yang didorong oleh hipermedia menggunakan projek Spring HATEOAS .

Dalam contoh tersebut, kami melihat bahawa klien dapat memiliki satu titik masuk ke aplikasi dan tindakan selanjutnya dapat diambil berdasarkan metadata dalam representasi respons.

Ini membolehkan pelayan menukar skema URI tanpa melanggar pelanggan. Aplikasi ini juga dapat mengiklankan kemampuan baru dengan meletakkan pautan atau URI baru dalam perwakilan.

Akhirnya, pelaksanaan sepenuhnya artikel ini boleh didapati dalam projek GitHub.

REST bawah

Saya baru sahaja mengumumkan kursus Learn Spring yang baru , yang berfokus pada asas-asas Spring 5 dan Spring Boot 2:

>> SEMAK KURSUS