知識庫 / REST RSS 訂閱

Spring REST 與 Zuul 代理集成

REST,Spring Cloud
HongKong
8
03:56 AM · Dec 06 ,2025

1. 概述

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

目標是在解決瀏覽器 CORS(跨域資源共享)和同一來源策略限制的情況下,允許 UI 調用 API,即使 UI 和 API 沒有共享相同的源。

我們將創建一個兩個獨立的應用程序——UI 應用程序和一個簡單的 REST API,並使用 UI 應用程序中的 Zuul 代理 來代理對 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. UI應用程序

我們的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。 請注意,API 應用程序未部署在與 UI 應用程序相同的服務器上,因此相對 URL 不應有效,並且在沒有代理的情況下也不會有效。

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

@EnableZuulProxy
@SpringBootApplication
public class UiApplication extends SpringBootServletInitializer {

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

除了簡單的 Boot 註解之外,我們還使用了 Zuul 代理的 enable-style 註解,這非常酷、簡潔和清晰。

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.