1、概览 {#1概览}
本文将带你了解如何在 UI (前端)应用中使用 Zuul 作为代理与 Spring REST 服务通信,使用 Zuul 代理的目的是为了统一处理 CORS 和 Same Origin Policy 问题。
Zuul 是 Netflix 基于 JVM 的路由和服务器端负载均衡器。Spring Cloud 与嵌入式 Zuul 代理进行了很好的集成。
2、Maven 配置 {#2maven-配置}
首先,在 UI 应用的 pom.xml
中添加 Spring Cloud Zuul 依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
<version>2.2.0.RELEASE</version>
</dependency>
最新版本可在 此处 找到。
3、Zuul Properties {#3zuul-properties}
接着,在 application.yml
中对 Zuul 进行配置:
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 {#4api}
API 是一个简单的 Spring Boot 应用,监听 8081 端口。
首先,定义资源 DTO 类,Foo
:
public class Foo { private long id; private String name;
// Get、Set 方法
}
以及,Controller:
@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 应用 {#5ui-应用}
UI 应用也是一个简单的 Spring Boot 应用,监听 8080 端口:
首先,创建主页 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); }
}
除了简单的 Spring Boot 注解外,还通过 @EnableZuulProxy
注解启用了 Zuul 代理。
6、测试路由 {#6测试路由}
测试 UI 应用,如下:
@Test public void whenSendRequestToFooResource_thenOK() { Response response = RestAssured.get("http://localhost:8080/foos/1");
assertEquals(200, response.getStatusCode());
}
7、自定义 Zuul Filter {#7自定义-zuul-filter}
有多种 Zuul Filter 可供选择,也可以创建自己的自定义 Filter:
@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; } // ...
}
如上这个简单的 Filter 只是在请求中添加了一个名为 Test 的 Header。当然,你也可以根据需要在这里添加复杂的请求。
8、测试自定义 Zuul Filter {#8测试自定义-zuul-filter}
最后,来测试一下自定义 Filter 是否正常工作。
首先,修改 Foos 资源服务器上的 FooController
:
@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、总结 {#9总结}
本文介绍了如何在前端应用中使用 Zuul 作为代理请求 REST API 服务,
Ref:https://www.baeldung.com/spring-rest-with-zuul-proxy