♻️ 重构代码。 动态路由加载DB

This commit is contained in:
冷冷 committed 2018-11-06 22:44:19 +08:00
1 parent e64d260712
commit a226c8b936
15 files changed
+317 -128

No files matched your search

@@ -17,6 +17,9 @@
package com.pig4cloud.pigx.common.gateway.configuration;
import org.springframework.cloud.gateway.config.GatewayProperties;
import org.springframework.cloud.gateway.config.PropertiesRouteDefinitionLocator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@@ -27,7 +30,16 @@ import org.springframework.context.annotation.Configuration;
* 动态路由配置类
*/
@Configuration
@ComponentScan("com.pig4cloud.pigx.common.gateway.support")
@ComponentScan("com.pig4cloud.pigx.common.gateway")
public class DynamicRouteAutoConfiguration {
/**
* 配置文件设置为空
* redis 加载为准
*
* @return
*/
@Bean
public PropertiesRouteDefinitionLocator propertiesRouteDefinitionLocator() {
return new PropertiesRouteDefinitionLocator(new GatewayProperties());
}
}
@@ -25,6 +25,7 @@ import org.springframework.beans.BeanUtils;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -65,8 +66,14 @@ public class RedisRouteDefinitionWriter implements RouteDefinitionRepository {
}
/**
* 动态路由入口
*
* @return
*/
@Override
public Flux<RouteDefinition> getRouteDefinitions() {
redisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<>(RouteDefinitionVo.class));
List<RouteDefinitionVo> values = redisTemplate.opsForHash().values(CommonConstant.ROUTE_KEY);
List<RouteDefinition> definitionList = new ArrayList<>();
values.forEach(vo -> {
@@ -3,54 +3,7 @@ spring:
gateway:
locator:
enabled: true
routes:
# 认证中心
- id: pigx-auth
uri: lb://pigx-auth
predicates:
- Path=/auth/**
filters:
# 验证码处理
- ValidateCodeGatewayFilter
# 前端密码解密
- PasswordDecoderFilter
#UPMS 模块
- id: pigx-upms
uri: lb://pigx-upms
predicates:
- Path=/admin/**
filters:
# 限流配置
- name: RequestRateLimiter
args:
key-resolver: '#{@remoteAddrKeyResolver}'
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
# 降级配置
- name: Hystrix
args:
name: default
fallbackUri: 'forward:/fallback'
# 代码生成模块
- id: pigx-codegen
uri: lb://pigx-codegen
predicates:
- Path=/gen/**
# 定时任务模块
- id: pigx-daemon
uri: lb://pigx-daemon
predicates:
- Path=/daemon/**
# 分布式事务管理模块
- id: pigx-tx-manager
uri: lb://pigx-tx-manager
predicates:
- Path=/tx/**
# 工作流管理模块
- id: pigx-activiti
uri: lb://pigx-activiti
predicates:
- Path=/act/**
security:
encode:
# 前端密码密钥,必须16位
@@ -0,0 +1,83 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.admin.api.entity;
import com.baomidou.mybatisplus.activerecord.Model;
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableName;
import com.baomidou.mybatisplus.enums.IdType;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 路由
*
* @author lengleng
* @date 2018-11-06 10:17:18
*/
@Data
@TableName("sys_route_conf")
@EqualsAndHashCode(callSuper = true)
public class SysRouteConf extends Model<SysRouteConf> {
private static final long serialVersionUID = 1L;
/**
* 路由ID
*/
@TableId(type = IdType.INPUT)
private String routeId;
/**
* 断言
*/
private String predicates;
/**
* 过滤器
*/
private String filters;
/**
*
*/
private String uri;
/**
* 排序
*/
private Integer order;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 修改时间
*/
private LocalDateTime updateTime;
/**
* 删除标记
*/
private String delFlag;
/**
* 主键值
*/
@Override
protected Serializable pkVal() {
return this.routeId;
}
}
+6
View File
@@ -72,6 +72,12 @@
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-security</artifactId>
</dependency>
<!--支持动态路由配置 -->
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common-gateway</artifactId>
<version>${pigx.version}</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>com.baomidou</groupId>
@@ -15,16 +15,21 @@
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.common.gateway.support;
package com.pig4cloud.pigx.admin.config;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.pig4cloud.pigx.admin.service.SysRouteConfService;
import com.pig4cloud.pigx.common.core.constant.CommonConstant;
import com.pig4cloud.pigx.common.gateway.support.DynamicRouteInitEvent;
import com.pig4cloud.pigx.common.gateway.vo.RouteDefinitionVo;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.boot.web.context.WebServerInitializedEvent;
import org.springframework.cloud.gateway.config.GatewayProperties;
import org.springframework.cloud.gateway.config.PropertiesRouteDefinitionLocator;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.EventListener;
@@ -33,6 +38,8 @@ import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.scheduling.annotation.Async;
import java.net.URI;
/**
* @author lengleng
* @date 2018/10/31
@@ -44,7 +51,7 @@ import org.springframework.scheduling.annotation.Async;
@AllArgsConstructor
public class DynamicRouteInitRunner {
private final RedisTemplate redisTemplate;
private final GatewayProperties gatewayProperties;
private final SysRouteConfService routeConfService;
@Async
@Order
@@ -53,12 +60,20 @@ public class DynamicRouteInitRunner {
Boolean result = redisTemplate.delete(CommonConstant.ROUTE_KEY);
log.info("初始化网关路由 {} ", result);
gatewayProperties.getRoutes().forEach(route -> {
routeConfService.routes().forEach(route -> {
RouteDefinitionVo vo = new RouteDefinitionVo();
BeanUtils.copyProperties(route, vo);
log.info("加载路由ID:{},{}", route.getId(), vo);
vo.setId(route.getRouteId());
vo.setUri(URI.create(route.getUri()));
vo.setOrder(route.getOrder());
JSONArray filterObj = JSONUtil.parseArray(route.getFilters());
vo.setFilters(filterObj.toList(FilterDefinition.class));
JSONArray predicateObj = JSONUtil.parseArray(route.getPredicates());
vo.setPredicates(predicateObj.toList(PredicateDefinition.class));
log.info("加载路由ID:{},{}", route.getRouteId(), vo);
redisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<>(RouteDefinitionVo.class));
redisTemplate.opsForHash().put(CommonConstant.ROUTE_KEY, route.getId(), vo);
redisTemplate.opsForHash().put(CommonConstant.ROUTE_KEY, route.getRouteId(), vo);
});
log.debug("初始化网关路由结束 ");
}
@@ -44,7 +44,7 @@ import java.util.List;
@Configuration
@MapperScan("com.pig4cloud.pigx.admin.mapper")
public class MybatisPlusConfigurer {
private static final String[] IGNORETABLES = new String[]{"sys_dept_relation", "sys_role_dept", "sys_role_menu", "sys_user_role"};
private static final String[] IGNORETABLES = new String[]{"sys_dept_relation", "sys_role_dept", "sys_role_menu", "sys_user_role", "sys_route_conf"};
/**
* 分页插件
@@ -15,39 +15,36 @@
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.common.gateway.support;
package com.pig4cloud.pigx.admin.controller;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONArray;
import com.pig4cloud.pigx.admin.service.SysRouteConfService;
import com.pig4cloud.pigx.common.core.util.R;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Mono;
import java.util.Map;
/**
* 路由
*
* @author lengleng
* @date 2018/10/31
* <p>
* 动态路由业务端点
* @date 2018-11-06 10:17:18
*/
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/route")
public class DynamicRouteEndpoint {
private final DynamicRouteHandler dynamicRouteHandler;
public class SysRouteConfController {
private final SysRouteConfService sysRouteConfService;
/**
* 获取当前定义的路由信息
*
* @return {"id":"RouteDefinition"}
* @return
*/
@GetMapping
public Mono<Map<String, RouteDefinition>> routes() {
return dynamicRouteHandler.routes();
public R routes() {
return new R<>(sysRouteConfService.routes());
}
/**
@@ -57,17 +54,8 @@ public class DynamicRouteEndpoint {
* @return
*/
@PutMapping
public R edit(@RequestBody JSONObject routes) {
return new R(dynamicRouteHandler.editRoutes(routes));
public R edit(@RequestBody JSONArray routes) {
return new R(sysRouteConfService.editRoutes(routes));
}
/**
* 回滚初始化配置
*
* @return
*/
@GetMapping("/fallback")
public Mono<R> fallback() {
return Mono.just(new R(dynamicRouteHandler.fallback()));
}
}
@@ -0,0 +1,33 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.admin.mapper;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.pig4cloud.pigx.admin.api.entity.SysRouteConf;
import org.apache.ibatis.annotations.Mapper;
/**
* 路由
*
* @author lengleng
* @date 2018-11-06 10:17:18
*/
@Mapper
public interface SysRouteConfMapper extends BaseMapper<SysRouteConf> {
}
@@ -0,0 +1,53 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.admin.service;
import cn.hutool.json.JSONArray;
import com.baomidou.mybatisplus.service.IService;
import com.pig4cloud.pigx.admin.api.entity.SysRouteConf;
import reactor.core.publisher.Mono;
import java.util.List;
/**
* 路由
*
* @author lengleng
* @date 2018-11-06 10:17:18
*/
public interface SysRouteConfService extends IService<SysRouteConf> {
/**
* 获取全部路由
* <p>
* RedisRouteDefinitionWriter.java
* PropertiesRouteDefinitionLocator.java
*
* @return
*/
List<SysRouteConf> routes();
/**
* 更新路由信息
*
* @param routes 路由信息
* @return
*/
Mono<Void> editRoutes(JSONArray routes);
}
@@ -15,48 +15,46 @@
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.common.gateway.support;
package com.pig4cloud.pigx.admin.service.impl;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.pig4cloud.pigx.admin.api.entity.SysRouteConf;
import com.pig4cloud.pigx.admin.mapper.SysRouteConfMapper;
import com.pig4cloud.pigx.admin.service.SysRouteConfService;
import com.pig4cloud.pigx.common.core.constant.CommonConstant;
import com.pig4cloud.pigx.common.gateway.vo.RouteDefinitionVo;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
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.RouteDefinitionLocator;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @author lengleng
* @date 2018/10/31
* @date 2018年11月06日10:27:55
* <p>
* 动态路由操作类
* see GatewayControllerEndpoint.java
* 动态路由处理类
*/
@Slf4j
@Service
public class DynamicRouteHandler implements ApplicationEventPublisherAware {
private final RouteDefinitionLocator routeDefinitionLocator;
@AllArgsConstructor
@Service("sysRouteConfService")
public class SysRouteConfServiceImpl extends ServiceImpl<SysRouteConfMapper, SysRouteConf> implements SysRouteConfService {
private final RedisTemplate redisTemplate;
private ApplicationEventPublisher applicationEventPublisher;
private final ApplicationEventPublisher applicationEventPublisher;
public DynamicRouteHandler(RedisTemplate redisTemplate
, RouteDefinitionLocator routeDefinitionLocator) {
this.redisTemplate = redisTemplate;
this.routeDefinitionLocator = routeDefinitionLocator;
}
/**
* 获取全部路由
@@ -66,9 +64,11 @@ public class DynamicRouteHandler implements ApplicationEventPublisherAware {
*
* @return
*/
public Mono<Map<String, RouteDefinition>> routes() {
return routeDefinitionLocator.getRouteDefinitions()
.collectMap(RouteDefinition::getId);
@Override
public List<SysRouteConf> routes() {
SysRouteConf condition = new SysRouteConf();
condition.setDelFlag(CommonConstant.STATUS_NORMAL);
return baseMapper.selectList(new EntityWrapper<>(condition));
}
/**
@@ -77,16 +77,20 @@ public class DynamicRouteHandler implements ApplicationEventPublisherAware {
* @param routes 路由信息
* @return
*/
public Mono<Void> editRoutes(JSONObject routes) {
@Override
public Mono<Void> editRoutes(JSONArray routes) {
// 清空Redis 缓存
Boolean result = redisTemplate.delete(CommonConstant.ROUTE_KEY);
log.info("清空网关路由 {} ", result);
routes.forEach((key, value) -> {
log.info("更新路由 -> {} ->{}", key, value);
// 遍历修改的routes,保存到Redis
List<RouteDefinitionVo> routeDefinitionVoList = new ArrayList<>();
routes.forEach(value -> {
log.info("更新路由 ->{}", value);
RouteDefinitionVo vo = new RouteDefinitionVo();
Map<String, Object> map = (Map) value;
Object id = map.get("id");
Object id = map.get("routeId");
if (id != null) {
vo.setId(String.valueOf(id));
}
@@ -118,25 +122,24 @@ public class DynamicRouteHandler implements ApplicationEventPublisherAware {
}
redisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<>(RouteDefinitionVo.class));
redisTemplate.opsForHash().put(CommonConstant.ROUTE_KEY, key, vo);
redisTemplate.opsForHash().put(CommonConstant.ROUTE_KEY, vo.getId(), vo);
routeDefinitionVoList.add(vo);
});
// 更新或保存routes,保存到DB
routeDefinitionVoList.forEach(vo -> {
SysRouteConf routeConf = new SysRouteConf();
routeConf.setRouteId(vo.getId());
routeConf.setFilters(JSONUtil.toJsonStr(vo.getFilters()));
routeConf.setPredicates(JSONUtil.toJsonStr(vo.getPredicates()));
routeConf.setOrder(vo.getOrder());
routeConf.setUri(vo.getUri().toString());
this.insertOrUpdate(routeConf);
});
log.debug("更新网关路由结束 ");
this.applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));
return Mono.empty();
}
/**
* 回滚路由
*
* @return
*/
public Mono<Void> fallback() {
this.applicationEventPublisher.publishEvent(new DynamicRouteInitEvent(this));
return Mono.empty();
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
}
@@ -16,6 +16,8 @@ spring:
discovery:
enabled: true
service-id: pigx-config
autoconfigure:
exclude: org.springframework.cloud.gateway.config.GatewayClassPathWarningAutoConfiguration
# 注册中心配置
eureka:
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2018-2025, lengleng All rights reserved.
~
~ Redistribution and use in source and binary forms, with or without
~ modification, are permitted provided that the following conditions are met:
~
~ Redistributions of ource code must retain the above copyright notice,
~ this list of conditions and the following disclaimer.
~ Redistributions in binary form must reproduce the above copyright
~ notice, this list of conditions and the following disclaimer in the
~ documentation and/or other materials provided with the distribution.
~ Neither the name of the pig4cloud.com developer nor the names of its
~ contributors may be used to endorse or promote products derived from
~ this software without specific prior written permission.
~ Author: lengleng (wangiegie@gmail.com)
-->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.pig4cloud.pigx.generator.mapper.SysRouteConfMapper">
<!-- 可根据自己的需求,是否要使用 -->
<resultMap type="com.pig4cloud.pigx.admin.api.entity.SysRouteConf" id="sysRouteConfMap">
<result property="routeId" column="route_id"/>
<result property="predicates" column="predicates"/>
<result property="filters" column="filters"/>
<result property="uri" column="uri"/>
<result property="order" column="order"/>
<result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/>
<result property="delFlag" column="del_flag"/>
</resultMap>
</mapper>
@@ -19,8 +19,8 @@ import java.time.LocalDateTime;
* @date ${datetime}
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("${tableName}")
@EqualsAndHashCode(callSuper = true)
public class ${className} extends Model<${className}> {
private static final long serialVersionUID = 1L;
@@ -18,16 +18,14 @@
package com.pig4cloud.pigx.manager;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.SpringCloudApplication;
/**
* @author LCN
* @author lengleng
* tx-manager ,进行了代码逻辑和代码规范重构
*/
@SpringBootApplication
@EnableDiscoveryClient
@SpringCloudApplication
public class PigxTxManagerApplication {