项目示例 - 3.服务网关 - 3.Gateway

项目示例 - 3.服务网关 - 3.Gateway

关联知识:

  • 分布式微服务 - 3.服务网关 - 4.Gateway

内容提要:

  • 基本使用
  • 自定义断言
  • 自定义局部、全局过滤器

基本使用

  1. 建Module:微服务起名为gateway-server
  2. 改pom:引入以下依赖
xml 复制代码
    <dependencies>
        <!--gateway-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>
        <!--Nacos服务注册-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
    </dependencies>
  1. 写yml:在resources目录下创建application.yml文件,并做以下配置
yml 复制代码
server:
  port: 80

spring:
  application:
    name: gateway-server
  cloud:
    nacos:
      discovery:
        # nacos的地址
        server-addr: localhost:8848
    gateway:
      discovery:
        locator:
          # 从服务注册中心根据别名来进行路由
          enabled: true
      routes:
        # 路由Id,自定义,唯一即可
        - id: nacos-provider-test
          # 成功匹配后,要转换成的路由地址(配合服务注册中心使用别名)
          uri: lb://nacos-provider
          # 成功匹配后,要转换成的路由地址(不配合服务注册中心)
          #uri: http://localhost:8001
          # 断言
          predicates:
            # 路径匹配的进行路由
            - Path=/**
  1. 主启动:在src下创建如下主启动类
java 复制代码
package learn.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class GatewayServer {

    public static void main(String[] args) {
        SpringApplication.run(GatewayServer.class, args);
    }

}
  1. 测试:
    1. 启动nacos,能正常打开nacos首页
    2. 启动nacos-provider微服务,浏览器访问localhost:8001/nacos/provider/test 接口,能正常返回信息,且在nacos服务列表中可看到成功注册
    3. 启动本微服务后,浏览器访问localhost/nacos/provider/test 接口,能正常返回信息

自定义断言

  1. 创建自定义断言类:
java 复制代码
package learn.demo.config;

import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

@Component
public class CustomRoutePredicateFactory extends AbstractRoutePredicateFactory<CustomRoutePredicateFactory.Config> {

    public CustomRoutePredicateFactory() {
        super(Config.class);
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("key", "value");
    }

    @Override
    public Predicate<ServerWebExchange> apply(Config config) {
        return new Predicate<ServerWebExchange>() {
            @Override
            public boolean test(ServerWebExchange serverWebExchange) {
                List<String> strings = serverWebExchange.getRequest().getHeaders().get(config.key);
                if (strings==null || strings.isEmpty())
                    return false;
                return config.value.equals(strings.get(0));
            }
        };
    }

    public static class Config {
        private String key;
        private String value;

        public String getKey() {
            return key;
        }

        public void setKey(String key) {
            this.key = key;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }
    }

}
  1. application.yml中配置断言:
yml 复制代码
server:
  port: 80

spring:
  application:
    name: gateway-server
  cloud:
    nacos:
      discovery:
        # nacos的地址
        server-addr: localhost:8848
    gateway:
      discovery:
        locator:
          # 从服务注册中心根据别名来进行路由
          enabled: true
      routes:
        # 路由Id,自定义,唯一即可
        - id: nacos-provider-test
          # 成功匹配后,要转换成的路由地址(配合服务注册中心使用别名)
          uri: lb://nacos-provider
          # 成功匹配后,要转换成的路由地址(不配合服务注册中心)
          #uri: http://localhost:8001
          # 断言
          predicates:
            # 路径匹配的进行路由
            - Path=/**
            - Custom=test, a
  1. 测试:
    1. 启动nacos,能正常打开nacos首页
    2. 启动nacos-provider微服务,浏览器访问localhost:8001/nacos/provider/test 接口,能正常返回信息,且在nacos服务列表中可看到成功注册
    3. 启动本微服务后,API工具访问localhost/nacos/provider/test 接口,返回404。在header中,携带key为test、value为a的参数后再次访问,可以正常返回信息。

自定义过滤器

自定义局部过滤器

  1. 创建自定义过滤器类:
java 复制代码
package learn.demo.config;

import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Arrays;
import java.util.List;

@Component
public class CustomGatewayFilterFactory extends AbstractGatewayFilterFactory<CustomGatewayFilterFactory.Config> {

    public CustomGatewayFilterFactory() {
        super(Config.class);
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("key", "value");
    }

    @Override
    public GatewayFilter apply(Config config) {
        return new GatewayFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                // pre操作
                String pre;
                List<String> strings = exchange.getRequest().getHeaders().get("pre");
                if (strings==null || strings.isEmpty())
                    pre="no args";
                else
                    pre=strings.get(0);

                return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                    // 异步post操作
                    exchange.getResponse().getHeaders().set(config.key, pre+" | "+config.value);
                }));
            }
        };
    }

    public static class Config {
        private String key;
        private String value;

        public String getKey() {
            return key;
        }

        public void setKey(String key) {
            this.key = key;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }
    }

}
  1. 添加配置:
yml 复制代码
server:
  port: 80

spring:
  application:
    name: gateway-server
  cloud:
    nacos:
      discovery:
        # nacos的地址
        server-addr: localhost:8848
    gateway:
      discovery:
        locator:
          # 从服务注册中心根据别名来进行路由
          enabled: true
      routes:
        # 路由Id,自定义,唯一即可
        - id: nacos-provider-test
          # 成功匹配后,要转换成的路由地址(配合服务注册中心使用别名)
          uri: lb://nacos-provider
          # 成功匹配后,要转换成的路由地址(不配合服务注册中心)
          #uri: http://localhost:8001
          # 断言
          predicates:
            # 路径匹配的进行路由
            - Path=/**
            - Custom=test, a
          filters:
            - Custom=post,test
  1. 测试:
    1. 启动nacos,能正常打开nacos首页
    2. 启动nacos-provider微服务,浏览器访问localhost:8001/nacos/provider/test 接口,能正常返回信息,且在nacos服务列表中可看到成功注册
    3. 启动本微服务后,API工具访问localhost/nacos/provider/test 接口,返回404。在header中,携带key为test、value为a的参数后再次访问,可以正常返回信息,查看响应头中有key为post、value为no args | test的参数。

自定义全局过滤器

  1. 创建自定义过滤器类:
java 复制代码
package learn.demo.config;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;

@Component
public class CustomGlobalFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // pre操作
        String pre;
        List<String> strings = exchange.getRequest().getHeaders().get("pre");
        if (strings==null || strings.isEmpty())
            pre="no args";
        else
            pre=strings.get(0);

        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            // 异步post操作
            exchange.getResponse().getHeaders().set("post", pre+" | test");
        }));
    }

    // 值越小,优先级越高
    @Override
    public int getOrder() {
        return 0;
    }
}
  1. 修改配置文件:
yml 复制代码
server:
  port: 80

spring:
  application:
    name: gateway-server
  cloud:
    nacos:
      discovery:
        # nacos的地址
        server-addr: localhost:8848
    gateway:
      discovery:
        locator:
          # 从服务注册中心根据别名来进行路由
          enabled: true
      routes:
        # 路由Id,自定义,唯一即可
        - id: nacos-provider-test
          # 成功匹配后,要转换成的路由地址(配合服务注册中心使用别名)
          uri: lb://nacos-provider
          # 成功匹配后,要转换成的路由地址(不配合服务注册中心)
          #uri: http://localhost:8001
          # 断言
          predicates:
            # 路径匹配的进行路由
            - Path=/**
            - Custom=test, a
  1. 测试:
    1. 启动nacos,能正常打开nacos首页
    2. 启动nacos-provider微服务,浏览器访问localhost:8001/nacos/provider/test 接口,能正常返回信息,且在nacos服务列表中可看到成功注册
    3. 启动本微服务后,API工具访问localhost/nacos/provider/test 接口,返回404。在header中,携带key为test、value为a的参数后再次访问,可以正常返回信息,查看响应头中有key为post、value为no args | test的参数。
相关推荐
极客先躯33 分钟前
高级java每日一道面试题-2024年10月3日-分布式篇-分布式系统中的容错策略都有哪些?
java·分布式·版本控制·共识算法·超时重试·心跳检测·容错策略
夜月行者1 小时前
如何使用ssm实现基于SSM的宠物服务平台的设计与实现+vue
java·后端·ssm
Yvemil71 小时前
RabbitMQ 入门到精通指南
开发语言·后端·ruby
niu_sama1 小时前
仿RabbitMQ实现消息队列三种主题的调试及源码
分布式·rabbitmq
鸡c1 小时前
rabbitMq------客户端模块
分布式·rabbitmq·ruby
sdg_advance1 小时前
Spring Cloud之OpenFeign的具体实践
后端·spring cloud·openfeign
王彬泽1 小时前
【微服务】服务注册与发现、分布式配置管理 - Nacos
微服务·服务注册与发现·分布式配置管理
猿java2 小时前
使用 Kafka面临的挑战
java·后端·kafka
碳苯2 小时前
【rCore OS 开源操作系统】Rust 枚举与模式匹配
开发语言·人工智能·后端·rust·操作系统·os
Dylanioucn2 小时前
【分布式微服务云原生】探索Redis:数据结构的艺术与科学
数据结构·redis·分布式·缓存·中间件