Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
KnowledgePlanet
road-map
xfg-dev-tech-db-router
提交
14e58c1b
xfg-dev-tech-db-router
项目概览
KnowledgePlanet
/
road-map
/
xfg-dev-tech-db-router
通知
257
Star
23
Fork
8
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
xfg-dev-tech-db-router
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
14e58c1b
编写于
2月 19, 2021
作者:
小傅哥
⛹
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
小傅哥,数据库路由组件设计
上级
ef37762d
变更
10
隐藏空白更改
内联
并排
Showing
10 changed file
with
257 addition
and
61 deletion
+257
-61
pom.xml
pom.xml
+6
-1
src/main/java/cn/bugstack/middleware/db/router/DBContextHolder.java
...ava/cn/bugstack/middleware/db/router/DBContextHolder.java
+38
-0
src/main/java/cn/bugstack/middleware/db/router/DBRouterBase.java
...n/java/cn/bugstack/middleware/db/router/DBRouterBase.java
+16
-0
src/main/java/cn/bugstack/middleware/db/router/DBRouterConfig.java
...java/cn/bugstack/middleware/db/router/DBRouterConfig.java
+37
-0
src/main/java/cn/bugstack/middleware/db/router/DBRouterJoinPoint.java
...a/cn/bugstack/middleware/db/router/DBRouterJoinPoint.java
+92
-0
src/main/java/cn/bugstack/middleware/db/router/annotation/DBRouter.java
...cn/bugstack/middleware/db/router/annotation/DBRouter.java
+16
-0
src/main/java/cn/bugstack/middleware/db/router/config/DataSourceAutoConfig.java
...ack/middleware/db/router/config/DataSourceAutoConfig.java
+23
-8
src/main/java/cn/bugstack/middleware/db/router/config/DataSourceProperties.java
...ack/middleware/db/router/config/DataSourceProperties.java
+0
-51
src/main/java/cn/bugstack/middleware/db/router/dynamic/DynamicDataSource.java
...stack/middleware/db/router/dynamic/DynamicDataSource.java
+2
-1
src/test/java/cn/bugstack/middleware/test/ApiTest.java
src/test/java/cn/bugstack/middleware/test/ApiTest.java
+27
-0
未找到文件。
pom.xml
浏览文件 @
14e58c1b
...
...
@@ -61,7 +61,12 @@
<dependency>
<groupId>
commons-beanutils
</groupId>
<artifactId>
commons-beanutils
</artifactId>
<version>
1.8.3
</version>
<version>
1.9.4
</version>
</dependency>
<dependency>
<groupId>
commons-lang
</groupId>
<artifactId>
commons-lang
</artifactId>
<version>
2.6
</version>
</dependency>
<dependency>
<groupId>
com.alibaba
</groupId>
...
...
src/main/java/cn/bugstack/middleware/db/router/DBContextHolder.java
0 → 100644
浏览文件 @
14e58c1b
package
cn.bugstack.middleware.db.router
;
/**
* 博客:https://bugstack.cn - 沉淀、分享、成长,让自己和他人都能有所收获!
* 公众号:bugstack虫洞栈
* Create by 小傅哥(fustack)
*/
public
class
DBContextHolder
{
private
static
final
ThreadLocal
<
String
>
dbKey
=
new
ThreadLocal
<
String
>();
private
static
final
ThreadLocal
<
String
>
tbKey
=
new
ThreadLocal
<
String
>();
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
();
}
}
src/main/java/cn/bugstack/middleware/db/router/DBRouterBase.java
0 → 100644
浏览文件 @
14e58c1b
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
();
}
}
src/main/java/cn/bugstack/middleware/db/router/DBRouterConfig.java
0 → 100644
浏览文件 @
14e58c1b
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
;
}
}
src/main/java/cn/bugstack/middleware/db/router/DBRouterJoinPoint.java
0 → 100644
浏览文件 @
14e58c1b
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
;
}
}
src/main/java/cn/bugstack/middleware/db/router/annotation/DBRouter.java
0 → 100644
浏览文件 @
14e58c1b
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
""
;
}
src/main/java/cn/bugstack/middleware/db/router/config/DataSourceAutoConfig.java
浏览文件 @
14e58c1b
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
<
String
,
Map
<
String
,
Object
>>
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
<
Object
,
Object
>
targetDataSources
=
new
HashMap
<>();
targetDataSources
.
put
(
"db01"
,
new
DriverManagerDataSource
(
"jdbc:mysql://127.0.0.1:3306/bugstack?useUnicode=true"
,
"root"
,
"1234"
));
for
(
String
dbInfo
:
dataSourceMap
.
keySet
())
{
Map
<
String
,
Object
>
objMap
=
dataSourceMap
.
get
(
dbInfo
);
targetDataSources
.
put
(
dbInfo
,
new
DriverManagerDataSource
(
objMap
.
get
(
"url"
).
toString
(),
objMap
.
get
(
"username"
).
toString
(),
objMap
.
get
(
"password"
).
toString
()));
}
// 设置数据源
DynamicDataSource
dynamicDataSource
=
new
DynamicDataSource
();
dynamicDataSource
.
setTargetDataSources
(
targetDataSources
);
return
dynamicDataSource
;
}
@Override
public
void
setEnvironment
(
Environment
environment
)
{
String
prefix
=
"router.jdbc.datasource."
;
String
dataSources
=
environment
.
getProperty
(
prefix
+
"list"
);
assert
dataSources
!=
null
;
for
(
String
each
:
dataSources
.
split
(
","
))
{
Map
<
String
,
Object
>
dataSourceProps
=
PropertyUtil
.
handle
(
environment
,
prefix
+
each
,
Map
.
class
);
dbCount
=
Integer
.
valueOf
(
environment
.
getProperty
(
prefix
+
"dbCount"
));
tbCount
=
Integer
.
valueOf
(
environment
.
getProperty
(
prefix
+
"tbCount"
));
String
dataSources
=
environment
.
getProperty
(
prefix
+
"list"
);
for
(
String
dbInfo
:
dataSources
.
split
(
","
))
{
Map
<
String
,
Object
>
dataSourceProps
=
PropertyUtil
.
handle
(
environment
,
prefix
+
dbInfo
,
Map
.
class
);
dataSourceMap
.
put
(
dbInfo
,
dataSourceProps
);
}
}
...
...
src/main/java/cn/bugstack/middleware/db/router/config/DataSourceProperties.java
已删除
100644 → 0
浏览文件 @
ef37762d
package
cn.bugstack.middleware.db.router.config
;
import
org.springframework.boot.context.properties.ConfigurationProperties
;
/**
* 博客:https://bugstack.cn - 沉淀、分享、成长,让自己和他人都能有所收获!
* 公众号:bugstack虫洞栈
* Create by 小傅哥(fustack)
*/
public
class
DataSourceProperties
{
public
static
final
String
PREFIX
=
"spring.datasource"
;
private
String
username
;
private
String
password
;
private
String
url
;
private
String
driverClassName
;
public
String
getUsername
()
{
return
username
;
}
public
void
setUsername
(
String
username
)
{
this
.
username
=
username
;
}
public
String
getPassword
()
{
return
password
;
}
public
void
setPassword
(
String
password
)
{
this
.
password
=
password
;
}
public
String
getUrl
()
{
return
url
;
}
public
void
setUrl
(
String
url
)
{
this
.
url
=
url
;
}
public
String
getDriverClassName
()
{
return
driverClassName
;
}
public
void
setDriverClassName
(
String
driverClassName
)
{
this
.
driverClassName
=
driverClassName
;
}
}
src/main/java/cn/bugstack/middleware/db/router/dynamic/DynamicDataSource.java
浏览文件 @
14e58c1b
package
cn.bugstack.middleware.db.router.dynamic
;
import
cn.bugstack.middleware.db.router.DBContextHolder
;
import
org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource
;
/**
...
...
@@ -11,7 +12,7 @@ public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected
Object
determineCurrentLookupKey
()
{
return
"db
01"
;
return
"db
"
+
DBContextHolder
.
getDBKey
()
;
}
}
src/test/java/cn/bugstack/middleware/test/ApiTest.java
浏览文件 @
14e58c1b
package
cn.bugstack.middleware.test
;
import
org.junit.Test
;
/**
* 博客:https://bugstack.cn - 沉淀、分享、成长,让自己和他人都能有所收获!
* 公众号:bugstack虫洞栈
...
...
@@ -11,4 +13,29 @@ public class ApiTest {
System
.
out
.
println
(
"Hi"
);
}
@Test
public
void
test_db_hash
()
{
String
key
=
"小傅哥"
;
int
dbCount
=
2
,
tbCount
=
32
;
int
size
=
dbCount
*
tbCount
;
// 散列
int
idx
=
(
size
-
1
)
&
(
key
.
hashCode
()
^
(
key
.
hashCode
()
>>>
16
));
System
.
out
.
println
(
idx
);
int
dbIdx
=
idx
/
tbCount
+
1
;
int
tbIdx
=
idx
-
tbCount
*
(
dbIdx
-
1
);
System
.
out
.
println
(
dbIdx
);
System
.
out
.
println
(
tbIdx
);
}
@Test
public
void
test_str_format
(){
System
.
out
.
println
(
String
.
format
(
"db%02d"
,
1
));
System
.
out
.
println
(
String
.
format
(
"_%02d"
,
25
));
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录