Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
matrix
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
CI / CD
CI / CD
Pipelines
Schedules
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
mall
arch
matrix
Commits
915cc5f0
Commit
915cc5f0
authored
Dec 05, 2019
by
qiuweili123
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
GX-1845 自定义数据源开发
parent
21fd52c4
Hide whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
1083 additions
and
0 deletions
+1083
-0
SelectDataSource.java
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/annotation/SelectDataSource.java
+15
-0
DataSourceAop.java
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/aop/DataSourceAop.java
+41
-0
AbsDynamicDataSource.java
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/bean/AbsDynamicDataSource.java
+31
-0
MatrixDataSource.java
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/bean/MatrixDataSource.java
+85
-0
MatrixDynamicDataSource.java
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/bean/MatrixDynamicDataSource.java
+133
-0
DataSourceConfig.java
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/config/DataSourceConfig.java
+137
-0
MatrixDataSourceConfig.java
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/config/MatrixDataSourceConfig.java
+79
-0
DataSourceConstant.java
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/constant/DataSourceConstant.java
+39
-0
DataSourceTypeEnum.java
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/constant/DataSourceTypeEnum.java
+36
-0
DataSourceError.java
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/errorCode/DataSourceError.java
+10
-0
AbsDataSourceFactory.java
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/factory/AbsDataSourceFactory.java
+20
-0
DataSourceFactory.java
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/factory/DataSourceFactory.java
+11
-0
DruidDataSourceFactory.java
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/factory/DruidDataSourceFactory.java
+31
-0
EncryptorFactory.java
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/factory/EncryptorFactory.java
+126
-0
HikariDataSourceFactory.java
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/factory/HikariDataSourceFactory.java
+26
-0
DataSourceContextHolder.java
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/holder/DataSourceContextHolder.java
+60
-0
MatrixDataSourceProperties.java
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/properties/MatrixDataSourceProperties.java
+25
-0
AbsDataSourceProvider.java
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/provider/AbsDataSourceProvider.java
+46
-0
ApolloDataSourceProvider.java
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/provider/ApolloDataSourceProvider.java
+71
-0
DataSourceProvider.java
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/provider/DataSourceProvider.java
+14
-0
DefaultDataSourceProvider.java
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/provider/DefaultDataSourceProvider.java
+24
-0
DataSourceTest.java
matrix-datasource/matrix-datasource-core/src/test/java/com/secoo/mall/mybatis/datasouce/DataSourceTest.java
+21
-0
application.yml
matrix-datasource/matrix-datasource-core/src/test/resources/application.yml
+2
-0
No files found.
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/annotation/SelectDataSource.java
0 → 100644
View file @
915cc5f0
package
com
.
secoo
.
mall
.
datasource
.
annotation
;
import
java.lang.annotation.ElementType
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.lang.annotation.Target
;
/**
* 选择使用的数据源
*/
@Target
({
ElementType
.
METHOD
,
ElementType
.
TYPE
})
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
@interface
SelectDataSource
{
String
value
();
}
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/aop/DataSourceAop.java
0 → 100644
View file @
915cc5f0
package
com
.
secoo
.
mall
.
datasource
.
aop
;
import
com.secoo.mall.datasource.annotation.SelectDataSource
;
import
com.secoo.mall.datasource.holder.DataSourceContextHolder
;
import
org.aspectj.lang.ProceedingJoinPoint
;
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.core.annotation.AnnotationUtils
;
import
org.springframework.core.annotation.Order
;
import
org.springframework.stereotype.Component
;
import
java.lang.reflect.Method
;
@Aspect
@Order
(
Byte
.
MIN_VALUE
)
@Component
public
class
DataSourceAop
{
@Pointcut
(
"@annotation(com.secoo.mall.datasource.annotation.SelectDataSource) || @within(com.secoo.mall.datasource.annotation.SelectDataSource)"
)
public
void
dataSoucePointcut
()
{
}
@Around
(
"com.secoo.mall.datasource.aop.DataSourceAop.dataSoucePointcut()"
)
public
Object
lookupKeyAround
(
ProceedingJoinPoint
pjp
)
throws
Throwable
{
MethodSignature
signature
=
(
MethodSignature
)
pjp
.
getSignature
();
Method
method
=
signature
.
getMethod
();
SelectDataSource
dsName
=
AnnotationUtils
.
getAnnotation
(
method
,
SelectDataSource
.
class
);
if
(
dsName
==
null
)
{
Class
clazz
=
signature
.
getDeclaringType
();
dsName
=
AnnotationUtils
.
findAnnotation
(
clazz
,
SelectDataSource
.
class
);
}
try
{
DataSourceContextHolder
.
setDs
(
dsName
.
value
());
return
pjp
.
proceed
();
}
finally
{
DataSourceContextHolder
.
clear
();
}
}
}
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/bean/AbsDynamicDataSource.java
0 → 100644
View file @
915cc5f0
package
com
.
secoo
.
mall
.
datasource
.
bean
;
import
org.springframework.jdbc.datasource.AbstractDataSource
;
import
javax.sql.DataSource
;
import
java.sql.Connection
;
import
java.sql.SQLException
;
public
abstract
class
AbsDynamicDataSource
extends
AbstractDataSource
{
private
String
dsName
;
public
AbsDynamicDataSource
(
String
dsName
)
{
this
.
dsName
=
dsName
;
}
public
String
getDsName
()
{
return
dsName
;
}
@Override
public
Connection
getConnection
()
throws
SQLException
{
return
getDataSource
().
getConnection
();
}
@Override
public
Connection
getConnection
(
String
username
,
String
password
)
throws
SQLException
{
return
getDataSource
().
getConnection
(
username
,
password
);
}
protected
abstract
DataSource
getDataSource
();
}
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/bean/MatrixDataSource.java
0 → 100644
View file @
915cc5f0
package
com
.
secoo
.
mall
.
datasource
.
bean
;
import
com.secoo.mall.datasource.config.MatrixDataSourceConfig
;
import
com.secoo.mall.datasource.constant.DataSourceTypeEnum
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.reflect.MethodUtils
;
import
javax.sql.DataSource
;
import
java.io.Closeable
;
import
java.io.IOException
;
import
java.io.PrintWriter
;
import
java.sql.Connection
;
import
java.sql.SQLException
;
import
java.sql.SQLFeatureNotSupportedException
;
import
java.util.logging.Logger
;
@Slf4j
public
class
MatrixDataSource
implements
DataSource
,
Closeable
{
private
DataSource
dataSource
;
public
MatrixDataSource
()
{
}
public
MatrixDataSource
(
DataSourceTypeEnum
dataSourceTypeEnum
,
MatrixDataSourceConfig
config
)
{
dataSource
=
dataSourceTypeEnum
.
getDataSourceFactory
().
createDataSouce
(
config
);
}
@Override
public
Connection
getConnection
()
throws
SQLException
{
return
dataSource
.
getConnection
();
}
@Override
public
Connection
getConnection
(
String
username
,
String
password
)
throws
SQLException
{
return
dataSource
.
getConnection
(
username
,
password
);
}
@Override
public
<
T
>
T
unwrap
(
Class
<
T
>
iface
)
throws
SQLException
{
return
dataSource
.
unwrap
(
iface
);
}
@Override
public
boolean
isWrapperFor
(
Class
<?>
iface
)
throws
SQLException
{
return
dataSource
.
isWrapperFor
(
iface
);
}
@Override
public
PrintWriter
getLogWriter
()
throws
SQLException
{
return
dataSource
.
getLogWriter
();
}
@Override
public
void
setLogWriter
(
PrintWriter
out
)
throws
SQLException
{
dataSource
.
setLogWriter
(
out
);
}
@Override
public
void
setLoginTimeout
(
int
seconds
)
throws
SQLException
{
dataSource
.
setLoginTimeout
(
seconds
);
}
@Override
public
int
getLoginTimeout
()
throws
SQLException
{
return
dataSource
.
getLoginTimeout
();
}
@Override
public
Logger
getParentLogger
()
throws
SQLFeatureNotSupportedException
{
return
dataSource
.
getParentLogger
();
}
@Override
public
void
close
()
throws
IOException
{
try
{
MethodUtils
.
invokeExactMethod
(
dataSource
,
"close"
);
}
catch
(
Exception
e
)
{
log
.
error
(
"datasource close error "
,
e
);
}
}
}
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/bean/MatrixDynamicDataSource.java
0 → 100644
View file @
915cc5f0
package
com
.
secoo
.
mall
.
datasource
.
bean
;
import
com.secoo.mall.common.core.exception.BusinessException
;
import
com.secoo.mall.common.util.string.StringUtil
;
import
com.secoo.mall.datasource.errorCode.DataSourceError
;
import
com.secoo.mall.datasource.holder.DataSourceContextHolder
;
import
com.secoo.mall.datasource.provider.DataSourceProvider
;
import
lombok.Data
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.DisposableBean
;
import
org.springframework.beans.factory.InitializingBean
;
import
javax.annotation.Resource
;
import
javax.sql.DataSource
;
import
java.lang.reflect.Method
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.concurrent.locks.Lock
;
import
java.util.concurrent.locks.ReentrantLock
;
@Slf4j
@Data
public
class
MatrixDynamicDataSource
extends
AbsDynamicDataSource
implements
InitializingBean
,
DisposableBean
{
private
Map
<
String
,
DataSource
>
dataSourceMap
=
new
HashMap
<>();
private
static
Lock
lock
=
new
ReentrantLock
();
@Resource
private
DataSourceProvider
provider
;
public
MatrixDynamicDataSource
(
String
dsName
)
{
super
(
dsName
);
}
@Override
/**
* 获取数据源有两种途径:
* 1.由构造参数直接指定
* 2.使用了selectDataSource注解
*/
protected
DataSource
getDataSource
()
{
String
dsName
=
StringUtil
.
isEmpty
(
getDsName
())
?
DataSourceContextHolder
.
getDs
()
:
getDsName
();
log
.
info
(
"cur ds is {}"
,
dsName
);
return
getTargetDataSource
(
dsName
);
}
/**
* 获取目的数据原
*
* @param dsName
* @return
*/
private
DataSource
getTargetDataSource
(
String
dsName
)
{
//如果数据源名字为空默认取一个,此种情况可以允许不使用@SelectDataSource指定数据源
/* if (dsName == null) {
dsName = dataSourceMap.keySet().iterator().next();
}*/
if
(
dataSourceMap
.
containsKey
(
dsName
))
{
return
dataSourceMap
.
get
(
dsName
);
}
throw
new
BusinessException
(
DataSourceError
.
DATA_SOURCE_NOT_EXIST
,
dsName
);
}
/**
* bean销毁
*
* @throws Exception
*/
@Override
public
void
destroy
()
throws
Exception
{
log
.
info
(
"datasource start closing ...."
);
for
(
Map
.
Entry
<
String
,
DataSource
>
item
:
dataSourceMap
.
entrySet
())
{
DataSource
dataSource
=
item
.
getValue
();
Class
<?
extends
DataSource
>
clazz
=
dataSource
.
getClass
();
try
{
Method
closeMethod
=
clazz
.
getDeclaredMethod
(
"close"
);
closeMethod
.
invoke
(
dataSource
);
}
catch
(
NoSuchMethodException
e
)
{
log
.
warn
(
"datasource close the datasource named [{}] failed,"
,
item
.
getKey
());
}
}
log
.
info
(
"datasource all closed success"
);
}
/**
* 数据加载
*
* @throws Exception
*/
@Override
public
void
afterPropertiesSet
()
throws
Exception
{
Map
<
String
,
DataSource
>
dataSourceMap
=
this
.
provider
.
loadDataSources
();
for
(
Map
.
Entry
<
String
,
DataSource
>
dataSourceEntry
:
dataSourceMap
.
entrySet
())
{
addDataSource
(
dataSourceEntry
.
getKey
(),
dataSourceEntry
.
getValue
());
}
}
public
void
addDataSource
(
String
dsName
,
DataSource
dataSource
)
{
lock
.
lock
();
log
.
info
(
"load dataSources lock {}"
,
dsName
);
if
(!
dataSourceMap
.
containsKey
(
dsName
))
{
dataSourceMap
.
put
(
dsName
,
dataSource
);
}
log
.
info
(
"load dataSources unlock {}"
,
dsName
);
lock
.
unlock
();
}
/**
* todo:动态更新数据源
*
* @param dsName
*/
public
void
removeDataSource
(
String
dsName
)
{
lock
.
lock
();
log
.
info
(
"remove dataSources lock {}"
,
dsName
);
if
(
dataSourceMap
.
containsKey
(
dsName
))
{
dataSourceMap
.
remove
(
dsName
);
}
log
.
info
(
"remove dataSources unlock {}"
,
dsName
);
lock
.
unlock
();
}
}
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/config/DataSourceConfig.java
0 → 100644
View file @
915cc5f0
package
com
.
secoo
.
mall
.
datasource
.
config
;
import
java.util.concurrent.TimeUnit
;
public
interface
DataSourceConfig
{
String
POOL_NAME_PRIFIX
=
"matrix-dataSource-"
;
int
DEFAULT_MIN_IDLE
=
5
;
int
DEFAULT_POOL_SIZE
=
50
;
long
CONNECTION_TIMEOUT
=
TimeUnit
.
SECONDS
.
toMillis
(
30L
);
long
VALIDATION_TIMEOUT
=
TimeUnit
.
SECONDS
.
toMillis
(
5L
);
long
IDLE_TIMEOUT
=
TimeUnit
.
MINUTES
.
toMillis
(
10L
);
long
MAX_LIFETIME
=
TimeUnit
.
MINUTES
.
toMillis
(
30L
);
/**
* Get the maximum number of milliseconds that a client will wait for a connection from the pool. If this
* time is exceeded without a connection becoming available, a SQLException will be thrown from
* {@link javax.sql.DataSource#getConnection()}.
*
* @return the connection timeout in milliseconds
*/
long
getConnectionTimeout
();
/**
* Set the maximum number of milliseconds that a client will wait for a connection from the pool. If this
* time is exceeded without a connection becoming available, a SQLException will be thrown from
* {@link javax.sql.DataSource#getConnection()}.
*
* @param connectionTimeoutMs the connection timeout in milliseconds
*/
void
setConnectionTimeout
(
long
connectionTimeoutMs
);
/**
* This property controls the maximum amount of time (in milliseconds) that a connection is allowed to sit
* idle in the pool. Whether a connection is retired as idle or not is subject to a maximum variation of +30
* seconds, and average variation of +15 seconds. A connection will never be retired as idle before this timeout.
* A value of 0 means that idle connections are never removed from the pool.
*
* @return the idle timeout in milliseconds
*/
long
getIdleTimeout
();
/**
* This property controls the maximum amount of time (in milliseconds) that a connection is allowed to sit
* idle in the pool. Whether a connection is retired as idle or not is subject to a maximum variation of +30
* seconds, and average variation of +15 seconds. A connection will never be retired as idle before this timeout.
* A value of 0 means that idle connections are never removed from the pool.
*
* @param idleTimeoutMs the idle timeout in milliseconds
*/
void
setIdleTimeout
(
long
idleTimeoutMs
);
/**
* This property controls the maximum lifetime of a connection in the pool. When a connection reaches this
* timeout, even if recently used, it will be retired from the pool. An in-use connection will never be
* retired, only when it is idle will it be removed.
*
* @return the maximum connection lifetime in milliseconds
*/
long
getMaxLifetime
();
/**
* This property controls the maximum lifetime of a connection in the pool. When a connection reaches this
* timeout, even if recently used, it will be retired from the pool. An in-use connection will never be
* retired, only when it is idle will it be removed.
*
* @param maxLifetimeMs the maximum connection lifetime in milliseconds
*/
void
setMaxLifetime
(
long
maxLifetimeMs
);
/**
* The property controls the minimum number of idle connections that HikariCP tries to maintain in the pool,
* including both idle and in-use connections. If the idle connections dip below this value, HikariCP will
* make a best effort to restore them quickly and efficiently.
*
* @return the minimum number of connections in the pool
*/
int
getMinimumIdle
();
/**
* The property controls the minimum number of idle connections that HikariCP tries to maintain in the pool,
* including both idle and in-use connections. If the idle connections dip below this value, HikariCP will
* make a best effort to restore them quickly and efficiently.
*
* @param minIdle the minimum number of idle connections in the pool to maintain
*/
void
setMinimumIdle
(
int
minIdle
);
/**
* The property controls the maximum number of connections that HikariCP will keep in the pool,
* including both idle and in-use connections.
*
* @return the maximum number of connections in the pool
*/
int
getMaximumPoolSize
();
/**
* The property controls the maximum size that the pool is allowed to reach, including both idle and in-use
* connections. Basically this value will determine the maximum number of actual connections to the database
* backend.
* <p>
* When the pool reaches this size, and no idle connections are available, calls to getConnection() will
* block for up to connectionTimeout milliseconds before timing out.
*
* @param maxPoolSize the maximum number of connections in the pool
*/
void
setMaximumPoolSize
(
int
maxPoolSize
);
/**
* Set the password used for authentication. Changing this at runtime will apply to new connections only.
* Altering this at runtime only works for DataSource-based connections, not Driver-class or JDBC URL-based
* connections.
*
* @param password the database password
*/
void
setPassword
(
String
password
);
/**
* Set the username used for authentication. Changing this at runtime will apply to new connections only.
* Altering this at runtime only works for DataSource-based connections, not Driver-class or JDBC URL-based
* connections.
*
* @param username the database username
*/
void
setUsername
(
String
username
);
/**
* The name of the data source.
*
* @return the name of the connection pool
*/
String
getName
();
}
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/config/MatrixDataSourceConfig.java
0 → 100644
View file @
915cc5f0
package
com
.
secoo
.
mall
.
datasource
.
config
;
import
lombok.Data
;
@Data
public
class
MatrixDataSourceConfig
implements
DataSourceConfig
{
private
String
name
;
private
String
username
;
private
String
password
;
/**
* Connection url
*/
private
String
url
;
private
int
minimumIdle
=
DEFAULT_MIN_IDLE
;
private
int
maxPoolSize
=
DEFAULT_POOL_SIZE
;
/**
* Unit:Millis
*/
private
long
connectionTimeout
=
CONNECTION_TIMEOUT
;
private
long
idleTimeout
=
IDLE_TIMEOUT
;
private
long
maxLifetime
=
MAX_LIFETIME
;
public
void
setName
(
String
name
)
{
this
.
name
=
POOL_NAME_PRIFIX
+
name
;
}
@Override
public
long
getConnectionTimeout
()
{
return
connectionTimeout
;
}
@Override
public
void
setConnectionTimeout
(
long
connectionTimeoutMs
)
{
this
.
connectionTimeout
=
connectionTimeoutMs
;
}
@Override
public
long
getIdleTimeout
()
{
return
idleTimeout
;
}
@Override
public
void
setIdleTimeout
(
long
idleTimeoutMs
)
{
this
.
idleTimeout
=
idleTimeoutMs
;
}
@Override
public
long
getMaxLifetime
()
{
return
maxLifetime
;
}
@Override
public
void
setMaxLifetime
(
long
maxLifetimeMs
)
{
this
.
maxLifetime
=
maxLifetimeMs
;
}
@Override
public
int
getMinimumIdle
()
{
return
this
.
minimumIdle
;
}
@Override
public
void
setMinimumIdle
(
int
minIdle
)
{
this
.
minimumIdle
=
minIdle
;
}
@Override
public
int
getMaximumPoolSize
()
{
return
maxPoolSize
;
}
@Override
public
void
setMaximumPoolSize
(
int
maxPoolSize
)
{
this
.
maxPoolSize
=
maxPoolSize
;
}
}
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/constant/DataSourceConstant.java
0 → 100644
View file @
915cc5f0
package
com
.
secoo
.
mall
.
datasource
.
constant
;
import
java.util.concurrent.TimeUnit
;
public
interface
DataSourceConstant
{
/**
* 解密服务
*/
String
APP_SECURITY_SERVER_HOST
=
"http://localhost:9080"
;
/**
* 解密文件
*/
String
SECURITY_FILE_JAR_PATH
=
APP_SECURITY_SERVER_HOST
+
"/file/getSecurityFile.jar"
;
/**
* 获取私钥
*/
String
APP_SALT_KEY_PATH
=
APP_SECURITY_SERVER_HOST
+
"/config/getPrivateKeyByAppId?appId=%s"
;
/**
* 阿波罗数据库的配置命名空间
*/
String
DB_NAMESPACE
=
"db.config"
;
/**
* 属性配置分割符
*/
String
PROPETY_SPLIT_CHAR
=
"\\."
;
/**
* 加密标识
*/
String
ENCRY_FLAG
=
"###"
;
/**
* 应用唯一标识
*/
String
APP_ID
=
"app.id"
;
/**
* http访问超时时间。10S
*/
Long
HTTP_CONNETION_TIME_COUT
=
TimeUnit
.
SECONDS
.
toMillis
(
10L
);
}
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/constant/DataSourceTypeEnum.java
0 → 100644
View file @
915cc5f0
package
com
.
secoo
.
mall
.
datasource
.
constant
;
import
com.secoo.mall.datasource.factory.DataSourceFactory
;
import
com.secoo.mall.datasource.factory.DruidDataSourceFactory
;
import
com.secoo.mall.datasource.factory.HikariDataSourceFactory
;
public
enum
DataSourceTypeEnum
{
DRUID
(
"druid"
,
new
DruidDataSourceFactory
()),
HIKARI
(
"hikari"
,
new
HikariDataSourceFactory
());
private
String
name
;
private
DataSourceFactory
dataSourceFactory
;
DataSourceTypeEnum
(
String
name
,
DataSourceFactory
dataSourceFactory
)
{
this
.
name
=
name
;
this
.
dataSourceFactory
=
dataSourceFactory
;
}
public
String
getName
()
{
return
name
;
}
public
DataSourceFactory
getDataSourceFactory
()
{
return
dataSourceFactory
;
}
public
static
DataSourceTypeEnum
getByName
(
String
name
)
{
for
(
DataSourceTypeEnum
typeEnum
:
DataSourceTypeEnum
.
values
())
{
if
(
typeEnum
.
getName
().
equals
(
name
))
{
return
typeEnum
;
}
}
return
null
;
}
}
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/errorCode/DataSourceError.java
0 → 100644
View file @
915cc5f0
package
com
.
secoo
.
mall
.
datasource
.
errorCode
;
import
com.secoo.mall.common.core.errorcode.ErrorCode
;
public
interface
DataSourceError
{
ErrorCode
APOLLO_CONFIG_NOT_EXIST
=
new
ErrorCode
(
1
,
"appollo config not exits"
);
ErrorCode
PRIVATE_KEY_NOT_EXIST
=
new
ErrorCode
(
2
,
"http get privatekey fail"
);
ErrorCode
APP_ID_NOT_EXIST
=
new
ErrorCode
(
3
,
"please config -Dappp.id"
);
ErrorCode
DATA_SOURCE_NOT_EXIST
=
new
ErrorCode
(
4
,
"could not find a datasource named %s"
);
}
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/factory/AbsDataSourceFactory.java
0 → 100644
View file @
915cc5f0
package
com
.
secoo
.
mall
.
datasource
.
factory
;
import
com.secoo.mall.datasource.config.MatrixDataSourceConfig
;
import
javax.sql.DataSource
;
public
abstract
class
AbsDataSourceFactory
<
T
>
implements
DataSourceFactory
<
T
>
{
@Override
public
<
T
extends
DataSource
>
T
createDataSouce
(
MatrixDataSourceConfig
config
)
{
return
convertAndCreate
(
config
);
}
protected
abstract
<
T
extends
DataSource
>
T
convertAndCreate
(
MatrixDataSourceConfig
config
);
}
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/factory/DataSourceFactory.java
0 → 100644
View file @
915cc5f0
package
com
.
secoo
.
mall
.
datasource
.
factory
;
import
com.secoo.mall.datasource.config.MatrixDataSourceConfig
;
import
javax.sql.DataSource
;
public
interface
DataSourceFactory
<
T
>
{
<
T
extends
DataSource
>
T
createDataSouce
(
MatrixDataSourceConfig
config
);
}
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/factory/DruidDataSourceFactory.java
0 → 100644
View file @
915cc5f0
package
com
.
secoo
.
mall
.
datasource
.
factory
;
import
com.alibaba.druid.pool.DruidDataSource
;
import
com.secoo.mall.datasource.config.MatrixDataSourceConfig
;
import
java.util.Properties
;
public
class
DruidDataSourceFactory
extends
AbsDataSourceFactory
<
DruidDataSource
>
{
private
final
String
duridPreFix
=
"druid."
;
@Override
protected
DruidDataSource
convertAndCreate
(
MatrixDataSourceConfig
config
)
{
Properties
properties
=
new
Properties
();
properties
.
setProperty
(
duridPreFix
+
"name"
,
config
.
getName
());
properties
.
setProperty
(
duridPreFix
+
"url"
,
config
.
getUrl
());
properties
.
setProperty
(
duridPreFix
+
"username"
,
config
.
getUsername
());
properties
.
setProperty
(
duridPreFix
+
"password"
,
config
.
getPassword
());
//连接相关信息
properties
.
setProperty
(
duridPreFix
+
"minIdle"
,
String
.
valueOf
(
config
.
getMinimumIdle
()));
properties
.
setProperty
(
duridPreFix
+
"maxActive"
,
String
.
valueOf
(
config
.
getMaximumPoolSize
()));
properties
.
setProperty
(
duridPreFix
+
"phyTimeoutMillis"
,
String
.
valueOf
(
config
.
getConnectionTimeout
()));
properties
.
setProperty
(
duridPreFix
+
"timeBetweenEvictionRunsMillis"
,
String
.
valueOf
(
config
.
getIdleTimeout
()));
properties
.
setProperty
(
duridPreFix
+
"maxEvictableIdleTimeMillis"
,
String
.
valueOf
(
config
.
getMaxLifetime
()));
DruidDataSource
dataSource
=
new
DruidDataSource
();
dataSource
.
configFromPropety
(
properties
);
return
dataSource
;
}
}
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/factory/EncryptorFactory.java
0 → 100644
View file @
915cc5f0
package
com
.
secoo
.
mall
.
datasource
.
factory
;
import
com.secoo.mall.app.security.encryptor.Encryptor
;
import
com.secoo.mall.common.constant.CharConstant
;
import
com.secoo.mall.common.core.classloader.MatrixUrlClassLoader
;
import
com.secoo.mall.common.core.exception.BusinessException
;
import
com.secoo.mall.common.util.file.IOUtil
;
import
com.secoo.mall.common.util.net.IpUtil
;
import
com.secoo.mall.common.util.string.StringUtil
;
import
com.secoo.mall.datasource.constant.DataSourceConstant
;
import
com.secoo.mall.datasource.errorCode.DataSourceError
;
import
com.secoo.mall.datasource.util.SysUtil
;
import
lombok.extern.slf4j.Slf4j
;
import
java.io.InputStream
;
import
java.net.HttpURLConnection
;
import
java.net.URL
;
import
java.util.List
;
import
java.util.Objects
;
@Slf4j
public
class
EncryptorFactory
<
T
>
{
private
volatile
static
EncryptorFactory
instance
;
private
Encryptor
<
T
>
encryptor
;
private
final
String
privateKey
=
initPrivateKey
();
/**
* 初始化是进行远程加载加密文件
*/
private
EncryptorFactory
()
{
createEncryptor
();
}
public
static
EncryptorFactory
getInstance
()
{
if
(
instance
==
null
)
{
synchronized
(
EncryptorFactory
.
class
)
{
if
(
instance
==
null
)
instance
=
new
EncryptorFactory
();
}
}
return
instance
;
}
public
Encryptor
<
T
>
getEncryptor
()
{
return
encryptor
;
}
public
String
getPrivateKey
()
{
return
privateKey
;
}
/**
* 同步方式获取数据
*
* @return
*/
private
String
initPrivateKey
()
{
String
appId
=
System
.
getProperty
(
DataSourceConstant
.
APP_ID
);
if
(
StringUtil
.
isEmpty
(
appId
))
{
throw
new
BusinessException
(
DataSourceError
.
APP_ID_NOT_EXIST
);
}
HttpURLConnection
connection
=
null
;
try
{
URL
url
=
new
URL
(
String
.
format
(
DataSourceConstant
.
APP_SALT_KEY_PATH
,
appId
));
connection
=
(
HttpURLConnection
)
url
.
openConnection
();
connection
.
setRequestMethod
(
"GET"
);
connection
.
addRequestProperty
(
DataSourceConstant
.
APP_ID
,
appId
);
connection
.
addRequestProperty
(
"accessToken"
,
SysUtil
.
getProperty
(
"accessToken"
));
connection
.
addRequestProperty
(
"hostIP"
,
IpUtil
.
getHostIp
());
connection
.
addRequestProperty
(
"hostName"
,
IpUtil
.
getHostName
());
connection
.
setConnectTimeout
(
DataSourceConstant
.
HTTP_CONNETION_TIME_COUT
.
intValue
());
connection
.
connect
();
int
responseCode
=
connection
.
getResponseCode
();
if
(
responseCode
==
HttpURLConnection
.
HTTP_OK
)
{
InputStream
inputStream
=
connection
.
getInputStream
();
List
<
String
>
strings
=
IOUtil
.
readLines
(
inputStream
,
CharConstant
.
CHARSET_NAME
);
log
.
info
(
"get key secucess"
);
return
String
.
join
(
""
,
strings
);
}
}
catch
(
Exception
e
)
{
log
.
error
(
"connetion server error"
,
e
);
}
finally
{
if
(
connection
!=
null
)
{
connection
.
disconnect
();
}
}
return
null
;
}
private
void
createEncryptor
()
{
if
(
StringUtil
.
isNotEmpty
(
this
.
privateKey
))
{
MatrixUrlClassLoader
.
getInstance
().
loadByUrl
(
DataSourceConstant
.
SECURITY_FILE_JAR_PATH
);
String
[]
args
=
this
.
privateKey
.
split
(
DataSourceConstant
.
ENCRY_FLAG
);
encryptor
=
MatrixUrlClassLoader
.
getInstance
().
loadClassByFullName
(
"com.secoo.mall.app.security.encryptor.StringEncryptor"
,
Encryptor
.
class
,
new
Class
[]{
String
.
class
,
String
.
class
},
args
);
}
/**
* 如果无法从远程创建解密对象,则进行降级处理
*/
if
(
Objects
.
isNull
(
encryptor
))
{
encryptor
=
new
Encryptor
<
T
>()
{
@Override
public
T
encrypt
(
T
value
)
{
return
value
;
}
@Override
public
T
decrypt
(
T
encryptedValue
)
{
return
encryptedValue
;
}
};
}
}
public
static
void
main
(
String
[]
args
)
{
Encryptor
encryptor
=
EncryptorFactory
.
getInstance
().
getEncryptor
();
String
key
=
"8d5862bcc9d076f20d2788cd731e4aa1cc7a0d187b1e9b9245d35f0f18f51968"
;
System
.
out
.
println
(
encryptor
.
decrypt
(
key
));
}
}
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/factory/HikariDataSourceFactory.java
0 → 100644
View file @
915cc5f0
package
com
.
secoo
.
mall
.
datasource
.
factory
;
import
com.secoo.mall.datasource.config.MatrixDataSourceConfig
;
import
com.zaxxer.hikari.HikariConfig
;
import
com.zaxxer.hikari.HikariDataSource
;
public
class
HikariDataSourceFactory
extends
AbsDataSourceFactory
<
HikariDataSource
>
{
@Override
protected
HikariDataSource
convertAndCreate
(
MatrixDataSourceConfig
config
)
{
//基础配置
HikariConfig
hikariConfig
=
new
HikariConfig
();
hikariConfig
.
setJdbcUrl
(
config
.
getUrl
());
hikariConfig
.
setPoolName
(
config
.
getName
());
hikariConfig
.
setUsername
(
config
.
getUsername
());
hikariConfig
.
setPassword
(
config
.
getPassword
());
//连接相关配置
hikariConfig
.
setMinimumIdle
(
config
.
getMinimumIdle
());
hikariConfig
.
setMinimumIdle
(
config
.
getMinimumIdle
());
hikariConfig
.
setMaximumPoolSize
(
config
.
getMaximumPoolSize
());
hikariConfig
.
setIdleTimeout
(
config
.
getIdleTimeout
());
hikariConfig
.
setMaxLifetime
(
config
.
getMaxLifetime
());
hikariConfig
.
setConnectionTimeout
(
config
.
getConnectionTimeout
());
return
new
HikariDataSource
(
hikariConfig
);
}
}
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/holder/DataSourceContextHolder.java
0 → 100644
View file @
915cc5f0
package
com
.
secoo
.
mall
.
datasource
.
holder
;
import
com.secoo.mall.common.util.string.StringUtil
;
import
java.util.ArrayDeque
;
import
java.util.Deque
;
/**
* 数据源管理工具
*/
public
final
class
DataSourceContextHolder
{
private
static
final
ThreadLocal
<
Deque
<
String
>>
DATA_SOURCE_HOLDER
=
new
ThreadLocal
()
{
@Override
protected
Object
initialValue
()
{
return
new
ArrayDeque
();
}
};
private
DataSourceContextHolder
()
{
}
/**
* 获取数据源
*
* @return 数据源名臣
*/
public
static
String
getDs
()
{
return
DATA_SOURCE_HOLDER
.
get
().
peek
();
}
/**
* 设置数据源
*
* @param ds
*/
public
static
void
setDs
(
String
ds
)
{
DATA_SOURCE_HOLDER
.
get
().
push
(
StringUtil
.
isNotEmpty
(
ds
)
?
ds
:
""
);
}
/**
* 如果当前线程是连续切换数据源 只会移除掉当前方法的数据源名称
*/
public
static
void
clear
()
{
Deque
<
String
>
deque
=
DATA_SOURCE_HOLDER
.
get
();
deque
.
poll
();
if
(
deque
.
isEmpty
())
{
forceClear
();
}
}
/**
* 强制清空线程中的数据源
* <p>手动清空数据源,防止OOM</p>
*/
public
static
void
forceClear
()
{
DATA_SOURCE_HOLDER
.
remove
();
}
}
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/properties/MatrixDataSourceProperties.java
0 → 100644
View file @
915cc5f0
package
com
.
secoo
.
mall
.
datasource
.
properties
;
import
com.secoo.mall.datasource.config.MatrixDataSourceConfig
;
import
com.secoo.mall.datasource.constant.DataSourceTypeEnum
;
import
lombok.Data
;
@Data
public
class
MatrixDataSourceProperties
extends
MatrixDataSourceConfig
{
public
static
final
String
PREFIX
=
"spring.datasource.matrix"
;
public
static
final
DataSourceTypeEnum
DEFAULT_DATASOURCE_TYPE
=
DataSourceTypeEnum
.
HIKARI
;
public
MatrixDataSourceProperties
()
{
}
/**
* SourceType DRUID or HIKARI.
* Default value HIKARI.
*/
private
DataSourceTypeEnum
type
=
DEFAULT_DATASOURCE_TYPE
;
public
void
setType
(
String
type
)
{
this
.
type
=
DataSourceTypeEnum
.
getByName
(
type
);
}
}
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/provider/AbsDataSourceProvider.java
0 → 100644
View file @
915cc5f0
package
com
.
secoo
.
mall
.
datasource
.
provider
;
import
com.google.common.collect.Maps
;
import
com.secoo.mall.app.security.encryptor.Encryptor
;
import
com.secoo.mall.datasource.bean.MatrixDataSource
;
import
com.secoo.mall.datasource.config.DataSourceConfig
;
import
com.secoo.mall.datasource.constant.DataSourceConstant
;
import
com.secoo.mall.datasource.factory.EncryptorFactory
;
import
com.secoo.mall.datasource.properties.MatrixDataSourceProperties
;
import
javax.sql.DataSource
;
import
java.util.List
;
import
java.util.Map
;
public
abstract
class
AbsDataSourceProvider
<
T
extends
MatrixDataSourceProperties
>
implements
DataSourceProvider
{
private
Encryptor
<
String
>
encryptor
=
EncryptorFactory
.
getInstance
().
getEncryptor
();
@Override
public
Map
<
String
,
DataSource
>
loadDataSources
()
{
List
<
T
>
list
=
getDataSourceProperties
();
Map
<
String
,
DataSource
>
dataSourceMap
=
Maps
.
newHashMapWithExpectedSize
(
list
.
size
());
for
(
T
properties
:
list
)
{
DataSource
dataSource
=
new
MatrixDataSource
(
properties
.
getType
(),
properties
);
//取得原数据源名称
String
dsName
=
properties
.
getName
().
replace
(
DataSourceConfig
.
POOL_NAME_PRIFIX
,
""
);
dataSourceMap
.
put
(
dsName
,
dataSource
);
}
return
dataSourceMap
;
}
/**
* 解密相关加密属性项项
*/
public
String
decryptPropertyItemValue
(
String
value
)
{
if
(
value
.
contains
(
DataSourceConstant
.
ENCRY_FLAG
))
{
value
=
encryptor
.
decrypt
(
value
);
}
return
value
;
}
protected
abstract
List
<
T
>
getDataSourceProperties
();
}
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/provider/ApolloDataSourceProvider.java
0 → 100644
View file @
915cc5f0
package
com
.
secoo
.
mall
.
datasource
.
provider
;
import
com.ctrip.framework.apollo.Config
;
import
com.ctrip.framework.apollo.ConfigService
;
import
com.google.common.collect.Lists
;
import
com.secoo.mall.common.core.exception.BusinessException
;
import
com.secoo.mall.common.util.colletion.CollectionUtil
;
import
com.secoo.mall.common.util.string.StringUtil
;
import
com.secoo.mall.datasource.constant.DataSourceConstant
;
import
com.secoo.mall.datasource.errorCode.DataSourceError
;
import
com.secoo.mall.datasource.properties.MatrixDataSourceProperties
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.reflect.MethodUtils
;
import
javax.sql.DataSource
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.stream.Collectors
;
/**
* 从Apollo配置中心进行加载
*/
@Slf4j
public
class
ApolloDataSourceProvider
extends
AbsDataSourceProvider
<
MatrixDataSourceProperties
>
{
/**
* 从appollo加载配置信息
*
* @return
*/
@Override
protected
List
<
MatrixDataSourceProperties
>
getDataSourceProperties
()
{
Config
appConfig
=
ConfigService
.
getConfig
(
DataSourceConstant
.
DB_NAMESPACE
);
Set
<
String
>
propertyNames
=
appConfig
.
getPropertyNames
();
List
<
MatrixDataSourceProperties
>
list
=
Lists
.
newArrayList
();
Map
<
String
,
DataSource
>
dataSourceMap
=
new
HashMap
<>();
if
(
CollectionUtil
.
isEmpty
(
propertyNames
))
{
throw
new
BusinessException
(
DataSourceError
.
APOLLO_CONFIG_NOT_EXIST
);
}
//用数据源名字为key,进行分组
Map
<
String
,
List
<
String
>>
propertyMap
=
propertyNames
.
stream
().
filter
(
pro
->
pro
.
contains
(
MatrixDataSourceProperties
.
PREFIX
)).
map
(
pro
->
pro
.
replace
(
MatrixDataSourceProperties
.
PREFIX
,
""
))
.
collect
(
Collectors
.
groupingBy
(
str
->
str
.
split
(
DataSourceConstant
.
PROPETY_SPLIT_CHAR
)[
1
]));
try
{
for
(
Map
.
Entry
<
String
,
List
<
String
>>
entry
:
propertyMap
.
entrySet
())
{
String
dsName
=
entry
.
getKey
();
MatrixDataSourceProperties
matrixDataSourceProperties
=
new
MatrixDataSourceProperties
();
matrixDataSourceProperties
.
setName
(
dsName
);
for
(
String
property
:
entry
.
getValue
())
{
String
propertyFullPath
=
MatrixDataSourceProperties
.
PREFIX
+
property
;
String
value
=
decryptPropertyItemValue
(
appConfig
.
getProperty
(
propertyFullPath
,
""
));
//得到实际的属性,首字母大写
String
beanProperty
=
StringUtil
.
capitalize
(
property
.
split
(
DataSourceConstant
.
PROPETY_SPLIT_CHAR
)[
2
]);
MethodUtils
.
invokeExactMethod
(
matrixDataSourceProperties
,
"set"
+
beanProperty
,
value
);
}
log
.
info
(
"init datasource name:{}"
,
dsName
);
list
.
add
(
matrixDataSourceProperties
);
}
}
catch
(
Exception
e
)
{
log
.
error
(
"e:"
,
e
);
throw
new
BusinessException
(
DataSourceError
.
APOLLO_CONFIG_NOT_EXIST
);
}
return
list
;
}
}
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/provider/DataSourceProvider.java
0 → 100644
View file @
915cc5f0
package
com
.
secoo
.
mall
.
datasource
.
provider
;
import
javax.sql.DataSource
;
import
java.util.Map
;
public
interface
DataSourceProvider
{
/**
* 加载定义的数据源
*
* @return
*/
Map
<
String
,
DataSource
>
loadDataSources
();
}
matrix-datasource/matrix-datasource-core/src/main/java/com/secoo/mall/datasource/provider/DefaultDataSourceProvider.java
0 → 100644
View file @
915cc5f0
package
com
.
secoo
.
mall
.
datasource
.
provider
;
import
com.secoo.mall.datasource.properties.MatrixDataSourceProperties
;
import
lombok.Setter
;
import
java.util.List
;
/**
* 默认的,基于Spring的配置的加载方式
*/
public
class
DefaultDataSourceProvider
extends
AbsDataSourceProvider
<
MatrixDataSourceProperties
>
{
/**
* 注入配置
*/
@Setter
private
List
<
MatrixDataSourceProperties
>
dataSourceConfigs
;
@Override
protected
List
<
MatrixDataSourceProperties
>
getDataSourceProperties
()
{
return
this
.
dataSourceConfigs
;
}
}
matrix-datasource/matrix-datasource-core/src/test/java/com/secoo/mall/mybatis/datasouce/DataSourceTest.java
0 → 100644
View file @
915cc5f0
package
com
.
secoo
.
mall
.
mybatis
.
datasouce
;
import
com.secoo.mall.datasource.bean.MatrixDataSource
;
import
com.secoo.mall.datasource.config.MatrixDataSourceConfig
;
import
com.secoo.mall.datasource.constant.DataSourceTypeEnum
;
import
org.junit.Test
;
public
class
DataSourceTest
{
@Test
public
void
testCreateDataSource
()
{
MatrixDataSourceConfig
config
=
new
MatrixDataSourceConfig
();
config
.
setName
(
"01"
);
// config.setType(DataSourceType.HIKARI);
config
.
setUrl
(
"jdbc:mysql://127.0.0.1:3306/appmsdb?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&useSSL=false"
);
config
.
setPassword
(
"mysql"
);
config
.
setUsername
(
"root"
);
MatrixDataSource
dataSource
=
new
MatrixDataSource
(
DataSourceTypeEnum
.
HIKARI
,
config
);
System
.
out
.
println
(
dataSource
);
}
}
matrix-datasource/matrix-datasource-core/src/test/resources/application.yml
0 → 100644
View file @
915cc5f0
mat
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment