1. 路由简介:

SpringCloudGateWay 是用于替代zuul作为API网关,在gateway中有三个重要的名词:过滤器,断言,路由

过滤器与断言是路由的一部分,路由便是将请求进行一系列的处理后分发到各个服务的一个过程。

路由的过程:首先会加载断言以及路由,在接受到请求后根据断言加载的顺序会匹配到先加载的断言,只有与断言匹配了的请求才会进入路由,没有匹配到的服务会将请求当成普通的访问请求。

2:路由加载断言的方式:

断言加载的方式有四种,分别是配置文件,java编码,数据库以及注册中心

第一种配置文件:

在官方文档中主要介绍的就是配置文件的加载方式

官方地址:https://cloud.spring.io/spring-cloud-gateway/reference/html/#gateway-starter

一般的断言有三种要素:id,uri,predicate.

id是断言的标识,uri是ip+端口,predicate则是断言匹配的规则

3:示例:

新建一个springboot项目,并且引入springcloudgateway的依赖

 <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
</dependencies>

在启动类注册三个全局过滤器

 @SpringBootApplication
public class GateWayApplication { public static void main(String[] args) {
SpringApplication.run(GateWayApplication.class, args);
} @Bean
@Order(-1)
public GlobalFilter a() {
return (exchange, chain) -> { return chain.filter(exchange).then(Mono.fromRunnable(() -> {
System.out.println(-1);
}));
};
} @Bean
@Order(0)
public GlobalFilter b() {
return (exchange, chain) -> { return chain.filter(exchange).then(Mono.fromRunnable(() -> {
System.out.println(0);
}));
};
} @Bean
@Order(1)
public GlobalFilter c() {
return (exchange, chain) -> { return chain.filter(exchange).then(Mono.fromRunnable(() -> {
System.out.println(1);
}));
};
}
}

在配置文件类配置两条路由

server.port: 7777
spring:
application:
name: gateway
cloud:
gateway:
discovery:
locator:
enabled: true
lower-case-service-id: true
routes:
- id: method_route
uri: http://127.0.0.1:9999
predicates:
- Method=GET
- id: method_route
uri: http://127.0.0.1:8006
predicates:
- Method=GET

发送请求,请求到达后匹配的是第一条路由,由此可以知道路由匹配的顺序会根据加载的顺序来

4:SpringCloudGateWay从注册中心获得路由

在官方文档中,我们可以看到有这样的一段话

Configuring Predicates and Filters For DiscoveryClient Routes

By default the Gateway defines a single predicate and filter for routes created via a DiscoveryClient.

The default predicate is a path predicate defined with the pattern /serviceId/**, where serviceId is the id of the service from the DiscoveryClient.

The default filter is rewrite path filter with the regex /serviceId/(?<remaining>.*) and the replacement /${remaining}. This just strips the service id from the path before the request is sent downstream.

If you would like to customize the predicates and/or filters used by the DiscoveryClient routes you can do so by setting spring.cloud.gateway.discovery.locator.predicates[x] and spring.cloud.gateway.discovery.locator.filters[y]. When doing so you need to make sure to include the default predicate and filter above, if you want to retain that functionality. Below is an example of what this looks like.

地址 :https://cloud.spring.io/spring-cloud-gateway/reference/html/#_global_filters

 spring.cloud.gateway.discovery.locator.predicates[0].name: Path
spring.cloud.gateway.discovery.locator.predicates[0].args[pattern]: "'/'+serviceId+'/**'"
spring.cloud.gateway.discovery.locator.predicates[1].name: Host
spring.cloud.gateway.discovery.locator.predicates[1].args[pattern]: "'**.foo.com'"
spring.cloud.gateway.discovery.locator.filters[0].name: Hystrix
spring.cloud.gateway.discovery.locator.filters[0].args[name]: serviceId
spring.cloud.gateway.discovery.locator.filters[1].name: RewritePath
spring.cloud.gateway.discovery.locator.filters[1].args[regexp]: "'/' + serviceId + '/(?<remaining>.*)'"
spring.cloud.gateway.discovery.locator.filters[1].args[replacement]: "'/${remaining}'"

根据文档介绍,依照这种方式,可以从注册中心获得断言与过滤器的配置

5:SpringGateWay从数据库配置路由

public class DBRouteDefinitionRepository  implements RouteDefinitionRepository

项目中实现了RouteDefinitionRepository后,springgateway会采用你实现的这个类去加载路由,如果不实现则采用他默认的方式加载路由

 public class DBRouteDefinitionRepository  implements RouteDefinitionRepository {
    //保存路由
    private final Map<String, RouteDefinition> routes = synchronizedMap(new LinkedHashMap<String, RouteDefinition>());
    
    private Logger log = LoggerFactory.getLogger(DBRouteDefinitionRepository.class);
    //初始標準
    private boolean init_flag = true;
    //
    private final GatewayProperties properties;
    private DynamicRouteServiceImpl service;
         public DBRouteDefinitionRepository(GatewayProperties properties) {
        this.properties = properties;
        this.service = new DynamicRouteServiceImpl();     }
    
    @Override
    public Flux<RouteDefinition> getRouteDefinitions() {
        if(init_flag) {
            List<RouteDefinition> routeDefinitions = new ArrayList<>();
            List<RouteDefinition> rs = new ArrayList<>();
            try {
                routeDefinitions = service.quertAllRoutes();//从数据库中加载route
                rs = this.properties.getRoutes();//获得配置文件的route
                for (RouteDefinition rse : rs) {
                    routeDefinitions.add(rse);
                }
                routes.clear();
                routeDefinitions.forEach(x->routes.put(x.getId(), x));
                init_flag=false;
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                log.error("Init Route Fail,Can't get Routes.",e);
            }
            return Flux.fromIterable(routeDefinitions);
        }else {
            return Flux.fromIterable(routes.values());
        }
        
    }     @Override
    public Mono<Void> delete(Mono<String> routeId) {
        return routeId.flatMap(id -> {
            if (routes.containsKey(id)) {
                routes.remove(id);
                return Mono.empty();
            }
            return Mono.defer(() -> Mono.error(new NotFoundException("RouteDefinition not found: "+routeId)));
        });
    }     @Override
    public Mono<Void> save(Mono<RouteDefinition> route) {
        return route.flatMap( r -> {
            routes.put(r.getId(), r);
            return Mono.empty();
        });
    } }

这个是我自己实现的类,这个类可以从数据库与配置文件中获得路由配置,从数据库中获得路由配置可以根据个人的要求来

@Validated
public class RouteDefinition { @NotEmpty
private String id = UUID.randomUUID().toString(); @NotEmpty
@Valid
private List<PredicateDefinition> predicates = new ArrayList<>(); @Valid
private List<FilterDefinition> filters = new ArrayList<>(); @NotNull
private URI uri; private int order = 0; public RouteDefinition() {
} public RouteDefinition(String text) {
int eqIdx = text.indexOf('=');
if (eqIdx <= 0) {
throw new ValidationException("Unable to parse RouteDefinition text '" + text
+ "'" + ", must be of the form name=value");
} setId(text.substring(0, eqIdx)); String[] args = tokenizeToStringArray(text.substring(eqIdx + 1), ","); setUri(URI.create(args[0])); for (int i = 1; i < args.length; i++) {
this.predicates.add(new PredicateDefinition(args[i]));
}
} public String getId() {
return id;
} public void setId(String id) {
this.id = id;
} public List<PredicateDefinition> getPredicates() {
return predicates;
} public void setPredicates(List<PredicateDefinition> predicates) {
this.predicates = predicates;
} public List<FilterDefinition> getFilters() {
return filters;
} public void setFilters(List<FilterDefinition> filters) {
this.filters = filters;
} public URI getUri() {
return uri;
} public void setUri(URI uri) {
this.uri = uri;
} public int getOrder() {
return order;
} public void setOrder(int order) {
this.order = order;
} @Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
RouteDefinition routeDefinition = (RouteDefinition) o;
return Objects.equals(id, routeDefinition.id)
&& Objects.equals(predicates, routeDefinition.predicates)
&& Objects.equals(order, routeDefinition.order)
&& Objects.equals(uri, routeDefinition.uri);
} @Override
public int hashCode() {
return Objects.hash(id, predicates, uri);
} @Override
public String toString() {
return "RouteDefinition{" + "id='" + id + '\'' + ", predicates=" + predicates
+ ", filters=" + filters + ", uri=" + uri + ", order=" + order + '}';
} }

SpringCloudGateway开发详解的更多相关文章

  1. EasyPR--开发详解(6)SVM开发详解

    在前面的几篇文章中,我们介绍了EasyPR中车牌定位模块的相关内容.本文开始分析车牌定位模块后续步骤的车牌判断模块.车牌判断模块是EasyPR中的基于机器学习模型的一个模块,这个模型就是作者前文中从机 ...

  2. 基于H5的微信支付开发详解

    这次总结一下用户在微信内打开网页时,可以调用微信支付完成下单功能的模块开发,也就是在微信内的H5页面通过jsApi接口实现支付功能.当然了,微信官网上的微信支付开发文档也讲解的很详细,并且有实现代码可 ...

  3. ****基于H5的微信支付开发详解[转]

    这次总结一下用户在微信内打开网页时,可以调用微信支付完成下单功能的模块开发,也就是在微信内的H5页面通过jsApi接口实现支付功能.当然了,微信官网上的微信支付开发文档也讲解的很详细,并且有实现代码可 ...

  4. 【转发】NPAPI开发详解,Windows版

    NPAPI开发详解,Windows版 9 jiaofeng601, +479 9人支持,来自Meteor.猪爪.hanyuxinting更多 .是非黑白 .Yuan Xulei.hyolin.Andy ...

  5. 热烈祝贺华清远见《ARM处理器开发详解》第2版正式出版

    2014年6月,由华清远见研发中心组织多名业 内顶尖讲师编写的<ARM处理器开发详解>一书正式出版.本书以S5PV210处理器为平台,详细介绍了嵌入式系统开发的各个主要环节,并注重实践,辅 ...

  6. 嵌入式Linux应用程序开发详解------(创建守护进程)

    嵌入式Linux应用程序开发详解 华清远见 本文只是阅读文摘. 创建一个守护进程的步骤: 1.创建一个子进程,然后退出父进程: 2.在子进程中使用创建新会话---setsid(): 3.改变当前工作目 ...

  7. iOS原生地图开发详解

    在上一篇博客中:http://my.oschina.net/u/2340880/blog/414760.对iOS中的定位服务进行了详细的介绍与参数说明,在开发中,地位服务往往与地图框架结合使用,这篇博 ...

  8. wpf 客户端【JDAgent桌面助手】开发详解(四) popup控件的win8.0的bug

    目录区域: 业余开发的wpf 客户端终于完工了..晒晒截图 wpf 客户端[JDAgent桌面助手]开发详解-开篇 wpf 客户端[JDAgent桌面助手]详解(一)主窗口 圆形菜单... wpf 客 ...

  9. PayPal 开发详解(七):运行REST API SAMPLE

    1.编译成功,修改配置文件 sdk_config.properties ,使用我们申请的测试帐号执行收款测试,clientId 和 clientSecret 参见 PayPal 开发详解(五) 2.将 ...

随机推荐

  1. openstack学习之neutron ml2初始化代码分析

    这里没有 去详细考虑neutron server怎么初始化的,而是直接从加载插件的地方开始分析.首先我们看下下面这个文件. Neutron/api/v2/router.py class APIRout ...

  2. Nginx(http协议代理 搭建虚拟主机 服务的反向代理 在反向代理中配置集群的负载均衡)

    Nginx 简介 Nginx (engine x) 是一个高性能的 HTTP 和反向代理服务.Nginx 是由伊戈尔·赛索耶夫为俄罗斯访问量第二的 Rambler.ru 站点(俄文:Рамблер)开 ...

  3. 大数据之Linux进阶指令

    1.文件内容操作相关命令 cut 根据条件 从命令结果中 提取 对应内容 -c  按字符选取内容 例子:head -2 1.txt | cut -c 5 截取前两行的第五个字符 -d  '分隔符'  ...

  4. [TimLinux] JavaScript table的td内容超过宽度缩为三个点

    1. 思路 CSS控制td内容自动缩为三个点 JS控制鼠标悬浮显示td全部内容 2. 实现 HTML代码: <!DOCTYPE html> <html> <head> ...

  5. 洛谷 题解 P1615 【西游记公司】

    我的程序只有1行... return scanf("%d:%d:%d\n%d:%d:%d\n%d", &a, &b, &c, &x, &y, ...

  6. linux mysql,tomcat与java的安装

    先将服务器的安全组设置为 把所有端口或者所需要的端口开放 然后测试远程访问 ssh 用户@ip                       登录 输入密码 service iptables stop  ...

  7. uni-app微信小程序开发之引入腾讯视频小程序播放插件

    登录微信小程序管理后台添加腾讯视频播放插件: 正式开始使用腾讯视频小程序插件之前需先在微信公众平台 -> 第三方设置 -> 插件管理处添加插件,如下图所示: 在uni-app中引入插件代码 ...

  8. 基于STM32F1 的BASIC解码实验 vb basic 液晶显示执行过程及结果

    基于STM32F1 的BASIC解码实验 1.basic程序以文件形式存储 2.程序文件存储在sd卡 3.解释结果显示在液晶屏上 主函数部分 int main(void){ u16 i,j; dela ...

  9. 小白学 Python 爬虫(20):Xpath 进阶

    人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...

  10. DARLING in the FRANXX

    那是一种叫比翼的鸟,这种鸟只有半边翅膀,如果雌鸟和雄鸟不紧靠在一起的话,它们就无法飞上天空,是不完整的生物. 但是,为什么,我总认为这种生活方式是如此美丽,感觉如此美丽. 那是一种叫比翼的鸟,我以前从 ...