Spring REST 与 Zuul 代理

http://www.baeldung.com/spring-rest-with-zuul-proxy
做者: Eugen Paraschiv
译者: http://oopsguy.comhtml

一、概述

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

本文旨在解决 CORS 和浏览器的同源策略限制,容许 UI 调用 API,即便它们不是同源java

基本上,咱们将建立两个独立的应用程序 — 一个 UI 应用程序和一个简单的 REST API,咱们将使用 UI 应用程序中的 Zuul 代理来代理对 REST API 的调用。git

Zuul 是 Netflix 的一个基于 JVM 的路由和服务端负载均衡器。Spring Cloud 与内嵌式 Zuul 代理能够很好地集成工做 — 本次咱们也将使用他们。github

二、Maven 配置

首先,咱们须要添加一个来自 Spring Cloud 的 zuul 支持到咱们的 UI 应用程序的 pom.xml 中:spring

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

三、Zuul Properties

接下来,咱们须要配置 Zuul,因为咱们使用 Spring Boot,咱们将在 application.yml 中进行配置:api

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/

四、API

咱们的 API 应用程序是一个简单的 Spring Boot 应用程序。服务器

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

首先定义咱们要使用的资源的 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));
    }
}

五、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 代理的注解启用方式,这很是酷,并且干净简洁。

六、测试路由

如今,让咱们来测试 UI 应用程序,以下所示:

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

七、自定义 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 的头部 — 固然,咱们能够根据咱们须要的复杂程度来扩充咱们的请求。

八、测试自定义 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"));
}

九、结论

在这篇文章中,咱们主要使用了 Zuul 未来自 UI 应用程序的请求路由到 REST API。咱们成功地解决了 CORS 和同源策略,咱们还定制和扩充了 HTTP 请求。

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

原文项目示例代码

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

相关文章
相关标签/搜索