zoukankan      html  css  js  c++  java
  • Spring REST 与 Zuul 代理

    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

  • 相关阅读:
    [LeetCode] 117. Populating Next Right Pointers in Each Node II
    [LeetCode] 229. Majority Element II
    [LeetCode] 876. Middle of the Linked List
    HttpClient 使用案例
    github 拷贝项目到本地
    tomcat下文件路径
    同一个tomcat 两个项目 互相访问接口方法
    Mysq 列中存储json格式根据key取value
    mysql 函数和存储过程的区别
    mysql触发器
  • 原文地址:https://www.cnblogs.com/oopsguy/p/7631552.html
Copyright © 2011-2022 走看看