Spring REST dengan Proksi Zuul

1. Gambaran keseluruhan

Dalam artikel ini, kita akan meneroka komunikasi antara aplikasi front-end dan REST API yang digunakan secara berasingan .

Tujuannya adalah untuk mengatasi CORS dan sekatan Dasar Asal yang Sama pada penyemak imbas dan membenarkan UI memanggil API walaupun mereka tidak mempunyai asal yang sama.

Pada dasarnya kami akan membuat dua aplikasi yang berasingan - aplikasi UI dan REST API yang mudah, dan kami akan menggunakan proksi Zuul dalam aplikasi UI untuk memproksi panggilan ke REST API.

Zuul adalah penyusun beban sisi penghala dan pelayan berasaskan JVM oleh Netflix. Dan Spring Cloud mempunyai integrasi yang bagus dengan proksi Zuul tertanam - yang akan kami gunakan di sini.

2. Konfigurasi Maven

Pertama, kita perlu menambahkan kebergantungan pada sokongan zuul dari Spring Cloud ke pom.xml aplikasi UI kami :

 org.springframework.cloud spring-cloud-starter-netflix-zuul 2.2.0.RELEASE 

Versi terbaru boleh didapati di sini.

3. Sifat Zuul

Seterusnya - kita perlu mengkonfigurasi Zuul, dan kerana kita menggunakan Spring Boot, kita akan melakukannya di aplikasi.yml :

zuul: routes: foos: path: /foos/** url: //localhost:8081/spring-zuul-foos-resource/foos

Perhatikan bahawa:

  • Kami menghampiri Foos pelayan sumber kami .
  • Semua permintaan dari UI yang dimulai dengan " / foos / " akan disalurkan ke pelayan Sumber Foos kami di // loclahost: 8081 / spring-zuul-foos-resource / foos /

4. API

Aplikasi API kami adalah aplikasi Spring Boot yang ringkas.

Dalam artikel ini, kita akan mempertimbangkan API yang digunakan dalam pelayan yang berjalan di port 8081.

Mari kita tentukan DTO asas untuk Sumber yang akan kita gunakan:

public class Foo { private long id; private String name; // standard getters and setters }

Dan pengawal mudah:

@RestController public class FooController { @GetMapping("/foos/{id}") public Foo findById( @PathVariable long id, HttpServletRequest req, HttpServletResponse res) { return new Foo(Long.parseLong(randomNumeric(2)), randomAlphabetic(4)); } }

5. Aplikasi UI

Aplikasi UI kami juga merupakan aplikasi Spring Boot yang ringkas.

Dalam artikel ini, kami akan mempertimbangkan API yang digunakan dalam pelayan yang berjalan di port 8080.

Mari kita mulakan dengan indeks utama.html - menggunakan sedikit AngularJS:

     var app = angular.module('myApp', ["ngResource"]); app.controller('mainCtrl', function($scope,$resource,$http) { $scope.foo = {id:0 , name:"sample foo"}; $scope.foos = $resource("/foos/:fooId",{fooId:'@id'}); $scope.getFoo = function(){ $scope.foo = $scope.foos.get({fooId:$scope.foo.id}); } }); {{foo.id}} {{foo.name}} New Foo 

Aspek yang paling penting di sini adalah bagaimana kita mengakses API menggunakan URL relatif!

Perlu diingat bahawa aplikasi API tidak digunakan pada pelayan yang sama dengan aplikasi UI, jadi URL relatif tidak boleh berfungsi , dan tidak akan berfungsi tanpa proksi.

Dengan proksi, bagaimanapun, kami mengakses sumber daya Foo melalui proksi Zuul, yang tentunya dikonfigurasi untuk merutekan permintaan ini ke mana sahaja API sebenarnya digunakan.

Dan akhirnya, aplikasi yang sebenarnya Boot:

@EnableZuulProxy @SpringBootApplication public class UiApplication extends SpringBootServletInitializer { public static void main(String[] args) { SpringApplication.run(UiApplication.class, args); } }

Di luar anotasi Boot yang sederhana, perhatikan bahawa kami menggunakan gaya anotasi yang diaktifkan untuk proksi Zuul juga, yang cukup sejuk, bersih dan ringkas.

6. Uji Laluan

Sekarang - mari uji aplikasi UI kami - seperti berikut:

@Test public void whenSendRequestToFooResource_thenOK() { Response response = RestAssured.get("//localhost:8080/foos/1"); assertEquals(200, response.getStatusCode()); }

7. Penapis Zuul Tersuai

Terdapat beberapa penapis Zuul yang tersedia, dan kami juga boleh membuat penapis tersuai kami sendiri:

@Component public class CustomZuulFilter extends ZuulFilter { @Override public Object run() { RequestContext ctx = RequestContext.getCurrentContext(); ctx.addZuulRequestHeader("Test", "TestSample"); return null; } @Override public boolean shouldFilter() { return true; } // ... }

Penapis sederhana ini hanya menambahkan tajuk yang disebut " Uji " pada permintaan - tetapi tentu saja, kita dapat menjadi rumit seperti yang kita perlukan di sini untuk menambah permintaan kita.

8. Uji Penapis Zuul Custom

Akhirnya, mari kita uji memastikan penapis khas kita berfungsi - pertama kita akan mengubah FooController kami di pelayan sumber Foos:

@RestController public class FooController { @GetMapping("/foos/{id}") public Foo findById( @PathVariable long id, HttpServletRequest req, HttpServletResponse res) { if (req.getHeader("Test") != null) { res.addHeader("Test", req.getHeader("Test")); } return new Foo(Long.parseLong(randomNumeric(2)), randomAlphabetic(4)); } }

Sekarang - mari kita mengujinya:

@Test public void whenSendRequest_thenHeaderAdded() { Response response = RestAssured.get("//localhost:8080/foos/1"); assertEquals(200, response.getStatusCode()); assertEquals("TestSample", response.getHeader("Test")); }

9. Kesimpulannya

Dalam penulisan ini, kami fokus menggunakan Zuul untuk merutekan permintaan dari aplikasi UI ke REST API. Kami berjaya menyelesaikan CORS dan dasar asal yang sama dan kami juga berjaya menyesuaikan dan menambah permintaan HTTP dalam perjalanan.

The pelaksanaan penuh tutorial ini boleh didapati dalam projek GitHub - ini adalah projek berasaskan Maven, jadi ia harus mudah untuk import dan berjalan kerana ia adalah.