http://www.baeldung.com/spring-rest-with-zuul-proxy

作者: Eugen Paraschiv

译者: http://oopsguy.com

1、概述

在本文中,我们将探讨前端应用与单独部署的 REST API 之间的通信。

本文旨在解决 CORS 和浏览器的同源策略限制,允许 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-zuul</artifactId>
<version>1.0.4.RELEASE</version>
</dependency>

3、Zuul Properties

接下来,我们需要配置 Zuul,由于我们使用 Spring Boot,我们将在 application.yml 中进行配置:

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

注意:

  • 我们正在代理我们的资源服务器 Foos
  • /foos/ 开头的 UI 的所有请求都将路由到我们的 Foos 资源服务器:http:// loclahost:8081/spring-zuul-foos-resource/foos/

4、API

我们的 API 应用程序是一个简单的 Spring Boot 应用程序。

在本文中,我们考虑将 API 部署至运行在 8081 端口上的服务器中。

首先定义我们要使用的资源的 DTO:

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

和一个简单的控制器:

@Controller
public class FooController { @RequestMapping(method = RequestMethod.GET, value = "/foos/{id}")
@ResponseBody
public Foo findById(
@PathVariable long id, HttpServletRequest req, HttpServletResponse res) {
return new Foo(Long.parseLong(randomNumeric(2)), randomAlphabetic(4));
}
}

5、UI 应用程序

我们的 UI 应用程序也是一个简单的 Spring Boot 应用程序。

在本文中,我们考虑将 UI 部署至运行在 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 工作,如果没有使用代理,该 UI 应用程序将无法正常工作。

然而,如果使用代理服务器,我们可以通过 Zuul 代理来访问 Foo 资源,该代理配置为将这些请求路由到实际部署 API 的位置。

最后,引导应用程序:

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

除了简单的引导注解,请注意,我们使用 Zuul 代理的注解启用方式,这非常酷,而且干净简洁。

6、测试路由

现在,让我们来测试 UI 应用程序,如下所示:

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

7、自定义 Zuul Filter

有多个 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 Filter

最后,让我们测试以确保我们自定义的过滤器能够正常工作 — 首先我们将在 Foos 资源服务器上修改 FooController

@Controller
public class FooController { @GetMapping("/foos/{id}")
@ResponseBody
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 请求。

本教程的完整实现可以在项目 GitHub 中找到 — 这是一个基于 Maven 的项目,所以应该很容易导入和运行。

原文项目示例代码

https://github.com/eugenp/tutorials/tree/master/spring-zuul

Spring REST 与 Zuul 代理的更多相关文章

  1. Spring Cloud (十三) Zuul:静态路由、静态过滤器与动态路由的实现

    前言 本文起笔于2018-06-26周二,接了一个这周要完成的开发任务,需要先等其他人的接口,可能更新的会慢一些,还望大家见谅.这篇博客我们主要讲Spring Cloud Zuul.项目地址:我的gi ...

  2. 配置Zuul代理下游的认证

    配置Zuul代理下游的认证 您可以通过proxy.auth.*设置控制@EnableZuulProxy下游的授权行为.例: application.yml proxy: auth: routes: c ...

  3. Spring的AOP与代理

    spring 支持两种注入方式: setter/constructor 支持多种配置方式: xml/java5注解/java类配置 支持两种事务管理: 声明性/编程性 实际上上述方式只有一个就能保证系 ...

  4. Spring强制使用CGLIB代理事务

    Spring强制使用CGLIB代理事务   springaopjdkreferenceclasspath Spring1.2: 将事务代理工厂[TransactionProxyFactoryBean] ...

  5. Spring AOP 和 动态代理技术

    AOP 是什么东西 首先来说 AOP 并不是 Spring 框架的核心技术之一,AOP 全称 Aspect Orient Programming,即面向切面的编程.其要解决的问题就是在不改变源代码的情 ...

  6. Spring Cloud Netflix Zuul 重试会自动跳过经常超时的服务实例的简单说明和分析

    在使用E版本的Spring Cloud Netflix Zuul内置的Ribbon重试功能时,发现Ribbon有一个非常有用的特性: 如果某个服务的某个实例经常需要重试,Ribbon则会在自己维护的一 ...

  7. 深入理解Spring AOP之二代理对象生成

    深入理解Spring AOP之二代理对象生成 spring代理对象 上一篇博客中讲到了Spring的一些基本概念和初步讲了实现方法,当中提到了动态代理技术,包含JDK动态代理技术和Cglib动态代理 ...

  8. Spring AOP之动态代理

    软件151 李飞瑶 一.Spring 动态代理中的基本概念  1.关注点(concern)    一个关注点可以是一个特定的问题,概念.或者应用程序的兴趣点.总而言之,应用程序必须达到一个目标    ...

  9. Spring AOP --JDK动态代理方式

    我们知道Spring是通过JDK或者CGLib实现动态代理的,今天我们讨论一下JDK实现动态代理的原理. 一.简述 Spring在解析Bean的定义之后会将Bean的定义生成一个BeanDefinit ...

随机推荐

  1. java面向对象(五)之多态

    多态 面向对象编程有三大特性:封装.继承.多态. 封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据.对外界而已它的内部细节是隐藏的,暴露给外界的只是它的访问方法. ...

  2. ASP.NET Core的身份认证框架IdentityServer4(7)- 使用客户端证书控制API访问

    前言 今天(2017-9-8,写于9.8,今天才发布)一口气连续把最后几篇IdentityServer4相关理论全部翻译完了,终于可以进入写代码的过程了,比较累.目前官方的文档和Demo以及一些相关组 ...

  3. eclipse没有联想功能的解决办法

    1.我window->Preferences->Java->Editor->content assist 把 Enable auto activation 选项打上勾 :(如下 ...

  4. OCUpload的简单介绍与使用

     OCUpload (One Click Upload)译成中文就是一键上传的意思.它是JQuery的一个插件.   对于传统的文件上传,只能通过form表单,将enctype设置为multipart ...

  5. 日志log4j配置详情,日志log具体到你想不到

    一.Log4j简介Log4j有三个主要的组件:Loggers(记录器),Appenders (输出源)和Layouts(布局). 1.LoggersLoggers组件在此系统中被分为五个级别:DEBU ...

  6. sqlserver与mysql中vachar(n)中遇到的坑

    前两天在做将mysql的数据表导入到sqlserver当中. 本人比较愚笨,操作方法 是先将mysql的数据表到处为insert脚本,再在sqlserver中执行sql脚本 在网上看了一下那些方法 , ...

  7. SGI STL内存配置器存在内存泄漏吗?

    阅读了SGI的源码后对STL很是膜拜,很高质量的源码,从中学到了很多.温故而知新!下文中所有STL如无特殊说明均指SGI版本实现. STL 内存配置器 STL对内存管理最核心部分我觉得是其将C++对象 ...

  8. CCIE-MPLS VPN-实验手册(中卷)

    5:MPLS VPN PE CE OSPF 实验1 5.1 实验拓扑 5.2 实验需求 a. R1 R2 R3 组成P-NETWORK,底层协议采用EIGRP b. R1 R2 R3 直连链路启用LD ...

  9. 团队作业10——事后分析(Beta版本)

    团队作业10--事后分析(Beta版本) 目录 一.设想与目标 二.计划 三.资源 四.变更管理 五.设计与实现 六.测试与发布 七.总结 八.图片和贡献分分配 一.设想和目标 1.我们的软件要解决什 ...

  10. 团队作业8——第二次项目冲刺(Beta阶段)--第四天

    一.Daily Scrum Meeting照片 二.燃尽图 三.项目进展 学号 成员 贡献比 201421123001 廖婷婷 17% 201421123002 翁珊 18% 201421123004 ...