mirror of
https://gitee.com/wangkang/udf.git
synced 2026-11-02 03:03:42 +00:00
更新
This commit is contained in:
@@ -4,3 +4,5 @@
|
||||
/udf-starter/udf-starter.iml
|
||||
/udf-starter/udf-starter-core/target/
|
||||
/udf-starter/udf-starter-core/udf-starter-core.iml
|
||||
/udf-starter/udf-starter-datasource-dynamic/udf-starter-datasource-dynamic.iml
|
||||
/udf-starter/udf-starter-datasource-dynamic/target/
|
||||
|
||||
+2
-2
@@ -11,7 +11,7 @@
|
||||
<url>https://itkk.org/</url>
|
||||
<!-- 公共参数 -->
|
||||
<properties>
|
||||
<udf-starter.version>1.0.5</udf-starter.version>
|
||||
<udf-starter.version>1.0.0</udf-starter.version>
|
||||
<springboot.version>2.2.5.RELEASE</springboot.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
@@ -30,7 +30,7 @@
|
||||
<!--子模块 -->
|
||||
<modules>
|
||||
<module>udf-starter-core</module>
|
||||
<!-- <module>udf-starter-datasource-dynamic</module>-->
|
||||
<module>udf-starter-datasource-dynamic</module>
|
||||
<!-- <module>udf-starter-process-activiti</module>-->
|
||||
<!-- <module>udf-starter-cache-redis</module>-->
|
||||
<!-- <module>udf-starter-cache-db</module>-->
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<!-- maven坐标 -->
|
||||
<artifactId>udf-starter-datasource-dynamic</artifactId>
|
||||
<name>udf-starter-datasource-dynamic</name>
|
||||
<packaging>jar</packaging>
|
||||
<url>https://www.itkk.org/</url>
|
||||
<!-- 父依赖 -->
|
||||
<parent>
|
||||
<groupId>org.itkk.udf</groupId>
|
||||
<artifactId>udf-starter</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</parent>
|
||||
<!-- 依赖 -->
|
||||
<dependencies>
|
||||
<!-- udf-starter-core -->
|
||||
<dependency>
|
||||
<groupId>org.itkk.udf</groupId>
|
||||
<artifactId>udf-starter-core</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package org.itkk.udf.starter.datasource.dynamic;
|
||||
|
||||
/**
|
||||
* 描述 : 数据源本地线程
|
||||
*
|
||||
* @author wangkang
|
||||
*/
|
||||
public class DataSourceThreadLocal extends ThreadLocal<String> {
|
||||
@Override
|
||||
public void remove() {
|
||||
super.remove();
|
||||
this.initialValue();
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
package org.itkk.udf.starter.datasource.dynamic;
|
||||
|
||||
/**
|
||||
* 描述 : DbContextHolder
|
||||
* <p/>
|
||||
* 多个登入用户可能需要同时切换数据源,所以这里需要写一个线程安全的ThreadLocal 用户切换数据源只要在线程中使用
|
||||
*
|
||||
* @author wangkang
|
||||
*/
|
||||
public class DbContextHolder {
|
||||
|
||||
/**
|
||||
* 描述 : 本地线程
|
||||
*/
|
||||
private static final ThreadLocal<String> CONTEXTHOLDER = new DataSourceThreadLocal();
|
||||
|
||||
/**
|
||||
* 描述 : 私有构造函数
|
||||
*/
|
||||
private DbContextHolder() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 描述 : 设置数据源代码
|
||||
*
|
||||
* @param code 数据源代码
|
||||
*/
|
||||
public static void setDataSourceCode(String code) {
|
||||
CONTEXTHOLDER.set(code);
|
||||
}
|
||||
|
||||
/**
|
||||
* 描述 : 获取数据源代码
|
||||
*
|
||||
* @return 数据源代码
|
||||
*/
|
||||
public static String getDataSourceCode() {
|
||||
return CONTEXTHOLDER.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Description: 清理数据源代码
|
||||
* </p>
|
||||
*/
|
||||
public static void clearDataSourceCode() {
|
||||
CONTEXTHOLDER.remove();
|
||||
}
|
||||
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package org.itkk.udf.starter.datasource.dynamic;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Documented
|
||||
@Target({ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface DbSwitch {
|
||||
String value();
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
package org.itkk.udf.starter.datasource.dynamic;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
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.Pointcut;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
@Aspect
|
||||
@Component
|
||||
@Slf4j
|
||||
public class DbSwitchAspect {
|
||||
/**
|
||||
* 描述 : dbSwitchAspect
|
||||
*/
|
||||
@Pointcut("@annotation(org.itkk.udf.starter.datasource.dynamic.DbSwitch)")
|
||||
public void pointCut() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 环绕通知
|
||||
* @param pjd pjd
|
||||
* @return Object
|
||||
* @throws Throwable Throwable
|
||||
*/
|
||||
@Around("pointCut()")
|
||||
public Object around(ProceedingJoinPoint pjd) throws Throwable {
|
||||
try {
|
||||
Signature signature = pjd.getSignature();
|
||||
MethodSignature methodSignature = (MethodSignature) signature;
|
||||
Method method = methodSignature.getMethod();
|
||||
if (method.isAnnotationPresent(DbSwitch.class)) {
|
||||
DbSwitch dbSwitch = method.getAnnotation(DbSwitch.class);
|
||||
String code = dbSwitch.value();
|
||||
if (StringUtils.isNotBlank(code)) {
|
||||
DbContextHolder.setDataSourceCode(code);
|
||||
}
|
||||
}
|
||||
return pjd.proceed();
|
||||
} finally {
|
||||
DbContextHolder.clearDataSourceCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
package org.itkk.udf.starter.datasource.dynamic;
|
||||
|
||||
import org.itkk.udf.starter.core.CoreUtil;
|
||||
import org.itkk.udf.starter.core.datasource.DataSourceMeta;
|
||||
import org.itkk.udf.starter.core.datasource.IBuildDataSource;
|
||||
import org.itkk.udf.starter.core.exception.SystemRuntimeException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 动态数据源
|
||||
*/
|
||||
@Slf4j
|
||||
public class DynamicDataSource extends AbstractRoutingDataSource {
|
||||
|
||||
/**
|
||||
* 描述 : 目标数据库
|
||||
*/
|
||||
private static Map<Object, Object> dyanmictargetDataSources = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* 描述 : 动态数据源参数
|
||||
*/
|
||||
@Autowired
|
||||
private DynamicDataSourceProperties dynamicDataSourceProperties;
|
||||
|
||||
/**
|
||||
* 描述 : 数据源构建
|
||||
*/
|
||||
@Autowired
|
||||
private IBuildDataSource buildDataSource;
|
||||
|
||||
@Override
|
||||
protected Object determineCurrentLookupKey() {
|
||||
//拿到code
|
||||
String dataSourceCode = DbContextHolder.getDataSourceCode();
|
||||
//判断code是否为空,如果为空,则设置为默认的数据源代码
|
||||
if (StringUtils.isBlank(dataSourceCode)) {
|
||||
dataSourceCode = dynamicDataSourceProperties.getDefaultCode();
|
||||
if (StringUtils.isBlank(dataSourceCode)) {
|
||||
throw new SystemRuntimeException("you do not specify a data source , current dataSourceCode is null");
|
||||
}
|
||||
}
|
||||
//拿到数据源属性,并且判断数据源属性是否存在,以及是否可用
|
||||
DataSourceMeta dataSourceProperties = dynamicDataSourceProperties.getMap().get(dataSourceCode);
|
||||
if (dataSourceProperties != null && dataSourceProperties.getEnable()) {
|
||||
Object obj = DynamicDataSource.dyanmictargetDataSources.get(dataSourceCode);
|
||||
if (obj == null) {
|
||||
DataSource dataSource = buildDataSource.build(dataSourceProperties);
|
||||
if (dataSource != null) {
|
||||
DynamicDataSource.dyanmictargetDataSources.put(dataSourceCode, dataSource);
|
||||
super.setTargetDataSources(DynamicDataSource.dyanmictargetDataSources);
|
||||
super.afterPropertiesSet();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//如果在配置文件中,选择的数据源不存在,则也清理掉数据源缓存(可能是动态删除)
|
||||
if (DynamicDataSource.dyanmictargetDataSources.containsKey(dataSourceCode)) {
|
||||
DynamicDataSource.dyanmictargetDataSources.remove(dataSourceCode);
|
||||
super.setTargetDataSources(DynamicDataSource.dyanmictargetDataSources);
|
||||
super.afterPropertiesSet();
|
||||
}
|
||||
throw new SystemRuntimeException("dataSourceCode : " + dataSourceCode + " not exist or not enable");
|
||||
}
|
||||
if(log.isDebugEnabled()) {
|
||||
log.debug("{} switch to the Data Source : {}", CoreUtil.getTraceId(), dataSourceCode);
|
||||
}
|
||||
return dataSourceCode;
|
||||
}
|
||||
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* DruidDataSourceConfig.java
|
||||
* Created at 2016-11-02
|
||||
* Created by wangkang
|
||||
* Copyright (C) 2016 egridcloud.com, All rights reserved.
|
||||
*/
|
||||
package org.itkk.udf.starter.datasource.dynamic;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* 描述 : DynamicDataSourceConfig
|
||||
*
|
||||
* @author wangkang
|
||||
*/
|
||||
@Configuration
|
||||
public class DynamicDataSourceConfiguration {
|
||||
|
||||
/**
|
||||
* 构造数据源
|
||||
*
|
||||
* @return DataSource
|
||||
*/
|
||||
@Bean
|
||||
@Primary
|
||||
public DataSource dataSource() {
|
||||
DynamicDataSource dynamicDataSource = new DynamicDataSource();
|
||||
dynamicDataSource.setTargetDataSources(new HashMap<>());
|
||||
return dynamicDataSource;
|
||||
}
|
||||
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package org.itkk.udf.starter.datasource.dynamic;
|
||||
|
||||
import org.itkk.udf.starter.core.datasource.DataSourceMeta;
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = DynamicDataSourceProperties.DYNAMIC_DATASOURCE_PROPERTIES_PRE_FIX)
|
||||
@Validated
|
||||
@Data
|
||||
public class DynamicDataSourceProperties {
|
||||
|
||||
/**
|
||||
* 配置文件前缀
|
||||
*/
|
||||
protected static final String DYNAMIC_DATASOURCE_PROPERTIES_PRE_FIX = "org.itkk.udf.starter.datasource.dynamic.properties";
|
||||
|
||||
/**
|
||||
* 默认数据代码
|
||||
*/
|
||||
@NotBlank(message = DYNAMIC_DATASOURCE_PROPERTIES_PRE_FIX + ".defaultCode不能为空")
|
||||
private String defaultCode;
|
||||
|
||||
/**
|
||||
* 数据源配置
|
||||
*/
|
||||
@NotNull(message = DYNAMIC_DATASOURCE_PROPERTIES_PRE_FIX + ".map不能为空")
|
||||
private Map<String, DataSourceMeta> map;
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user