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 publicFlux getRouteDefinitions(){ if(init_flag){ List routeDefinitions=newArrayList<>(); List rs=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 publicMono delete(Mono routeId){ returnrouteId.flatMap(id->{ if(routes.containsKey(id)){ routes.remove(id); returnMono.empty(); } returnMono.defer(()->Mono.error(newNotFoundException("RouteDefinitionnotfound:"+routeId))); }); } @Override publicMono save(Mono route){ returnroute.flatMap(r->{ routes.put(r.getId(),r); returnMono.empty(); }); } }
这个是我自己实现的类,这个类可以从数据库与配置文件中获得路由配置,从数据库中获得路由配置可以根据个人的要求来
@Validated publicclassRouteDefinition{ @NotEmpty privateStringid=UUID.randomUUID().toString(); @NotEmpty @Valid privateListpredicates=newArrayList<>(); @Valid privateList filters=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;i getPredicates(){ returnpredicates; } publicvoidsetPredicates(List predicates){ this.predicates=predicates; } publicList getFilters(){ returnfilters; } publicvoidsetFilters(List filters){ 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(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。