Spring Cloud Gateway编码实现任意地址跳转-即时焦点
(资料图片仅供参考)
欢迎访问我的GitHub本篇概览作为《Spring Cloud Gateway实战》系列的第十四篇,本文会继续发掘Spring Cloud Gateway的潜力,通过编码体验操控网关的乐趣,开发出一个实用的功能:让Spring Cloud Gateway应用在收到请求后,可以按照业务的需要跳转到任意的地址去一般路由规则先来看一个普通的路由规则,如下所示,意思是将所有/hello/**的请求转发到http://127.0.0.1:8082这个地址去:这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos
spring: application: name: hello-gateway cloud: gateway: routes: - id: path_route uri: http://127.0.0.1:8082 predicates: - Path=/hello/**
上述规则的功能如下图所示,假设这就是生产环境的样子,192.168.50.99:8082是提供服务的后台应用:特殊规则以上是常规情况,但也有些特殊情况,要求SpringCloud Gateway把浏览器的请求转发到不同的服务上去如下图所示,在之前的环境中增加了另一个服务(即蓝色块),假设蓝色服务代表测试环境浏览器发起的/hello/str请求中,如果header中带有tag-test-user,并且值等于true,此时要求SpringCloud Gateway把这个请求转发到测试环境如果浏览器的请求header中没有tag-test-user,SpringCloud Gateway需要像以前那样继续转发到192.168.50.99:8082很明显,上述需求难以通过配置来实现,因为转发的地址和转发逻辑都是围绕业务逻辑来定制的,这也就是本篇的目标:对同一个请求path,可以通过编码转发到不同的地方去实现上述功能的具体做法是:自定义过滤器设计编码之前先设计,把关键点想清楚再动手今天咱们要开发一个SpringCloud Gateway应用,里面新增一个自定义过滤器实现这个功能需要三个知识点作为基础,也就是说,您会通过本篇实战掌握以下知识点:自定义过滤器自定义过滤器的配置参数和bean的映射编码构造Route实例用思维导图将具体工作内容展开,如下图所示,咱们就按部就班的实现吧:源码下载本篇实战中的完整源码可在GitHub下载到,地址和链接信息如下表所示(https://github.com/zq2599/blog_demos):名称 | 链接 | 备注 |
---|---|---|
项目主页 | https://github.com/zq2599/blog_demos | 该项目在GitHub上的主页 |
git仓库地址(https) | https://github.com/zq2599/blog_demos.git | 该项目源码的仓库地址,https协议 |
git仓库地址(ssh) | git@github.com:zq2599/blog_demos.git | 该项目源码的仓库地址,ssh协议 |
spring-cloud-tutorials com.bolingcavalry 1.0-SNAPSHOT 4.0.0 gateway-dynamic-route com.bolingcavalry common ${project.version} org.springframework.cloud spring-cloud-starter-gateway org.springframework.boot spring-boot-maven-plugin com.bolingcavalry.gateway.GatewayDynamicRouteApplication repackage
启动类是普通的SpringBoot启动类:package com.bolingcavalry.gateway;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplicationpublic class GatewayDynamicRouteApplication { public static void main(String[] args) { SpringApplication.run(GatewayDynamicRouteApplication.class,args); }}
接下来是本篇的核心,自定义过滤器类,代码中已经添加了详细的注释,有几处要注意的地方稍后会提到:package com.bolingcavalry.gateway.filter;import lombok.Data;import lombok.ToString;import lombok.extern.slf4j.Slf4j;import org.springframework.cloud.gateway.filter.GatewayFilter;import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;import org.springframework.cloud.gateway.route.Route;import org.springframework.http.HttpHeaders;import org.springframework.http.HttpMethod;import org.springframework.http.server.reactive.ServerHttpRequest;import org.springframework.stereotype.Component;import org.springframework.util.MultiValueMap;import org.springframework.web.util.UriComponentsBuilder;import java.net.URI;import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR;@Component@Slf4jpublic class BizLogicRouteGatewayFilterFactory extends AbstractGatewayFilterFactory { private static final String TAG_TEST_USER = "tag-test-user"; public BizLogicRouteGatewayFilterFactory() { super(BizLogicRouteConfig.class); } @Override public GatewayFilter apply(BizLogicRouteConfig config) { return (exchange, chain) -> { // 本次的请求对象 ServerHttpRequest request = exchange.getRequest(); // 调用方请求时的path String rawPath = request.getURI().getRawPath(); log.info("rawPath [{}]", rawPath); // 请求头 HttpHeaders headers = request.getHeaders(); // 请求方法 HttpMethod httpMethod = request.getMethod(); // 请求参数 MultiValueMap queryParams = request.getQueryParams(); // 这就是定制的业务逻辑,isTestUser等于ture代表当前请求来自测试用户,需要被转发到测试环境 boolean isTestUser = false; // 如果header中有tag-test-user这个key,并且值等于true(不区分大小写), // 就认为当前请求是测试用户发来的 if (headers.containsKey(TAG_TEST_USER)) { String tageTestUser = headers.get(TAG_TEST_USER).get(0); if ("true".equalsIgnoreCase(tageTestUser)) { isTestUser = true; } } URI uri; if (isTestUser) { log.info("这是测试用户的请求"); // 从配置文件中得到测试环境的uri uri = UriComponentsBuilder.fromHttpUrl(config.getTestEnvUri() + rawPath).queryParams(queryParams).build().toUri(); } else { log.info("这是普通用户的请求"); // 从配置文件中得到正式环境的uri uri = UriComponentsBuilder.fromHttpUrl(config.getProdEnvUri() + rawPath).queryParams(queryParams).build().toUri(); } // 生成新的Request对象,该对象放弃了常规路由配置中的spring.cloud.gateway.routes.uri字段 ServerHttpRequest serverHttpRequest = request.mutate().uri(uri).method(httpMethod).headers(httpHeaders -> httpHeaders = httpHeaders).build(); // 取出当前的route对象 Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR); //从新设置Route地址 Route newRoute = Route.async().asyncPredicate(route.getPredicate()).filters(route.getFilters()).id(route.getId()) .order(route.getOrder()).uri(uri).build(); // 放回exchange中 exchange.getAttributes().put(GATEWAY_ROUTE_ATTR,newRoute); // 链式处理,交给下一个过滤器 return chain.filter(exchange.mutate().request(serverHttpRequest).build()); }; } /** * 这是过滤器的配置类,配置信息会保存在此处 */ @Data @ToString public static class BizLogicRouteConfig { // 生产环境的服务地址 private String prodEnvUri; // 测试环境的服务地址 private String testEnvUri; }}
上述代码中要注意的地方如下:BizLogicRouteConfig是过滤器的配置类,可以在使用过滤器时在配置文件中配置prodEnvUri和testEnvUri的值,在代码中可以通过这两个字段取得配置值过滤器的工厂类名为BizLogicRouteGatewayFilterFactory,按照规则,过滤器的名字是BizLogicRoute在apply方法中,重新创建ServerHttpRequest和Route对象,它们的参数可以按照业务需求随意设置,然后再将这两个对象设置给SpringCloud gateway的处理链中,接下来,处理链上的其他过滤拿到的就是新的ServerHttpRequest和Route对象了配置假设生产环境地址是http://127.0.0.1:8082,测试环境地址是http://127.0.0.1:8087,整个SpringCloud Gateway应用的配置文件如下,可见使用了刚刚创建的过滤器,并且为此过滤器配置了两个参数:server: #服务端口 port: 8086spring: application: name: gateway-dynamic-route cloud: gateway: routes: - id: path_route uri: http://0.0.0.0:8082 predicates: - Path=/hello/** filters: - name: BizLogicRoute args: prodEnvUri: http://127.0.0.1:8082 testEnvUri: http://127.0.0.1:8087
至此,编码完成了,启动这个服务开发和启动后台服务,模拟生产和测试环境接下来开始验证功能是否生效,咱们要准备两个后台服务:模拟生产环境的后台服务是provider-hello,监听端口是8082,其/hello/str接口的返回值是Hello World, 2021-12-12 10:53:09模拟测试环境的后台服务是provider-for-test-user,监听端口是8087,其/hello/str接口的返回值是Hello World, 2021-12-12 10:57:11 (from test enviroment)(和生产环境相比,返回内容多了个(from test enviroment)),对应Controller参考如下:package com.bolingcavalry.provider.controller;import com.bolingcavalry.common.Constants;import org.springframework.web.bind.annotation.*;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Map;@RestController@RequestMapping("/hello")public class Hello { private String dateStr(){ return new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date()); } /** * 返回字符串类型 * @return */ @GetMapping("/str") public String helloStr() { return Constants.HELLO_PREFIX + ", " + dateStr() + " (from test enviroment)"; }}
以上两个服务,对应的代码都在我的Github仓库中,如下图红框所示:启动gateway-dynamic-route、provider-hello、provider-for-test-user服务此时,SpringCloud gateway应用和两个后台服务都启动完成,情况如下图,接下来验证刚才开发的过滤器能不能像预期那样转发:验证用postman工具向gateway-dynamic-route应用发起一次请求,返回值如下图红框所示,证明这是provider-hello的响应,看来咱们的请求已经正常到达:再发送一次请求,如下图,这次在header中加入键值对,得到的结果是provider-for-test-user的响应至此,过滤器的开发和验证已经完成,通过编码,可以把外部请求转发到任何咱们需要的地址去,并且支持参数配置,这个过滤器还有一定的可配置下,减少了硬编码的比率,如果您正在琢磨如何深度操控SpringCloud Gateway,希望本文能给您一些参考;欢迎关注博客园:程序员欣宸学习路上,你不孤单,欣宸原创一路相伴...
关键词:
- 国家移民管理局暂停签发韩国、日本公民来华口岸签证及72/144小时过境免签-环球滚动
- 港股异动 | 药明生物(02269)升7% 近三月北水增仓超5个百分点 机构料全年业绩持续高增
- 当前快报:美国小企业乐观度降至近十年来倒数第二
- 英文爱情的句子唯美句子大全(精选259句)
- 粤港澳大湾区中小企业报告:逾6成中小企业预期2023年将投放可观资金于大湾区_天天热文
- 山西泽州警方摧毁省级目标贩毒网络 17名毒贩累计贩毒超30公斤 今日热门
- 安逸花网贷8万逾期还不起我会不会被起诉 全球快播
- 有意思小周刊(2023.01.09):一文详解|影响成长的关键思考_世界消息
- 当前要闻:电子车牌板块1月9日跌0.11%,易华录领跌,主力资金净流出6738.9万元
- 省呗网贷逾期14年多久会上征信
-
目前距离NBA交易截止日仅剩下一个多月的时间
目前距离NBA交易截止日仅剩下一个多月的时间,这也导致近段时间出现不
-
热资讯!提升服务贸易还有大空间
知识密集型服务附加值高、成长性好,是当前全球服务贸易的一个重要发展
-
鸟叔江南style是哪一年火的(江南style鸟叔原名叫什么简介介绍)-世界热头条
对于江南style鸟叔原名叫什么这个问题感兴趣的朋友应该很多,这个也是
-
环球观焦点:宁夏平罗县鼓楼商圈组织开展“安全隐患大排查”活动
中工网讯6月23日,在宁夏回族自治区石嘴山市平罗县总工会的部署下,平
-
灌区渠道内提前蓄水保障农田用水 保证粮食安全 焦点关注
近日,辽宁省出现连续高温晴热天气,多地发布了高温橙色预警,农业用水
-
我国拟立法保障粮食安全 环球新消息
为保障粮食有效供给,确保国家粮食安全,提高防范和抵御粮食安全风险能
-
苹果手机怎么改ip地址_苹果手机怎么改id密码 环球热资讯
1、打开iPhone,找到桌面上的“设置”图标,如图。2、点击“设置”进入
-
天天关注:加码负极材料一体化 贝特瑞和京阳科技合资项目正式投产
6月26日,瑞阳新能源年产4万吨新能源锂电池材料一体化项目和年产6万吨
-
【研华科技】参评“维科杯·OFweek 2023人工智能行业年度评选” 环球热闻
维科杯·OFweek2023(第八届)物联网与人工智能行业年度评选(OFweek8t
-
全球速看:6月26日济南金昊新戊二醇价格暂稳
6月26日,济南金昊化工有限公司万华新戊二醇经销价格为10000元 吨,报
X 关闭
Spring Cloud Gateway编码实现任意地址跳转-即时焦点
翻译:WTA上周回眸:科维托娃手感火热剑指温网,朱琳登上荣誉榜_天天热点评
视频文件损坏无法播放怎么办(视频文件打不开) 动态焦点
热推荐:恶魔城暗影之王3_《恶魔城:暗影之王》pc正式版图文流程攻略
不能分手的分手伴奏(关于不能分手的分手伴奏的基本详情介绍)
X 关闭
得知西安疫情防控“升级” 男子夜骑共享单车回咸阳淳化
中国医生将任SIU主席背后:从追随者同行者到引领者
海南省通报政法队伍教育整顿成果
云南两地发现核酸阳性人员 西安实行最严格的社会面管控
广东梅州大埔中央红色交通线沿线发现多株百岁古树