Spring Boot +Mybatis+druid动态多数据源自由切换
实现数据源动态切换,希望能帮到需要的人,代码copy就能用
- pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.7.RELEASE</version>
</parent>
<groupId>com.crr.zgl</groupId>
<artifactId>api</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<java.version>1.8</java.version>
<jackson-dataformat-yaml.version>2.8.3</jackson-dataformat-yaml.version>
<junit.version>4.12</junit.version>
<log4j.version>2.6.2</log4j.version>
<druid.version>1.1.3</druid.version>
<apache-commons-pool2.version>2.4.2</apache-commons-pool2.version>
<mysql-connector-java.version>6.0.5</mysql-connector-java.version>
<mybatis-spring-boot-starter.version>1.1.1</mybatis-spring-boot-starter.version>
<jersey-client.version>2.23.1</jersey-client.version>
<jedis.version>2.9.0</jedis.version>
<apache-commons-lang3.version>3.4</apache-commons-lang3.version>
<commons-lang.version>2.6</commons-lang.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<scope>test</scope>
</dependency>
<dependency> <!--mysql java驱动-->
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-connector-java.version}</version>
</dependency>
<dependency><!--parse yaml-->
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
<version>${jackson-dataformat-yaml.version}</version>
</dependency>
<dependency><!--回归测试框架-->
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<dependency><!-- log4j2 2个核心包之一 -->
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency><!--JDBC连接池、监控组件-->
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<dependency><!--Tomcat Jdbc Pool 数据库连接池-->
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>${apache-commons-pool2.version}</version>
</dependency>
<dependency><!--tomcat 自带jdbc-->
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jdbc</artifactId>
</dependency>
<dependency> <!--mysql java驱动-->
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-connector-java.version}</version>
</dependency>
<dependency><!--是JAX-RS(JSR311)开源参考实现用于构建RESTful Web service-->
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>${jersey-client.version}</version>
</dependency>
<dependency><!--redis 客户端-->
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>${jedis.version}</version>
</dependency>
<dependency> <!-- 引入log4j2依赖 -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency> <!-- 加上这个才能辨认到log4j2.yml文件 -->
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
</dependency>
<dependency><!--包含大量和JavaBean操作有关的工具方法-->
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<exclusions>
<exclusion><!--使用抽象的API记录日志,这些API都是实现无关的-->
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency><!--是基于JDK API开发一系列公共基础类,涉及到数组工具类,字符串工具类,字符工具类,数学方面,时间日期工具类,异常,事件等工具类-->
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${apache-commons-lang3.version}</version>
</dependency>
<dependency><!--主要是一些公共的工具集合,比如对字符、数组的操作等等-->
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>${commons-lang.version}</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.5.3-beta</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-client</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.7.1</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.10</version>
</dependency>
</dependencies>
<build>
<finalName>api</finalName>
<resources>
<resource>
<directory>${basedir}/src/main/resources</directory>
<includes>
<include>**/*</include>
</includes>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
<!-- 是否替换资源中的属性-->
<filtering>false</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
- 数据源配置
spring.datasource.masterMapperLocations=classpath:com/rrc/zgl/dao/*/impl/*Mapper.xml
#master数据源
spring.datasource.master.url=jdbc:mysql://localhost:3306/zgl?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false
spring.datasource.master.username=root
spring.datasource.master.password=123456
spring.datasource.master.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.master.initialSize=5
spring.datasource.master.minIdle=5
spring.datasource.master.maxActive= 20
spring.datasource.master.maxWait= 60000
spring.datasource.master.timeBetweenEvictionRunsMillis= 60000
spring.datasource.master.minEvictableIdleTimeMillis= 300000
spring.datasource.master.validationQuery= SELECT 1
spring.datasource.master.testWhileIdle= true
spring.datasource.master.testOnBorrow= false
spring.datasource.master.testOnReturn= false
spring.datasource.master.poolPreparedStatements= true
spring.datasource.master.maxPoolPreparedStatementPerConnectionSize= 20
spring.datasource.master.filters= stat,wall,log4j
spring.datasource.master.connectionProperties= druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
spring.datasource.master.useGlobalDataSourceStat= true
#cluster数据源
spring.datasource.cluster.url=jdbc:mysql://localhost:3306/zgl1?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false
spring.datasource.cluster.username=root
spring.datasource.cluster.password=123456
spring.datasource.cluster.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.cluster.initialSize=5
spring.datasource.cluster.minIdle=5
spring.datasource.cluster.maxActive= 20
spring.datasource.cluster.maxWait= 60000
spring.datasource.cluster.timeBetweenEvictionRunsMillis= 60000
spring.datasource.cluster.minEvictableIdleTimeMillis= 300000
spring.datasource.cluster.validationQuery= SELECT 1
spring.datasource.cluster.testWhileIdle= true
spring.datasource.cluster.testOnBorrow= false
spring.datasource.cluster.testOnReturn= false
spring.datasource.cluster.poolPreparedStatements= true
spring.datasource.cluster.maxPoolPreparedStatementPerConnectionSize= 20
spring.datasource.cluster.filters= stat,wall,log4j
spring.datasource.cluster.connectionProperties= druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
spring.datasource.cluster.useGlobalDataSourceStat= true
- 启动类
@SpringBootApplication
@PropertySource(value = {"classpath:dataSource.properties"})
@ServletComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
4.配置数据源1
@Configuration
@EnableTransactionManagement
public class ClusterDruidDataSourceConfig {
@Value("${spring.datasource.masterMapperLocations}")
private String clusterMapperLocations;
@ConfigurationProperties(prefix = "spring.datasource.cluster")
@Bean(name = "clusterDataSource")
public DataSource clusterDataSource() {
return new DruidDataSource();
}
/**
* SqlSessionFactory配置
*
* @return
* @throws Exception
*/
@Bean(name = "clusterSqlSessionFactory")
public SqlSessionFactory clusterSqlSessionFactory(
@Qualifier("clusterDataSource") DataSource dataSource
) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
//配置mapper文件位置
sqlSessionFactoryBean.setMapperLocations(resolver.getResources(clusterMapperLocations));
return sqlSessionFactoryBean.getObject();
}
/**
* 配置事物管理器
*
* @return
*/
@Bean(name = "clusterTransactionManager")
public DataSourceTransactionManager clusterTransactionManager(
@Qualifier("clusterDataSource") DataSource dataSource
) {
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(dataSource);
return dataSourceTransactionManager;
}
- 数据源2
@Configuration
@EnableTransactionManagement
public class MasterDruidDataSourceConfig {
@Value("${spring.datasource.masterMapperLocations}")
private String masterMapperLocations;
@ConfigurationProperties(prefix = "spring.datasource.master")
@Bean(name = "masterDataSource")
@Primary
public DataSource masterDataSource() {
return new DruidDataSource();
}
/**
* SqlSessionFactory配置
*
* @return
* @throws Exception
*/
@Bean(name = "masterSqlSessionFactory")
@Primary
public SqlSessionFactory masterSqlSessionFactory(
@Qualifier("masterDataSource") DataSource dataSource
) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
// 配置mapper文件位置
sqlSessionFactoryBean.setMapperLocations(resolver.getResources(masterMapperLocations));
return sqlSessionFactoryBean.getObject();
}
/**
* 配置事物管理器
*
* @return
*/
@Bean(name = "masterTransactionManager")
@Primary
public DataSourceTransactionManager masterTransactionManager(
@Qualifier("masterDataSource") DataSource dataSource
) {
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(dataSource);
return dataSourceTransactionManager;
}
}
- 数据源动态切换
@Aspect
@Component
public class DynamicDataSourceAspect {
private Logger logger = LoggerFactory.getLogger(DynamicDataSourceAspect.class);
@Around("execution(* com.crr.zgl.dao..*.*(..))")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
Signature signature = pjp.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
boolean methodAnnotation = method.isAnnotationPresent(TargetDataSource.class);
TargetDataSource targetDataSource = null;
if (methodAnnotation) {
targetDataSource = method.getAnnotation(TargetDataSource.class);
} else {
Class clazz[] = pjp.getTarget().getClass().getInterfaces();
targetDataSource = (TargetDataSource) clazz[0].getAnnotation(TargetDataSource.class);
}
if (targetDataSource != null) {
DynamicDataSourceHolder.setDataSource(targetDataSource.dataSource());
logger.debug("mybatis接口: " + (method.getDeclaringClass() + "." + method.getName()) + " 设置数据源 key is " + targetDataSource.dataSource());
}
Object result = pjp.proceed();//执行方法
DynamicDataSourceHolder.clearDataSource();
return result;
}
}
- 数据源切换
/**
* 多数据进行切换
*/
public class DynamicDataSourceHolder {
//使用ThreadLocal把数据源与当前线程绑定
private static final ThreadLocal<String> dataSources = new ThreadLocal<String>();
public static void setDataSource(String dataSourceName) {
dataSources.set(dataSourceName);
}
public static String getDataSource() {
return (String) dataSources.get();
}
public static void clearDataSource() {
dataSources.remove();
}
}
- 获取数据源
/**
* 动态数据源获取sessionfactory
* @Author:zhangguangliang
*/
public class DynamicSqlSessionTemplate extends SqlSessionTemplate {
private static Logger logger = LoggerFactory.getLogger(DynamicSqlSessionTemplate.class);
private SqlSessionFactory sqlSessionFactory;
private ExecutorType executorType;
private SqlSession sqlSessionProxy;
private PersistenceExceptionTranslator exceptionTranslator;
private Map<Object, SqlSessionFactory> targetSqlSessionFactorys;
private SqlSessionFactory defaultTargetSqlSessionFactory;
public void setTargetSqlSessionFactorys(Map<Object, SqlSessionFactory> targetSqlSessionFactorys) {
this.targetSqlSessionFactorys = targetSqlSessionFactorys;
}
public void setDefaultTargetSqlSessionFactory(SqlSessionFactory defaultTargetSqlSessionFactory) {
this.defaultTargetSqlSessionFactory = defaultTargetSqlSessionFactory;
}
public DynamicSqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
this(sqlSessionFactory, sqlSessionFactory.getConfiguration().getDefaultExecutorType());
}
public DynamicSqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType) {
this(sqlSessionFactory, executorType, new MyBatisExceptionTranslator(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(), true));
}
public DynamicSqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) {
super(sqlSessionFactory, executorType, exceptionTranslator);
this.sqlSessionFactory = sqlSessionFactory;
this.executorType = executorType;
this.exceptionTranslator = exceptionTranslator;
this.sqlSessionProxy = (SqlSession) newProxyInstance(SqlSessionFactory.class.getClassLoader(), new Class[]{SqlSession.class}, new SqlSessionInterceptor());
this.defaultTargetSqlSessionFactory = sqlSessionFactory;
}
@Override
public SqlSessionFactory getSqlSessionFactory() {
String dataSourceType = DynamicDataSourceHolder.getDataSource();
SqlSessionFactory targetSqlSessionFactory = targetSqlSessionFactorys.get(dataSourceType);
if (targetSqlSessionFactory != null) {
return targetSqlSessionFactory;
} else if (defaultTargetSqlSessionFactory != null) {
if (dataSourceType != null) {
logger.warn("此[" + dataSourceType + "]dataSourceType未配置文件中配置targetSqlSessionFactorys,将会返回defaultTargetSqlSessionFactory来执行后面的操作");
}
return defaultTargetSqlSessionFactory;
} else {
Assert.notNull(targetSqlSessionFactorys, "Property 'targetSqlSessionFactorys' or 'defaultTargetSqlSessionFactory' are required");
Assert.notNull(defaultTargetSqlSessionFactory, "Property 'defaultTargetSqlSessionFactory' or 'targetSqlSessionFactorys' are required");
}
return this.sqlSessionFactory;
}
@Override
public Configuration getConfiguration() {
return this.getSqlSessionFactory().getConfiguration();
}
@Override
public ExecutorType getExecutorType() {
return this.executorType;
}
@Override
public PersistenceExceptionTranslator getPersistenceExceptionTranslator() {
return this.exceptionTranslator;
}
/**
* {@inheritDoc}
*/
@Override
public <T> T selectOne(String statement) {
return this.sqlSessionProxy.<T>selectOne(statement);
}
/**
* {@inheritDoc}
*/
@Override
public <T> T selectOne(String statement, Object parameter) {
return this.sqlSessionProxy.<T>selectOne(statement, parameter);
}
/**
* {@inheritDoc}
*/
@Override
public <K, V> Map<K, V> selectMap(String statement, String mapKey) {
return this.sqlSessionProxy.<K, V>selectMap(statement, mapKey);
}
/**
* {@inheritDoc}
*/
@Override
public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey) {
return this.sqlSessionProxy.<K, V>selectMap(statement, parameter, mapKey);
}
/**
* {@inheritDoc}
*/
@Override
public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) {
return this.sqlSessionProxy.<K, V>selectMap(statement, parameter, mapKey, rowBounds);
}
/**
* {@inheritDoc}
*/
@Override
public <E> List<E> selectList(String statement) {
return this.sqlSessionProxy.<E>selectList(statement);
}
/**
* {@inheritDoc}
*/
@Override
public <E> List<E> selectList(String statement, Object parameter) {
return this.sqlSessionProxy.<E>selectList(statement, parameter);
}
/**
* {@inheritDoc}
*/
@Override
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
return this.sqlSessionProxy.<E>selectList(statement, parameter, rowBounds);
}
/**
* {@inheritDoc}
*/
@Override
public void select(String statement, ResultHandler handler) {
this.sqlSessionProxy.select(statement, handler);
}
/**
* {@inheritDoc}
*/
@Override
public void select(String statement, Object parameter, ResultHandler handler) {
this.sqlSessionProxy.select(statement, parameter, handler);
}
/**
* {@inheritDoc}
*/
@Override
public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) {
this.sqlSessionProxy.select(statement, parameter, rowBounds, handler);
}
/**
* {@inheritDoc}
*/
@Override
public int insert(String statement) {
return this.sqlSessionProxy.insert(statement);
}
/**
* {@inheritDoc}
*/
@Override
public int insert(String statement, Object parameter) {
return this.sqlSessionProxy.insert(statement, parameter);
}
/**
* {@inheritDoc}
*/
@Override
public int update(String statement) {
return this.sqlSessionProxy.update(statement);
}
/**
* {@inheritDoc}
*/
@Override
public int update(String statement, Object parameter) {
return this.sqlSessionProxy.update(statement, parameter);
}
/**
* {@inheritDoc}
*/
@Override
public int delete(String statement) {
return this.sqlSessionProxy.delete(statement);
}
/**
* {@inheritDoc}
*/
@Override
public int delete(String statement, Object parameter) {
return this.sqlSessionProxy.delete(statement, parameter);
}
/**
* {@inheritDoc}
*/
@Override
public <T> T getMapper(Class<T> type) {
return getConfiguration().getMapper(type, this);
}
/**
* {@inheritDoc}
*/
@Override
public void commit() {
throw new UnsupportedOperationException("Manual commit is not allowed over a Spring managed SqlSession");
}
/**
* {@inheritDoc}
*/
@Override
public void commit(boolean force) {
throw new UnsupportedOperationException("Manual commit is not allowed over a Spring managed SqlSession");
}
/**
* {@inheritDoc}
*/
@Override
public void rollback() {
throw new UnsupportedOperationException("Manual rollback is not allowed over a Spring managed SqlSession");
}
/**
* {@inheritDoc}
*/
@Override
public void rollback(boolean force) {
throw new UnsupportedOperationException("Manual rollback is not allowed over a Spring managed SqlSession");
}
/**
* {@inheritDoc}
*/
@Override
public void close() {
throw new UnsupportedOperationException("Manual close is not allowed over a Spring managed SqlSession");
}
/**
* {@inheritDoc}
*/
@Override
public void clearCache() {
this.sqlSessionProxy.clearCache();
}
/**
* {@inheritDoc}
*/
@Override
public Connection getConnection() {
return this.sqlSessionProxy.getConnection();
}
/**
* {@inheritDoc}
*
* @since 1.0.2
*/
@Override
public List<BatchResult> flushStatements() {
return this.sqlSessionProxy.flushStatements();
}
/**
* Proxy needed to route MyBatis method calls to the proper SqlSession got from Spring's Transaction Manager It also unwraps exceptions thrown by
* {@code Method#invoke(Object, Object...)} to pass a {@code PersistenceException} to the {@code PersistenceExceptionTranslator}.
*/
private class SqlSessionInterceptor implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
SqlSession sqlSession = getSqlSession(DynamicSqlSessionTemplate.this.getSqlSessionFactory(), DynamicSqlSessionTemplate.this.executorType, DynamicSqlSessionTemplate.this.exceptionTranslator);
try {
Object result = method.invoke(sqlSession, args);
if (!isSqlSessionTransactional(sqlSession, DynamicSqlSessionTemplate.this.getSqlSessionFactory())) {
// force commit even on non-dirty sessions because some databases require / a commit/rollback before calling close()
sqlSession.commit(true);
}
return result;
} catch (Throwable t) {
Throwable unwrapped = unwrapThrowable(t);
if (DynamicSqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) {
// release the connection to avoid a deadlock if the translator is no loaded. See issue #22
closeSqlSession(sqlSession, DynamicSqlSessionTemplate.this.getSqlSessionFactory());
sqlSession = null;
Throwable translated = DynamicSqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException) unwrapped);
if (translated != null) {
unwrapped = translated;
}
}
throw unwrapped;
} finally {
if (sqlSession != null) {
closeSqlSession(sqlSession, DynamicSqlSessionTemplate.this.getSqlSessionFactory());
}
}
}
}
}
/**
* 反射工具类
*
* @Author:zhangguangliang
* @Time:2017年9月16日14:44:10
*/
public class ReflectionUtil extends ReflectionUtils {
private static Logger logger = LoggerFactory.getLogger(ReflectionUtil.class);
/**
* 获取obj对象fieldName的Field
*
* @param obj
* @param fieldName
* @return
*/
public static Field getFieldByFieldName(Object obj, String fieldName) {
if (obj == null || fieldName == null) {
return null;
}
for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) {
try {
return superClass.getDeclaredField(fieldName);
} catch (Exception e) {
}
}
return null;
}
/**
* 获取obj对象fieldName的属性值
*
* @param obj
* @param fieldName
* @return
*/
public static Object getValueByFieldName(Object obj, String fieldName) {
Object value = null;
try {
Field field = getFieldByFieldName(obj, fieldName);
if (field != null) {
if (field.isAccessible()) {
value = field.get(obj);
} else {
field.setAccessible(true);
value = field.get(obj);
field.setAccessible(false);
}
}
} catch (Exception e) {
logger.error("更加属性名称获取属性值异常:");
}
return value;
}
/**
* 获取obj对象fieldName的属性值
*
* @param obj
* @param fieldName
* @return
*/
@SuppressWarnings("unchecked")
public static <T> T getValueByFieldType(Object obj, Class<T> fieldType) {
Object value = null;
for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) {
try {
Field[] fields = superClass.getDeclaredFields();
for (Field f : fields) {
if (f.getType() == fieldType) {
if (f.isAccessible()) {
value = f.get(obj);
break;
} else {
f.setAccessible(true);
value = f.get(obj);
f.setAccessible(false);
break;
}
}
}
if (value != null) {
break;
}
} catch (Exception e) {
logger.error("更加属性类型获取属性值异常:");
}
}
return (T) value;
}
/**
* 设置obj对象fieldName的属性值
*
* @param obj
* @param fieldName
* @param value
* @throws SecurityException
* @throws NoSuchFieldException
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
public static boolean setValueByFieldName(Object obj, String fieldName, Object value) {
try {
// java.lang.Class.getDeclaredField()方法用法实例教程 -
// 方法返回一个Field对象,它反映此Class对象所表示的类或接口的指定已声明字段。
// 此方法返回这个类中的指定字段的Field对象
Field field = obj.getClass().getDeclaredField(fieldName);
/**
* public void setAccessible(boolean flag) throws SecurityException将此对象的 accessible 标志设置为指示的布尔值。值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。值为 false 则指示反射的对象应该实施 Java 语言访问检查。 首先,如果存在安全管理器,则在
* ReflectPermission("suppressAccessChecks") 权限下调用 checkPermission 方法。 如果 flag 为 true,并且不能更改此对象的可访问性(例如,如果此元素对象是 Class 类的 Constructor 对象),则会引发 SecurityException。 如果此对象是 java.lang.Class 类的 Constructor 对象,并且
* flag 为 true,则会引发 SecurityException。 参数: flag - accessible 标志的新值 抛出: SecurityException - 如果请求被拒绝。
*/
if (field.isAccessible()) {// 获取此对象的 accessible 标志的值。
field.set(obj, value);// 将指定对象变量上此 Field 对象表示的字段设置为指定的新值
} else {
field.setAccessible(true);
field.set(obj, value);
field.setAccessible(false);
}
return true;
} catch (Exception e) {
logger.error("更加属性名称设置属性值异常:");
}
return false;
}
/**
* 执行某对象的方法
*
* @param owner
* @param methodName
* @param args
* @return
* @throws Exception
*/
public Object invokeMethod(Object owner, String methodName, Object[] args) throws Exception {
Class<? extends Object> cls = owner.getClass();
@SuppressWarnings("rawtypes")
Class[] argclass = new Class[args.length];
for (int i = 0, j = argclass.length; i < j; i++) {
argclass[i] = args[i].getClass();
}
Method method = cls.getMethod(methodName, argclass);
return method.invoke(owner, args);
}
/**
* 执行静态类的方法
*
* @param className
* @param methodName
* @param args
* @return
* @throws Exception
*/
public Object invokeStaticMethod(String className, String methodName, Object[] args) throws Exception {
Class<?> cls = Class.forName(className);
@SuppressWarnings("rawtypes")
Class[] argclass = new Class[args.length];
for (int i = 0, j = argclass.length; i < j; i++) {
argclass[i] = args[i].getClass();
}
Method method = cls.getMethod(methodName, argclass);
return method.invoke(null, args);
}
public Object newInstance(String className, Object[] args) throws Exception {
Class<?> clss = Class.forName(className);
@SuppressWarnings("rawtypes")
Class[] argclass = new Class[args.length];
for (int i = 0, j = argclass.length; i < j; i++) {
argclass[i] = args[i].getClass();
}
Constructor<?> cons = clss.getConstructor(argclass);
return cons.newInstance();
}
}
- druid配置类
@WebFilter(filterName="druidWebStatFilter",urlPatterns="/*",
initParams={
@WebInitParam(name="exclusions",value="*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*")// 忽略资源
})
public class DruidStatFilter extends WebStatFilter {
}
@WebServlet(urlPatterns = "/druid/*",
initParams = {
@WebInitParam(name = "allow", value = "127.0.0.1"),// IP白名单 (没有配置或者为空,则允许所有访问)
//@WebInitParam(name="deny",value="192.168.16.111"),// IP黑名单 (存在共同时,deny优先于allow)
//@WebInitParam(name="loginUsername",value="zgl"),// 用户名
//@WebInitParam(name="loginPassword",value="zgl"),// 密码
@WebInitParam(name = "resetEnable", value = "false")// 禁用HTML页面上的“Reset All”功能
})
public class DruidStatViewServlet extends StatViewServlet {
// 按照BeanId来拦截配置 用来bean的监控
/* @Bean(value = "druid-stat-interceptor")
public DruidStatInterceptor DruidStatInterceptor() {
DruidStatInterceptor druidStatInterceptor = new DruidStatInterceptor();
return druidStatInterceptor;
}
@Bean
public BeanNameAutoProxyCreator beanNameAutoProxyCreator() {
BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();
beanNameAutoProxyCreator.setProxyTargetClass(true);
// 设置要监控的bean的id
beanNameAutoProxyCreator.setBeanNames("clusterSqlSessionFactory","masterTransactionManager");
beanNameAutoProxyCreator.setInterceptorNames("druid-stat-interceptor");
return beanNameAutoProxyCreator;
}*/
}
- 使用
@TargetDataSource(dataSource = DataSourceConfig.masterDataSource_)
@Repository(value = "userMapper")
public interface UserMapper {
int deleteByPrimaryKey(Long id);
@TargetDataSource(dataSource = DataSourceConfig.clusterDataSource_)
int insert(User record);
int insertSelective(User record);
User selectByPrimaryKey(Long id);
int updateByPrimaryKeySelective(User record);
int updateByPrimaryKey(User record);
}
@Transactional(transactionManager = "clusterTransactionManager",rollbackFor=Exception.class)
public String test() {
User user = new User();
user.setName("124");
user.setPassword("setPassword");
int insert1 = zgl1UserMapper.insert(user);
//int insert = userMapper.insert(user);
return "success";
}