废话不多说,直接上代码
一、多数据源实现- 配置文件
# 数据源配置
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
druid:
# 主库数据源(配置库)
master:
url: jdbc:mysql://localhost:3306/config?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: pwd123456
# 从库数据源
slave:
# 从数据源开关/默认关闭
enabled: false
username:
password:
# 初始连接数
initialSize: 5
# 最小连接池数量
minIdle: 10
# 最大连接池数量
maxActive: 20
# 配置获取连接等待超时的时间
maxWait: 60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
timeBetweenEvictionRunsMillis: 60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
minEvictableIdleTimeMillis: 300000
# 配置一个连接在池中最大生存的时间,单位是毫秒
maxEvictableIdleTimeMillis: 900000
# 配置检测连接是否有效
validationQuery: SELECt 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
webStatFilter:
enabled: true
statViewServlet:
enabled: true
# 设置白名单,不填则允许所有访问
allow:
url-pattern: /druid
public String value() default "MASTER";
}
- 切面
@Aspect
@Order(1)
@Component
public class DataSourceAspect
{
protected Logger logger = LoggerFactory.getLogger(getClass());
@Pointcut("@annotation(com.ruoyi.framework.aspectj.lang.annotation.DataSource)"
+ "|| @within(com.ruoyi.framework.aspectj.lang.annotation.DataSource)")
public void dsPointCut()
{
}
@Around("dsPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable
{
DataSource dataSource = getDataSource(point);
if (StringUtils.isNotNull(dataSource))
{
String dsType = DataSourceType.MASTER.name();
Object obj = AnnotationResolver.newInstance().resolver(point, dataSource.value());
if(StringUtils.isNotNull(obj)) {
dsType = obj.toString();
}
DynamicDataSourceContextHolder.setDataSourceType(dsType);
}
try
{
return point.proceed();
}
finally
{
// 销毁数据源 在执行方法之后
DynamicDataSourceContextHolder.clearDataSourceType();
}
}
public DataSource getDataSource(ProceedingJoinPoint point)
{
MethodSignature signature = (MethodSignature) point.getSignature();
DataSource dataSource = AnnotationUtils.findAnnotation(signature.getMethod(), DataSource.class);
if (Objects.nonNull(dataSource))
{
return dataSource;
}
return AnnotationUtils.findAnnotation(signature.getDeclaringType(), DataSource.class);
}
}
- 注解解析器
public class AnnotationResolver {
private static AnnotationResolver resolver ;
public static AnnotationResolver newInstance(){
if (resolver == null) {
return resolver = new AnnotationResolver();
}else{
return resolver;
}
}
public Object resolver(JoinPoint joinPoint, String str) {
if (str == null) return null ;
Object value = null;
if (str.matches("#\{\D*\}")) {// 如果name匹配上了#{},则把内容当作变量
String newStr = str.replaceAll("#\{", "").replaceAll("\}", "");
if (newStr.contains(".")) { // 复杂类型
try {
value = complexResolver(joinPoint, newStr);
} catch (Exception e) {
e.printStackTrace();
}
} else {
value = simpleResolver(joinPoint, newStr);
}
} else { //非变量
value = str;
}
return value;
}
private Object complexResolver(JoinPoint joinPoint, String str) throws Exception {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] names = signature.getParameterNames();
Object[] args = joinPoint.getArgs();
String[] strs = str.split("\.");
for (int i = 0; i < names.length; i++) {
if (strs[0].equals(names[i])) {
Class clazz = args[i].getClass().getSuperclass();
Method method = clazz.getDeclaredMethod(getMethodName(strs[1]), null);
Object value = method.invoke(args[i]);
return getValue(value, 1, strs);
}
}
return null;
}
private Object getValue(Object obj, int index, String[] strs) {
try {
if (obj != null && index < strs.length - 1) {
Method method = obj.getClass().getDeclaredMethod(getMethodName(strs[index + 1]), null);
obj = method.invoke(obj);
getValue(obj, index + 1, strs);
}
return obj;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private String getMethodName(String name) {
return "get" + name.replaceFirst(name.substring(0, 1), name.substring(0, 1).toUpperCase());
}
private Object simpleResolver(JoinPoint joinPoint, String str) {
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
String[] names = methodSignature.getParameterNames();
Object[] args = joinPoint.getArgs();
for (int i = 0; i < names.length; i++) {
if (str.equals(names[i])) {
return args[i];
}
}
return null;
}
}
- 注解切换数据源
@DataSource(value = "#{dsname}")
@Override
public TvContext selectTvContextByContextId(Long contextId, String dsname)
{
String dsType = DynamicDataSourceContextHolder.getDataSourceType();
TvContext tvContext = tvContextMapper.selectTvContextByContextId(contextId);
tvContext.setDsname(dsType);
return tvContext;
}



