springboot 版本
依赖版本:1.5.*
<!--spring 切面-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!--springboot mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
<!--数据库连接驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.30</version>
</dependency>
<!--连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.0</version>
</dependency>
yml 配置
mybatis:
configuration:
log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
type-aliases-package: com.orange.entity
mapper-locations: classpath:mapper/*.xml
spring:
profiles: development
datasource:
master2:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://*:3306/orange?autoReconnect=true&characterEncoding=utf8&useUnicode=true&zeroDateTimeBehavior=convertToNull&noAccessToProcedureBodies=true
username: *
password: *
type: com.alibaba.druid.pool.DruidDataSource
initialSize: 5
maxActive: 5
maxWait: 60000
minIdle: 5
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 'x'
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20
master:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://*:3306/orange?autoReconnect=true&characterEncoding=utf8&useUnicode=true&zeroDateTimeBehavior=convertToNull&noAccessToProcedureBodies=true
username: *
password: *
type: com.alibaba.druid.pool.DruidDataSource
initialSize: 5
maxActive: 15
maxWait: 60000
minIdle: 5
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 'x'
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
filters: stat,wall,log4j
useGlobalDataSourceStat: true
webStatFilter:
# exclusions: *.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*
sessionStatEnable: true
principalSessionName: USER_SESSION
sessionStatMaxCount: 1000
获取当前返回的数据源基础信息实现
package com.orange.config;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
* Summary: 获取当前返回的数据源基础信息实现
* Created by wuyunfeng on 09. 十月 2017 下午3:45.
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.getDB();
}
}
设置当前数据源名称
package com.orange.config;
import lombok.extern.slf4j.Slf4j;
/**
* Summary: 设置当前数据源名称
* Created by wuyunfeng on 09. 十月 2017 下午3:36.
*/
@Slf4j
public class DataSourceContextHolder {
public static final String DEFAULT_DS = "master";
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
// 设置数据源名
public static void setDB(String dbType) {
log.debug("切换到{}数据源", dbType);
contextHolder.set(dbType);
}
// 获取数据源名
public static String getDB() {
return contextHolder.get();
}
// 清除数据源名
public static void clearDB() {
contextHolder.remove();
}
}
数据源配置:DataSourceConfig
package com.orange.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.orange.utils.constants.Constant;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
/**
* Summary: 数据源连接配置
* Created by wuyunfeng on 10. 十月 2017 下午10:17.
*/
@Configuration
public class DataSourceConfig {
@Bean(name = Constant.DS_MASTER)
@ConfigurationProperties(prefix = "spring.datasource.master")
public DruidDataSource masterSource() {
return DruidDataSourceBuilder.create().build();
}
@Bean(name = Constant.DS_SALVE)
@ConfigurationProperties(prefix = "spring.datasource.slave")
public DruidDataSource slaveSource() {
return DruidDataSourceBuilder.create().build();
}
/**
* 动态数据源集合创建
*
* @return DataSource
*/
@Bean(name = "dynamicDS")
public DataSource dataSource() {
DynamicDataSource dynamicDataSource = new DynamicDataSource();
// 默认数据源
dynamicDataSource.setDefaultTargetDataSource(masterSource());
// 配置多数据源
Map<Object, Object> dsMap = new HashMap<>();
dsMap.put(Constant.DS_MASTER, masterSource());
dsMap.put(Constant.DS_SALVE, slaveSource());
dynamicDataSource.setTargetDataSources(dsMap);
return dynamicDataSource;
}
}
MybatisDbConfig
package com.orange.config;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.boot.autoconfigure.SpringBootVFS;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.TransactionManagementConfigurer;
import javax.sql.DataSource;
/**
* Summary:
* Created by wuyunfeng on 09. 十月 2017 下午3:27.
*/
@SuppressWarnings("SpringAutowiredFieldsWarningInspection")
@Configuration
@MapperScan(basePackages = {"com.orange.mapper"}, sqlSessionFactoryRef = "sqlSessionFactory")
@EnableTransactionManagement
public class MybatisDbConfig implements TransactionManagementConfigurer {
@Autowired
@Qualifier("dynamicDS")
private DataSource ds;
@Value("${mybatis.type-aliases-package}")
private String typeAliasesPackage;
@Value("${mybatis.mapper-locations}")
private String mapperLocations;
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(ds);
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
factoryBean.setTypeAliasesPackage(typeAliasesPackage);
factoryBean.setMapperLocations(resolver.getResources(mapperLocations));
factoryBean.setVfs(SpringBootVFS.class);
return factoryBean.getObject();
}
// @Bean
// public SqlSessionTemplate sqlSessionTemplate() throws Exception {
// SqlSessionTemplate template = new SqlSessionTemplate(sqlSessionFactory());
// return template;
// }
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(ds);
}
/**
* 事务处理 配置
* 结合 @EnableTransactionManagement
* @return PlatformTransactionManager
*/
@Override
public PlatformTransactionManager annotationDrivenTransactionManager() {
return transactionManager();
}
}
package com.gary.annotation;
import com.gary.utils.constants.Constant;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Summary: 自定义 mybatis 数据源注解
* Created by wuyunfeng on 09. 十月 2017 下午3:58.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({
ElementType.METHOD
})
public @interface DS {
String value() default Constant.DS_MASTER;
}
package com.gary.aspect;
import com.gary.annotation.DS;
import com.gary.config.DataSourceContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
* Summary: mybatis 数据源数据源切换 切面实现
*
* @author wuyunfeng
* @date 09. 十月 2017 下午4:00
*/
@Aspect
@Component
@Order(-1)
@Slf4j
public class DynamicDataSourceAspect {
@Before(value = "@annotation(ds)", argNames = "point, ds")
public void beforeSwitchDS(@SuppressWarnings("unused") JoinPoint point, DS ds) {
// String methodName = point.getSignature().getName();
// 得到方法的参数的类型
String dataSource = DataSourceContextHolder.DEFAULT_DS;
try {
// 取出注解中的数据源名
dataSource = ds.value();
} catch (Exception e) {
e.printStackTrace();
log.error("unknowException {}", e.toString());
}
// 切换数据源
DataSourceContextHolder.setDB(dataSource);
}
@After(value = "@annotation(com.gary.annotation.DS)")
public void afterSwitchDS(@SuppressWarnings("unused") JoinPoint point) {
DataSourceContextHolder.clearDB();
}
}
更多文章请到我的个人博客https://blog.pearpai.com/