SpringCloud Gateway众所周知是微服务全家桶中的网关服务,在微服务前面作为网关接受请求访问的一道门槛,想要通过这道门槛访问到后面的微服务,必须在这道门槛内部配置相应的路由,即可以转到后面具体的微服务地址,下面介绍三种方式的路由配置,其中两种比较常用,第三种是为了配合实际的项目需求,自己摸索出来的方式 ,仅供参考。
第一种,配置文件的方式,就是yml中配置路由
spring: cloud: gateway: routes: - id: baidu_route uri: https://www.baidu.com predicates: - Path=/
第二种,RouteLocatorBuilder的方式,通过Bean注入
publicRouteLocatorcustomRouteLocator(RouteLocatorBuilderbuilder) { returnbuilder.routes() .route("baidu_route", r->r.path("/") .uri("https://www.baidu.com")) .build(); }
第三种,通过底层的API即RouteDefinitionWriter的方式,按照底层的元数据定义类RouteDefinition直接组装路由信息,然后手动的保存到路由网关里,最重要的是需要有个事件广播机制,让Gateway感知到路由的变化
importorg.springframework.beans.factory.annotation.Autowired; importorg.springframework.cloud.gateway.event.RefreshRoutesEvent; importorg.springframework.cloud.gateway.route.RouteDefinition; importorg.springframework.cloud.gateway.route.RouteDefinitionWriter; importorg.springframework.cloud.gateway.support.NotFoundException; importorg.springframework.context.ApplicationEventPublisher; importorg.springframework.context.ApplicationEventPublisherAware; importorg.springframework.http.ResponseEntity; importorg.springframework.stereotype.Service; importreactor.core.publisher.Mono; /*** 动态路由服务*/publicclassDynamicRouteServiceImplimplementsApplicationEventPublisherAware{ privateRouteDefinitionWriterrouteDefinitionWriter; privateApplicationEventPublisherpublisher; publicvoidsetApplicationEventPublisher(ApplicationEventPublisherapplicationEventPublisher) { this.publisher=applicationEventPublisher; } //增加路由publicStringadd(RouteDefinitiondefinition) { routeDefinitionWriter.save(Mono.just(definition)).subscribe(); this.publisher.publishEvent(newRefreshRoutesEvent(this)); return"success"; } //更新路由publicStringupdate(RouteDefinitiondefinition) { try { delete(definition.getId()); } catch (Exceptione) { return"update fail,not find route routeId: "+definition.getId(); } try { routeDefinitionWriter.save(Mono.just(definition)).subscribe(); this.publisher.publishEvent(newRefreshRoutesEvent(this)); return"success"; } catch (Exceptione) { return"update route fail"; } } //删除路由publicMono<ResponseEntity<Object>>delete(Stringid) { returnthis.routeDefinitionWriter.delete(Mono.just(id)).then(Mono.defer(() -> { returnMono.just(ResponseEntity.ok().build()); })).onErrorResume((t) -> { returntinstanceofNotFoundException; }, (t) -> { returnMono.just(ResponseEntity.notFound().build()); }); } }
importcom.example.demo.service.DynamicRouteServiceImpl; importorg.springframework.beans.factory.annotation.Autowired; importorg.springframework.boot.ApplicationArguments; importorg.springframework.boot.ApplicationRunner; importorg.springframework.cloud.gateway.handler.predicate.PredicateDefinition; importorg.springframework.cloud.gateway.route.RouteDefinition; importorg.springframework.stereotype.Component; importjava.net.URI; importjava.util.ArrayList; importjava.util.HashMap; importjava.util.List; importjava.util.Map; publicclassInitRouteRunnerimplementsApplicationRunner { privateDynamicRouteServiceImpldynamicRouteService; publicvoidrun(ApplicationArgumentsargs) throwsException { RouteDefinitiondefinition=newRouteDefinition(); definition.setId("baidu_route"); //设置断言List<PredicateDefinition>pdList=newArrayList<>(); PredicateDefinitionpredicate=newPredicateDefinition(); Map<String, String>argsMap=newHashMap<>(); argsMap.put("Path","/"); predicate.setArgs(argsMap); predicate.setName("Path"); pdList.add(predicate); definition.setPredicates(pdList); definition.setUri(newURI("https://www.baidu.com")); dynamicRouteService.add(definition); } }
给出了例子都是项目启动的时候初始化好的数据,上面三种方式都实现了http://ip:port/baidu跳转到百度首页的效果。
为什么要用第三种方式,其实是一个误解,我们有个项目是api总线项目,需要动态的管理一些api接口,有些是自己的有些是第三方的,本来是通过httpconnection的方式去转发的,后来改用了SpringCloud Gateway,想法是这个比较专业,性能会比较好,我们只做业务上的数据维护即可,活生生的把SpringCloud Gateway当Nginx去用了。如果各位感兴趣可以用到自己的业务中。