Spring REST 與 Zuul 代理集成

REST,Spring Cloud
Remote
1
03:35 PM · Dec 01 ,2025

1. 概述

在本文中,我們將探討前端應用程序與部署在不同位置的 REST API 之間的通信。

目標是在解決瀏覽器中 CORS 和同一來源策略限制的情況下,允許 UI 調用 API,即使它們不共享同一來源。

我們將基本上創建兩個單獨的應用程序——一個 UI 應用程序和一個簡單的 REST API,並且我們將使用 Zuul 代理 在 UI 應用程序中作為代理來調用 REST API。

Zuul 是 Netflix 基於 JVM 的路由器和服務器端負載均衡器。Spring Cloud 具有與嵌入式 Zuul 代理的良好集成——這就是我們在這裏使用的。

2. Maven 配置

首先,我們需要將 Spring Cloud 的 zuul 支持依賴添加到我們 UI 應用程序的 pom.xml 中:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
    <version>2.2.0.RELEASE</version>
</dependency>

最新版本可以在這裏找到 這裏

3. Zuul 屬性

接下來,我們需要配置 Zuul,由於我們使用了 Spring Boot,我們將會在 application.yml

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

請注意:

  • 我們正在將請求代理到我們的資源服務器 Foos
  • 所有從 UI 發起的以 “/foos/” 開頭的請求都將路由到我們的 Foos 資源服務器,地址為 http://loclahost:8081/spring-zuul-foos-resource/foos/

4. API我們的API應用程序是一個簡單的Spring Boot應用程序。

在本文中,我們將考慮部署在運行在端口8081上的API。

首先,讓我們定義我們使用的資源的基準DTO:

public class Foo {
    private long id;
    private String name;

    // standard getters and setters
}

以及一個簡單的控制器:

@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. The UI Application

我們的UI應用程序也是一個簡單的Spring Boot應用程序。

在本文中,我們將考慮在運行在 8080端口上的API。

讓我們從主 index.html – 使用一些AngularJS開始:

<html>
<body ng-app="myApp" ng-controller="mainCtrl">
<script src="angular.min.js"></script>
<script src="angular-resource.min.js"></script>

<script>
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});
    }  
});
</script>

<div>
    <h1>Foo Details</h1>
    <span>{{foo.id}}</span>
    <span>{{foo.name}}</span>
    <a href="#" ng-click="getFoo()">New Foo</a>
</div>
</body>
</html>

最重要的是我們如何使用相對 URL 訪問 API 使用相對 URL!

請記住,API應用程序未部署在與UI應用程序相同的服務器上,因此相對 URL 不應該工作,並且在沒有代理的情況下也不會工作。

有了代理,我們通過 Zuul 代理訪問 Foo 資源,該代理當然配置為將這些請求路由到 API 實際部署的任何位置。

最後,啓用 Boot 的應用程序:

@EnableZuulProxy
@SpringBootApplication
public class UiApplication extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(UiApplication.class, args);
    }
}

除了簡單的 Boot 註解之外,請注意我們還使用了 Zuul 代理的樣式化啓用,這非常酷、乾淨且簡潔。

6. 測試路由

現在,讓我們測試我們的UI應用程序,方法如下:

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

7. 自定義 Zuul 過濾器有多個 Zuul 過濾器可用,我們也可以創建自己的自定義過濾器:

@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;
    }
    // ...
}

這個簡單的過濾器只是將一個名為“Test”的標題添加到請求中——當然,我們可以在這裏變得儘可能複雜,增強我們的請求。

8. 測試自定義 Zuul 過濾器

最後,讓我們測試以確保自定義過濾器正常工作——首先,我們將修改我們的 FooController 在 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));
    }
}

現在,讓我們測試它:

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

9. 結論

在本篇文檔中,我們重點介紹瞭如何使用 Zuul 將來自 UI 應用程序的請求路由到 REST API。我們成功地解決了 CORS 和同源策略的問題,並且還能夠自定義和增強傳輸中的 HTTP 請求。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.