SpringCloudGateway开发过程解析
路由简介:
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的依赖
org.springframework.boot spring-boot-starter-test test org.springframework.cloud spring-cloud-starter-gateway
在启动类注册三个全局过滤器
@SpringBootApplication
publicclassGateWayApplication{
publicstaticvoidmain(String[]args){
SpringApplication.run(GateWayApplication.class,args);
}
@Bean
@Order(-1)
publicGlobalFiltera(){
return(exchange,chain)->{
returnchain.filter(exchange).then(Mono.fromRunnable(()->{
System.out.println(-1);
}));
};
}
@Bean
@Order(0)
publicGlobalFilterb(){
return(exchange,chain)->{
returnchain.filter(exchange).then(Mono.fromRunnable(()->{
System.out.println(0);
}));
};
}
@Bean
@Order(1)
publicGlobalFilterc(){
return(exchange,chain)->{
returnchain.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从注册中心获得路由
在官方文档中,我们可以看到有这样的一段话
ConfiguringPredicatesandFiltersForDiscoveryClientRoutes
BydefaulttheGatewaydefinesasinglepredicateandfilterforroutescreatedviaaDiscoveryClient.
Thedefaultpredicateisapathpredicatedefinedwiththepattern/serviceId/**,whereserviceIdistheidoftheservicefromtheDiscoveryClient.
Thedefaultfilterisrewritepathfilterwiththeregex/serviceId/(?
Ifyouwouldliketocustomizethepredicatesand/orfiltersusedbytheDiscoveryClientroutesyoucandosobysettingspring.cloud.gateway.discovery.locator.predicates[x]andspring.cloud.gateway.discovery.locator.filters[y].Whendoingsoyouneedtomakesuretoincludethedefaultpredicateandfilterabove,ifyouwanttoretainthatfunctionality.Belowisanexampleofwhatthislookslike.
地址: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+'/(?.*)'" spring.cloud.gateway.discovery.locator.filters[1].args[replacement]:"'/${remaining}'"
根据文档介绍,依照这种方式,可以从注册中心获得断言与过滤器的配置
5:SpringGateWay从数据库配置路由
publicclassDBRouteDefinitionRepositoryimplementsRouteDefinitionRepository
项目中实现了RouteDefinitionRepository后,springgateway会采用你实现的这个类去加载路由,如果不实现则采用他默认的方式加载路由
publicclassDBRouteDefinitionRepositoryimplementsRouteDefinitionRepository{
//保存路由
privatefinalMaproutes=synchronizedMap(newLinkedHashMap());
privateLoggerlog=LoggerFactory.getLogger(DBRouteDefinitionRepository.class);
//初始標準
privatebooleaninit_flag=true;
//
privatefinalGatewayPropertiesproperties;
privateDynamicRouteServiceImplservice;
publicDBRouteDefinitionRepository(GatewayPropertiesproperties){
this.properties=properties;
this.service=newDynamicRouteServiceImpl();
}
@Override
publicFluxgetRouteDefinitions(){
if(init_flag){
ListrouteDefinitions=newArrayList<>();
Listrs=newArrayList<>();
try{
routeDefinitions=service.quertAllRoutes();//从数据库中加载route
rs=this.properties.getRoutes();//获得配置文件的route
for(RouteDefinitionrse:rs){
routeDefinitions.add(rse);
}
routes.clear();
routeDefinitions.forEach(x->routes.put(x.getId(),x));
init_flag=false;
}catch(Exceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
log.error("InitRouteFail,Can'tgetRoutes.",e);
}
returnFlux.fromIterable(routeDefinitions);
}else{
returnFlux.fromIterable(routes.values());
}
}
@Override
publicMonodelete(MonorouteId){
returnrouteId.flatMap(id->{
if(routes.containsKey(id)){
routes.remove(id);
returnMono.empty();
}
returnMono.defer(()->Mono.error(newNotFoundException("RouteDefinitionnotfound:"+routeId)));
});
}
@Override
publicMonosave(Monoroute){
returnroute.flatMap(r->{
routes.put(r.getId(),r);
returnMono.empty();
});
}
}
这个是我自己实现的类,这个类可以从数据库与配置文件中获得路由配置,从数据库中获得路由配置可以根据个人的要求来
@Validated
publicclassRouteDefinition{
@NotEmpty
privateStringid=UUID.randomUUID().toString();
@NotEmpty
@Valid
privateListpredicates=newArrayList<>();
@Valid
privateListfilters=newArrayList<>();
@NotNull
privateURIuri;
privateintorder=0;
publicRouteDefinition(){
}
publicRouteDefinition(Stringtext){
inteqIdx=text.indexOf('=');
if(eqIdx<=0){
thrownewValidationException("UnabletoparseRouteDefinitiontext'"+text
+"'"+",mustbeoftheformname=value");
}
setId(text.substring(0,eqIdx));
String[]args=tokenizeToStringArray(text.substring(eqIdx+1),",");
setUri(URI.create(args[0]));
for(inti=1;igetPredicates(){
returnpredicates;
}
publicvoidsetPredicates(Listpredicates){
this.predicates=predicates;
}
publicListgetFilters(){
returnfilters;
}
publicvoidsetFilters(Listfilters){
this.filters=filters;
}
publicURIgetUri(){
returnuri;
}
publicvoidsetUri(URIuri){
this.uri=uri;
}
publicintgetOrder(){
returnorder;
}
publicvoidsetOrder(intorder){
this.order=order;
}
@Override
publicbooleanequals(Objecto){
if(this==o){
returntrue;
}
if(o==null||getClass()!=o.getClass()){
returnfalse;
}
RouteDefinitionrouteDefinition=(RouteDefinition)o;
returnObjects.equals(id,routeDefinition.id)
&&Objects.equals(predicates,routeDefinition.predicates)
&&Objects.equals(order,routeDefinition.order)
&&Objects.equals(uri,routeDefinition.uri);
}
@Override
publicinthashCode(){
returnObjects.hash(id,predicates,uri);
}
@Override
publicStringtoString(){
return"RouteDefinition{"+"id='"+id+'\''+",predicates="+predicates
+",filters="+filters+",uri="+uri+",order="+order+'}';
}
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。