spring-cloud-gateway入门篇

spring cloud gateway 入门篇

1. 添加依赖。创建springboot项目,添加相关依赖,启动项目

创建一个空的springboot项目

步骤:略

pom配置

通过配置 spring.cloud.gateway.enabled=false 可以关闭网关功能

<!-- 后续文章都基于此版本号 -->
<properties>
	<java.version>17</java.version>
	<spring-boot.version>3.2.4</spring-boot.version>
	<spring-cloud.version>2023.0.1</spring-cloud.version>
	<spring-cloud-alibaba.version>2023.0.1.0</spring-cloud-alibaba.version>
</properties>

<!-- 统一管理依赖版本号 -->
<dependencyManagement>
    <dependencies>
        
        <!-- SpringBoot -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>${spring-boot.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        
        <!-- SpringCloud -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        
    </dependencies>
</dependencyManagement>

<dependencies>
    
    <!-- SpringCloud-Gateway 网关依赖 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
    
    <!-- lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <scope>provided</scope>
    </dependency>
    
</dependencies>

2. 核心概念

  • Route(路由): 网关的基本构件。它由一个ID、一个目的地URI、一个谓词(Predicate)集合和一个过滤器(Filter)集合定义。如果集合谓词为真,则路由被匹配。
  • Predicate(断言): 这是一个 Java 8 Function Predicate。Spring Framework ServerWebExchange。这让你可以在HTTP请求中的任何内容上进行匹配,比如header或查询参数。
  • Filter(过滤器): 这些是 GatewayFilter 的实例,已经用特定工厂构建。在这里,你可以在发送下游请求之前或之后修改请求和响应。
    ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/e680703eceec4515b095ddf94dbee2aa.png#pic_center

3. 网关工作流程

客户端向 Spring Cloud Gateway 发出请求。如果Gateway处理程序映射确定一个请求与路由相匹配,它将被发送到Gateway Web处理程序。这个处理程序通过一个特定于该请求的过滤器链来运行该请求。过滤器被虚线分割的原因是,过滤器可以在代理请求发送之前和之后运行逻辑。所有的 "pre" (前)过滤器逻辑都被执行。然后发出代理请求。在代理请求发出后,"post" (后)过滤器逻辑被运行。
在这里插入图片描述

4.配置路由

一、通过 .yml 或者 .properties 文件配置

server:
  port: 8080

spring:
  application:
    name: gateway-demo
  cloud:
    # Gateway 配置
    gateway:
      # 为所有路由配置Http超时(响应和连接)
      httpclient:
        connect-timeout: 3000
        response-timeout: 3s
      # 路由集合
      routes:
        # 路由id,唯一即可。建议配合服务名
        - id: my-route-id-1
          # 断言配置。当请求满足断言时,路由才会生效。若配置了多个断言,需要同时满足所有断言才生效
          predicates:
            - Path=/order-service/** # 按照path路径进行匹配,只要以/order-service/开头就符合规则
          # 路由的目的地,匹配后提供服务的路由地址。可以配合nacos通过服务名自动负载均衡
          uri: http://127.0.0.1:7777
          # 路由优先级。匹配到多个路由,最小的执行
          order: 1
          # 过滤器配置。系统内置多个网关过滤器,也
          filters:
            - StripPrefix=1 # 内置过滤器:表示截断路径前缀。如果请求的路径为/order-service/order/1,则路径会修改为/order/1
            - AddRequestParameter=tenantId, 123456 # 内置过滤器:表示给当前路由加上查询参数 ?tenantId=123456
          # 路由Http超时配置
          metadata:
            response-timeout: 200
            connect-timeout: 200
        - id: my-route-id-2
          predicates:
            - Path=/user-service/**
          uri: http://127.0.0.1:8888
          filters:
            - StripPrefix=1
        - id: my-route-id-3
          predicates:
            - Path=/dict-service/**
          uri: http://127.0.0.1:9999
          filters:
            - StripPrefix=1

二、也可以通过 Route 的Fluent式 Java API 方式配置

@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder, ThrottleGatewayFilterFactory throttle) {
    return builder.routes()
            .route(r -> r.host("**.abc.org").and().path("/image/png")
                .filters(f -> f.addResponseHeader("X-TestHeader", "foobar"))
                .uri("http://httpbin.org:80")
            )
            .route(r -> r.path("/image/webp")
                .filters(f -> f.addResponseHeader("X-AnotherHeader", "baz"))
                .uri("http://httpbin.org:80")
                .metadata("key", "value")
            )
            .route(r -> r.order(-1)
                .host("**.throttle.org").and().path("/get")
                .filters(f -> f.filter(throttle.apply(1, 1, 10, TimeUnit.SECONDS)))
                .uri("http://httpbin.org:80")
                .metadata("key", "value")
            )
            .build();
}

5.在本地准备另外一个简单的web项目(order-service),启动端口7777

server:
  port: 8080

并准备几个简单的测试接口

@Slf4j @RestController
public class OrderController {
    @PostMapping("/order/add")
    public CommResponse addOrder(@Validated @RequestBody Order order) {
        log.info("Micro Order Add!order={}", order);
        var response = new CommResponse();
        response.setRespCode("2000");
        response.setRespMsg("Success");
        response.setRespData("Micro Order Add Success");
        log.info("Micro Order Add Success!response={}", response);
        return response;
    }

    @PostMapping("/order/simulation")
    public void addSimulation() {
        log.info("Micro Order simulation!模拟网络延迟");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    @GetMapping("/order/list")
    public CommResponse orderList(@RequestParam(value = "tenantId") String tenantId) {
        log.info("Micro Order List!tenantId={}", tenantId);
        var response = new CommResponse();
        response.setRespCode("2000");
        response.setRespMsg("Success");
        response.setRespData(Order.init());
        return response;
    }

    @GetMapping("/order/{id}")
    public CommResponse getOrder(@PathVariable(name = "id") String id) {
        log.info("Get Order By ID!id={}", id);
        var response = new CommResponse();
        response.setRespCode("2000");
        response.setRespMsg("Success");
        response.setRespData(Order.init().stream().filter(order -> order.getId().equals(id)).findFirst().orElse(null));
        return response;
    }
}

@Getter @Setter @NoArgsConstructor @AllArgsConstructor @ToString
public class Order {
    private String id;
    private String name;
    private List<String> productList;
    private String createTime;

    public static List<Order> init() {
        List<Order> orderList = new ArrayList<>();
        orderList.add(new Order("1", "水果店订单", Arrays.asList("苹果", "梨"), "2024-10-12 10:12:00"));
        orderList.add(new Order("2", "洗衣液1kg订单", Arrays.asList("洗衣液"), "2024-10-15 20:12:00"));
        orderList.add(new Order("3", "杯子订单", Arrays.asList("保温杯", "马克杯", "吸管杯"), "2024-10-18 12:30:00"));
        return orderList;
    }
}

@Data
public class CommResponse {
    private String respCode;
    private String respMsg;
    private Object respData;
}

启动测试启动

  • 本地启动Gateway项目(8080)
  • 本地启动Order项目(7777)
  • 本地启动路由配置中相关的其它测试项目…

使用apiPost、postMan等工具进行接口调用测试

post: http://127.0.0.1:8080/order-service/order/add
post: http://127.0.0.1:8080/order-service/order/simulation
get:  http://127.0.0.1:8080/order-service/order/list
get:  http://127.0.0.1:8080/order-service/order/1
...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值