背景
最近在个人在学习整合SpringCloud,以往都是在公司框架中使用,或者零碎的学习部分。于是想系统的从零开始整合SC。昨天已经把sc框架搭建就绪。本篇博客是基于上一篇而来。如果未搭建好的请移步:https://blog.csdn.net/fly_west/article/details/122203075
本篇博客主要讲述整合gateway。用过网关的人都知道,网关路由转发学习阶段一般都是配置在配置文件里面在,不管是用yml还是Apollo等,都会面临一个问题那就是网关启动后,再新增微服务,修改配置文件后,需要重启服务。这个是一大弊端,因此本篇博客主要讲述mysql数据库维护网关配置。当然也可以再维护一份到redis中,我在这暂时没有这样做。只抛砖引玉实现了存储到mysql中。
网关实现
库表结构
CREATE TABLE `basic_gateway` (
`id` int(11) NOT NULL,
`system_id` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '系统编号',
`service_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '服务名称',
`uri` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '转发地址',
`predicates` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '访问前缀',
`filters` int(1) NULL DEFAULT NULL COMMENT '是否过滤',
`remarks` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`) USING BTREE
)
yml配置文件
server:
port: 8082
spring:
application:
name: demo-gateway
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
register-enabled: true
gateway:
discovery:
locator:
#让gateway通过服务发现组件找到其他的微服务
enabled: true
entity
@Data
@TableName("basic_gateway")
public class BasicGateway {
@TableId("id")
private long id;
@TableField("system_id")
private String systemId;
@TableField("service_name")
private String serviceName;
@TableField("uri")
private String uri;
@TableField("predicates")
private String predicates;
@TableField("filters")
private Integer filters;
@TableField("remarks")
private String remarks;
}
网关router实现类
@Component
@Slf4j
public class GateWayService implements ApplicationEventPublisherAware, CommandLineRunner {
private ApplicationEventPublisher publisher;
@Autowired
private RouteDefinitionWriter routeDefinitionWriter;
@Autowired
private GatewayMapper gatewayMapper;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
public void refresh() {
loadRouteConfig();
}
@Override
public void run(String... args) throws Exception {
//CommandLineRunner 项目启动时加载,且只加载一次
log.info("网关路由开始加载------------------------");
loadRouteConfig();
log.info("网关路由加载结束--------------------------");
}
private void loadRouteConfig() {
List<BasicGateway> gatewayList = gatewayMapper.selectList(null);
if (!CollectionUtils.isEmpty(gatewayList)) {
for (BasicGateway gateway : gatewayList) {
RouteDefinition definition = handleData(gateway);
routeDefinitionWriter.save(Mono.just(definition)).subscribe();
}
this.publisher.publishEvent(new RefreshRoutesEvent(this));
}
}
/**
* 数据库路由数据转换
*
* @return org.springframework.cloud.gateway.route.RouteDefinition
* @Author zhuiri
* @Date 2021/12/29 14:03
**/
private RouteDefinition handleData(BasicGateway gateway) {
RouteDefinition definition = new RouteDefinition();
Map<String, String> predicateParams = new HashMap<>(8);
PredicateDefinition predicate = new PredicateDefinition();
FilterDefinition filterDefinition = new FilterDefinition();
Map<String, String> filterParams = new HashMap<>(8);
URI url = null;
if (gateway.getUri().startsWith("http") || gateway.getUri().startsWith("https")) {
//http地址
url = UriComponentsBuilder.fromHttpUrl(gateway.getUri()).build().toUri();
} else {
//注册中心
url = UriComponentsBuilder.fromUriString("lb://" + gateway.getUri()).build().toUri();
}
definition.setId(String.valueOf(gateway.getId()));
predicate.setName("Path");
predicateParams.put("pattern", gateway.getPredicates() + "/**");
predicate.setArgs(predicateParams);
// 名称是固定的, 路径去前缀
filterDefinition.setName("StripPrefix");
filterParams.put("_genkey_0", gateway.getFilters().toString());
filterDefinition.setArgs(filterParams);
definition.setPredicates(Arrays.asList(predicate));
definition.setFilters(Arrays.asList(filterDefinition));
definition.setUri(url);
definition.setOrder(Integer.parseInt("0"));
return definition;
}
public void saveRoute(BasicGateway gateway) {
RouteDefinition definition = handleData(gateway);
routeDefinitionWriter.save(Mono.just(definition)).subscribe();
this.publisher.publishEvent(new RefreshRoutesEvent(this));
}
public void update(BasicGateway gateway) {
RouteDefinition definition = handleData(gateway);
try {
this.routeDefinitionWriter.delete(Mono.just(definition.getId()));
routeDefinitionWriter.save(Mono.just(definition)).subscribe();
this.publisher.publishEvent(new RefreshRoutesEvent(this));
} catch (Exception e) {
e.printStackTrace();
}
}
public void deleteRoute(String routeId) {
routeDefinitionWriter.delete(Mono.just(routeId)).subscribe();
this.publisher.publishEvent(new RefreshRoutesEvent(this));
}
}
此处扩充说了一下增删改查还有刷新功能
mapper文件
public interface GatewayMapper extends BaseMapper<BasicGateway> {
}
服务端
yml配置文件
server:
port: 8081
swagger:
title: demo_project
description: project description
version: 1.0
contactEmail: 123456@qq.com
spring:
application:
name: cloud-business
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
register-enabled: true
**注意:**此处一定要加register-enabled:true,否则网关就会报错Caused by: java.net.ConnectException: Connection timed out: no further information
如有问题,希望大家评论区留言多多指教!如觉得写得还可以,就给一个赞吧!