从0到1学SpringCloud——12 gateway 动态配置网关路由规则
目录
一、前言
二、动态路由
1、数据库设计
-
CREATE TABLE `zf_gateway_route` (
-
`route_id` varchar(16) NOT NULL DEFAULT '' COMMENT '路由id',
-
`uri` varchar(64) DEFAULT NULL COMMENT '路由地址',
-
`path_name` varchar(8) DEFAULT '' COMMENT 'path断言名称',
-
`path_pattern` varchar(32) DEFAULT NULL COMMENT 'path断言匹配路径',
-
`method_name` varchar(8) DEFAULT NULL COMMENT 'method断言名称',
-
`method_pattern` varchar(8) DEFAULT NULL COMMENT 'method匹配方法',
-
`msg_name` varchar(32) DEFAULT NULL COMMENT 'header断言名称',
-
`msg_type` varchar(64) DEFAULT NULL COMMENT '消息类型,多个值之间用,分割',
-
`filter_name` varchar(16) DEFAULT NULL COMMENT '过滤器名称',
-
`new_path` varchar(64) DEFAULT NULL COMMENT '转发地址',
-
`remark` varchar(32) DEFAULT NULL COMMENT '备注',
-
`status` int(2) DEFAULT NULL COMMENT '状态:0、停用;1、启用',
-
`index` int(2) DEFAULT NULL COMMENT '排序',
-
PRIMARY KEY (`route_id`)
-
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='网关路由信息表';
首先设计一张路由表,用来存储路由信息。
添加两条测试数据:
-
INSERT INTO `zf_gateway_route` (`route_id`, `uri`, `path_name`, `path_pattern`, `method_name`, `method_pattern`, `msg_name`, `msg_type`, `filter_name`, `new_path`, `remark`, `status`, `index`) VALUES ('zhufeng-route-csdn', 'https://blog.csdn.net/', 'Path', '/csdn/**', 'Method', 'Get', NULL, NULL, 'MsgPath', '/nav/java', '第三方测试', 0, 1);
-
INSERT INTO `zf_gateway_route` (`route_id`, `uri`, `path_name`, `path_pattern`, `method_name`, `method_pattern`, `msg_name`, `msg_type`, `filter_name`, `new_path`, `remark`, `status`, `index`) VALUES ('zhufeng-web-msg', 'lb://zhufeng-web-msg', 'Path', '/msg/info', 'Method', 'Get', NULL, NULL, NULL, NULL, '路由测试', 0, 2);
数据说明:
1、uri:路由地址,也就是通过配置的微服务或者http地址发送请求
2、path_name:断言规则,命名规则为: Name RoutePredicateFactory,
比如:数据库配置为 Path ,gateway会自动找到 PathRoutePredicateFactory 。
3、path_pattern:请求的路径规则进行适配
4、method_name:断言规则 ,为方便演示,把method单独列了一项,
调用 MethodRoutePredicateFactory 来校验是否为Get或Post请求。
2、路由代码
-
package com.zhufeng.gateway.db.route;
-
-
import com.alibaba.fastjson.JSONObject;
-
import com.zhufeng.gateway.db.service.GatewayService;
-
import org.springframework.cloud.gateway.filter.FilterDefinition;
-
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
-
import org.springframework.cloud.gateway.route.RouteDefinition;
-
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
-
import org.springframework.stereotype.Component;
-
import reactor.core.publisher.Flux;
-
import reactor.core.publisher.Mono;
-
-
import javax.annotation.PostConstruct;
-
import javax.annotation.Resource;
-
import java.net.URI;
-
import java.util.ArrayList;
-
import java.util.List;
-
-
/**
-
* @ClassName: ZhufengRouteDefinitionRepository
-
* @Description 动态配置路由规则
-
* @author 月夜烛峰
-
* @date 2022/9/15 19:38
-
*/
-
-
public class ZhufengRouteDefinitionRepository implements RouteDefinitionRepository {
-
-
private List<RouteDefinition> routeDefinitions = new ArrayList<RouteDefinition>();
-
-
-
private GatewayService gatewayService;
-
-
/**
-
* 初始化参数
-
*/
-
-
public void init() {
-
load();
-
}
-
-
/**
-
* 通过数据库配置路由规则
-
*/
-
private void load() {
-
List<JSONObject> routeList = gatewayService.findRouteList();
-
for(JSONObject routeJson:routeList) {
-
//配置路由规则
-
RouteDefinition route= new RouteDefinition();
-
route.setId(routeJson.getString("routeId"));
-
URI uri = URI.create(routeJson.getString("uri"));
-
route.setUri(uri);
-
//配置请求路径规则
-
PredicateDefinition path = new PredicateDefinition();
-
path.setName(routeJson.getString("pathName"));
-
path.addArg("pattern", routeJson.getString("pathPattern"));
-
route.getPredicates().add(path);
-
-
//配置方法规则:Get、Post等
-
PredicateDefinition method = new PredicateDefinition();
-
method.setName(routeJson.getString("methodName"));
-
String methodPattern = routeJson.getString("methodPattern");
-
String[] methodArr = methodPattern.split(",");
-
for(int i=0;i<methodArr.length;i ) {
-
method.addArg("pattern" 0, methodArr[i]);
-
}
-
route.getPredicates().add(method);
-
-
-
routeDefinitions.add(route);
-
-
}
-
-
}
-
-
-
public Flux<RouteDefinition> getRouteDefinitions() {
-
return Flux.fromIterable(routeDefinitions);
-
}
-
-
-
public Mono<Void> save(Mono<RouteDefinition> route) {
-
// TODO Auto-generated method stub
-
return null;
-
}
-
-
-
public Mono<Void> delete(Mono<String> routeId) {
-
// TODO Auto-generated method stub
-
return null;
-
}
-
-
}
Service比较简单:
-
public interface GatewayService {
-
-
public List<JSONObject> findRouteList();
-
}
Service实现:
-
-
public class GatewayServiceImpl implements GatewayService {
-
-
-
private GatewayMapper gatewayMapper;
-
-
-
public List<JSONObject> findRouteList() {
-
return gatewayMapper.findRouteList();
-
}
-
}
Mapper:
-
-
public interface GatewayMapper {
-
-
public List<JSONObject> findRouteList();
-
}
-
-
-
-
<mapper namespace="com.zhufeng.gateway.db.mapper.GatewayMapper">
-
-
<!--获取所有路由信息-->
-
<select id="findRouteList" resultType="com.alibaba.fastjson.JSONObject">
-
SELECT
-
route_id as routeId,
-
uri,
-
path_name as pathName,
-
path_pattern as pathPattern,
-
method_name as methodName,
-
method_pattern as methodPattern,
-
msg_name as msgName,
-
msg_type as msgType,
-
filter_name as filterName,
-
new_path as newPath,
-
remark
-
FROM
-
zf_gateway_route
-
WHERE status = 0
-
</select>
-
</mapper>
application.properties配置文件:
-
#服务端口
-
server.port=9990
-
#服务名称
-
spring.application.name=zhufeng-gateway-db
-
-
mybatis.type-aliases-package=com.zhufeng.gateway.db.mapper
-
mybatis.mapper-locations=classpath:mapper/*.xml
3、效果演示
启动前需先启动nacos服务端,再创建两个微服务 zhufeng-web-user、zhufeng-web-msg,
《从0到1学SpringCloud——11 gateway网关路由配置详解》有具体过程。
启动后先测试第一个路由规则,访问 http://127.0.0.1:9990/csdn/test
根据路由规则,会被转发到 blog.csdn.net ,/csdn/test 会被替换为 /nav/java
虽然地址栏还是显示csdn/test,但是实际已经路由到了csdn的java博客专栏,通过标题可以看出Java博客,说明第一个配置生效。
然后测试第二个路由规则,请求被转发到 zhufeng-web-msg 微服务。
启动zhufeng-web-msg微服务,写一个简单的Controller
-
/**
-
* @ClassName: MsgController
-
* @Description 消息路由测试
-
* @author 月夜烛峰
-
* @date 2022/7/22 20:33
-
*/
-
-
-
public class MsgController {
-
-
-
public String showInfo() {
-
return "good luck~";
-
}
-
-
}
为了方便演示Get请求和Post请求的不同,使用PostMan来测试,
分别请求 http://127.0.0.1:9990/msg/info
Get请求
Post请求
Get请求可以正常访问,Post请求被拦截,说明数据库配置的路由拦截条件生效。
三、自定义路由
1、代码实现
通过上述配置,简单了解了路由工厂的明明规范,我们可以遵循gateway定义自己的路由信息。
打开Gateway的源码,可以看到内部设置了很多断言规则,都有对应的路由工厂,途中标注的就是刚才用到的两个,仿照源码格式,我们写一个自己的路由工厂。
命名格式:Name RoutePredicateFactory
Name:ZhufengVersion
工厂类:ZhufengVersionRoutePredicateFactory
校验逻辑:
当发起post请求时,如果Head中的版本号为 1.0 或者版本号不存在时放行,否则拦截。
ZhufengVersionRoutePredicateFactory代码:
-
package com.zhufeng.gateway.db.route;
-
-
import lombok.extern.slf4j.Slf4j;
-
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
-
import org.springframework.cloud.gateway.handler.predicate.GatewayPredicate;
-
import org.springframework.stereotype.Component;
-
import org.springframework.validation.annotation.Validated;
-
import org.springframework.web.server.ServerWebExchange;
-
-
import java.util.Arrays;
-
import java.util.List;
-
import java.util.function.Predicate;
-
-
/**
-
* @ClassName: ZhufengVersionRoutePredicateFactory
-
* @Description 动态路由版本判断
-
* @author 月夜烛峰
-
* @date 2022/9/15 19:49
-
*/
-
-
-
public class ZhufengVersionRoutePredicateFactory extends AbstractRoutePredicateFactory<ZhufengVersionRoutePredicateFactory.Config> {
-
-
public static final String VERSION_KEY = "version";
-
-
public ZhufengVersionRoutePredicateFactory() {
-
super(Config.class);
-
}
-
-
-
public List<String> shortcutFieldOrder() {
-
return Arrays.asList(VERSION_KEY);
-
}
-
-
-
public Predicate<ServerWebExchange> apply(Config config) {
-
-
return new GatewayPredicate() {
-
-
public boolean test(ServerWebExchange exchange) {
-
String version = exchange.getRequest().getHeaders().getFirst("version");
-
log.info("系统版本:{},当前请求版本:{}", config.version, version);
-
if (config.version == null || config.version.length() == 0) {
-
log.info("默认不拦截...");
-
return true;
-
}
-
-
if (version == null || version.length() == 0) {
-
log.info("header中版本为空,不拦截...");
-
return true;
-
}
-
if (config.version.equals(version)) {
-
log.info("校验通过,请求放行!当前请求版本:{},系统要求版本:{}", version, config.version);
-
return true;
-
}
-
return false;
-
}
-
-
-
public String toString() {
-
return String.format("version: %s", config.version);
-
}
-
};
-
}
-
-
-
public static class Config {
-
-
-
private String version;
-
-
public String getVersion() {
-
return version;
-
}
-
-
public void setVersion(String version) {
-
this.version = version;
-
}
-
-
-
}
-
-
}
2、新增路由规则
修改ZhufengRouteDefinitionRepository代码,新增:
代码:
-
//自定义版本断言(仅作为演示),request请求中,只有版本为1.0时放行
-
PredicateDefinition version = new PredicateDefinition();
-
version.setName("ZhufengVersion");
-
version.addArg("version", "1.0");
-
route.getPredicates().add(version);
3、效果演示
通过PostMan测试,在Headers中新增version字段
当version为1.0时
当version为2.0时
控制台打印:
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhfjaaak
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
excel下划线不显示怎么办
PHP中文网 06-23 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
photoshop蒙版画笔没反应怎么办
PHP中文网 06-24