diff --git a/pom.xml b/pom.xml
index ce9b601720eb212c604b1a763df40579463fb608..ec9f8100405137f10018b31b1ebf9ceecc7b4f9a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -61,7 +61,12 @@
commons-beanutils
commons-beanutils
- 1.8.3
+ 1.9.4
+
+
+ commons-lang
+ commons-lang
+ 2.6
com.alibaba
diff --git a/src/main/java/cn/bugstack/middleware/db/router/DBContextHolder.java b/src/main/java/cn/bugstack/middleware/db/router/DBContextHolder.java
new file mode 100644
index 0000000000000000000000000000000000000000..7a942d986c1b07afa48dbf72805d66620fc9a428
--- /dev/null
+++ b/src/main/java/cn/bugstack/middleware/db/router/DBContextHolder.java
@@ -0,0 +1,38 @@
+package cn.bugstack.middleware.db.router;
+
+/**
+ * 博客:https://bugstack.cn - 沉淀、分享、成长,让自己和他人都能有所收获!
+ * 公众号:bugstack虫洞栈
+ * Create by 小傅哥(fustack)
+ */
+public class DBContextHolder {
+
+ private static final ThreadLocal dbKey = new ThreadLocal();
+ private static final ThreadLocal tbKey = new ThreadLocal();
+
+ public static void setDBKey(String dbKeyIdx){
+ dbKey.set(dbKeyIdx);
+ }
+
+ public static String getDBKey(){
+ return dbKey.get();
+ }
+
+ public static void setTBKey(String tbKeyIdx){
+ tbKey.set(tbKeyIdx);
+ }
+
+ public static String getTBKey(){
+ return tbKey.get();
+ }
+
+ public static void clearDBKey(){
+ dbKey.remove();
+ }
+
+ public static void clearTBKey(){
+ tbKey.remove();
+ }
+
+
+}
diff --git a/src/main/java/cn/bugstack/middleware/db/router/DBRouterBase.java b/src/main/java/cn/bugstack/middleware/db/router/DBRouterBase.java
new file mode 100644
index 0000000000000000000000000000000000000000..66d7205d44eadb72d71b1b7336667c38ccfd3c6d
--- /dev/null
+++ b/src/main/java/cn/bugstack/middleware/db/router/DBRouterBase.java
@@ -0,0 +1,16 @@
+package cn.bugstack.middleware.db.router;
+
+/**
+ * 博客:https://bugstack.cn - 沉淀、分享、成长,让自己和他人都能有所收获!
+ * 公众号:bugstack虫洞栈
+ * Create by 小傅哥(fustack)
+ */
+public class DBRouterBase {
+
+ private String tbIdx;
+
+ public String getTbIdx() {
+ return DBContextHolder.getTBKey();
+ }
+
+}
diff --git a/src/main/java/cn/bugstack/middleware/db/router/DBRouterConfig.java b/src/main/java/cn/bugstack/middleware/db/router/DBRouterConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..2f783636baad11963ba1e990b5dbaadfcab0686c
--- /dev/null
+++ b/src/main/java/cn/bugstack/middleware/db/router/DBRouterConfig.java
@@ -0,0 +1,37 @@
+package cn.bugstack.middleware.db.router;
+
+/**
+ * 博客:https://bugstack.cn - 沉淀、分享、成长,让自己和他人都能有所收获!
+ * 公众号:bugstack虫洞栈
+ * Create by 小傅哥(fustack)
+ */
+public class DBRouterConfig {
+
+ private int dbCount; //分库数
+ private int tbCount; //分表数
+
+ public DBRouterConfig() {
+ }
+
+ public DBRouterConfig(int dbCount, int tbCount) {
+ this.dbCount = dbCount;
+ this.tbCount = tbCount;
+ }
+
+ public int getDbCount() {
+ return dbCount;
+ }
+
+ public void setDbCount(int dbCount) {
+ this.dbCount = dbCount;
+ }
+
+ public int getTbCount() {
+ return tbCount;
+ }
+
+ public void setTbCount(int tbCount) {
+ this.tbCount = tbCount;
+ }
+
+}
diff --git a/src/main/java/cn/bugstack/middleware/db/router/DBRouterJoinPoint.java b/src/main/java/cn/bugstack/middleware/db/router/DBRouterJoinPoint.java
new file mode 100644
index 0000000000000000000000000000000000000000..c4fd1bdbc6af427c68d745a71aec265a98324be3
--- /dev/null
+++ b/src/main/java/cn/bugstack/middleware/db/router/DBRouterJoinPoint.java
@@ -0,0 +1,92 @@
+package cn.bugstack.middleware.db.router;
+
+import cn.bugstack.middleware.db.router.annotation.DBRouter;
+import org.apache.commons.beanutils.BeanUtils;
+import org.apache.commons.lang.StringUtils;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.Signature;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.lang.reflect.Method;
+
+/**
+ * 博客:https://bugstack.cn - 沉淀、分享、成长,让自己和他人都能有所收获!
+ * 公众号:bugstack虫洞栈
+ * Create by 小傅哥(fustack)
+ */
+@Aspect
+@Component("db-router-point")
+public class DBRouterJoinPoint {
+
+ private Logger logger = LoggerFactory.getLogger(DBRouterJoinPoint.class);
+
+ @Autowired
+ private DBRouterConfig dbRouterConfig;
+
+ @Pointcut("@annotation(cn.bugstack.middleware.db.router.annotation.DBRouter)")
+ public void aopPoint() {
+ }
+
+ @Around("aopPoint()")
+ public Object doRouter(ProceedingJoinPoint jp) throws Throwable {
+ Method method = getMethod(jp);
+ DBRouter dbRouter = method.getAnnotation(DBRouter.class);
+// String dbKey = dbRouter.key();
+ String dbKey = "userId";
+ if (StringUtils.isBlank(dbKey)) throw new RuntimeException("annotation DBRouter key is null!");
+ // 计算路由
+ String dbKeyAttr = getAttrValue(dbKey, jp.getArgs());
+ int size = dbRouterConfig.getDbCount() * dbRouterConfig.getTbCount();
+ // 扰动函数
+ int idx = (size - 1) & (dbKeyAttr.hashCode() ^ (dbKeyAttr.hashCode() >>> 16));
+ // 库表索引
+ int dbIdx = idx / dbRouterConfig.getTbCount() + 1;
+ int tbIdx = idx - dbRouterConfig.getTbCount() * (dbIdx - 1);
+ // 设置到ThreadLocal
+ DBContextHolder.setDBKey(String.format("%02d", dbIdx));
+ DBContextHolder.setTBKey(String.format("%02d", tbIdx));
+ logger.info("数据库路由 method:{} dbIdx:{} tbIdx:{}", method.getName(), dbIdx, tbIdx);
+ try {
+ return jp.proceed();
+ } finally {
+ DBContextHolder.clearDBKey();
+ DBContextHolder.clearTBKey();
+ }
+ }
+
+ private Method getMethod(JoinPoint jp) throws NoSuchMethodException {
+ Signature sig = jp.getSignature();
+ MethodSignature methodSignature = (MethodSignature) sig;
+ return getClass(jp).getMethod(methodSignature.getName(), methodSignature.getParameterTypes());
+ }
+
+ private Class extends Object> getClass(JoinPoint jp) throws NoSuchMethodException {
+ return jp.getTarget().getClass();
+ }
+
+ public String getAttrValue(String attr, Object[] args) {
+ String filedValue = null;
+ for (Object arg : args) {
+ try {
+ if (StringUtils.isBlank(filedValue)) {
+ filedValue = BeanUtils.getProperty(arg, attr);
+ } else {
+ break;
+ }
+ } catch (Exception e) {
+ logger.error("获取路由属性值失败 attr:{}", attr, e);
+ }
+ }
+ return filedValue;
+ }
+
+}
diff --git a/src/main/java/cn/bugstack/middleware/db/router/annotation/DBRouter.java b/src/main/java/cn/bugstack/middleware/db/router/annotation/DBRouter.java
new file mode 100644
index 0000000000000000000000000000000000000000..bf258e19fce37ba9f9a6e210b618d18eae91390b
--- /dev/null
+++ b/src/main/java/cn/bugstack/middleware/db/router/annotation/DBRouter.java
@@ -0,0 +1,16 @@
+package cn.bugstack.middleware.db.router.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * 博客:https://bugstack.cn - 沉淀、分享、成长,让自己和他人都能有所收获!
+ * 公众号:bugstack虫洞栈
+ * Create by 小傅哥(fustack)
+ */
+//@Retention(RetentionPolicy.RUNTIME)
+//@Target({ElementType.TYPE, ElementType.METHOD})
+public @interface DBRouter {
+
+ String key() default "";
+
+}
diff --git a/src/main/java/cn/bugstack/middleware/db/router/config/DataSourceAutoConfig.java b/src/main/java/cn/bugstack/middleware/db/router/config/DataSourceAutoConfig.java
index 805b28f0d476717997ff4dcee2101c8b37b894d4..cb5735707f600249f18f97f300491651f3683282 100644
--- a/src/main/java/cn/bugstack/middleware/db/router/config/DataSourceAutoConfig.java
+++ b/src/main/java/cn/bugstack/middleware/db/router/config/DataSourceAutoConfig.java
@@ -1,5 +1,6 @@
package cn.bugstack.middleware.db.router.config;
+import cn.bugstack.middleware.db.router.DBRouterConfig;
import cn.bugstack.middleware.db.router.dynamic.DynamicDataSource;
import cn.bugstack.middleware.db.router.util.PropertyUtil;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
@@ -24,27 +25,41 @@ import java.util.Map;
@Configuration
public class DataSourceAutoConfig implements EnvironmentAware {
+ private Map> dataSourceMap = new HashMap<>();
+
+ private int dbCount; //分库数
+ private int tbCount; //分表数
+
@Bean
- public DataSource dataSource() {
+ public DBRouterConfig dbRouterConfig() {
+ return new DBRouterConfig(dbCount, tbCount);
+ }
+ @Bean
+ public DataSource dataSource() {
+ // 创建数据源
Map