springboot datajpa 多数据库主从分离代码实现
2018-03-23 本文已影响158人
anyangdp
pom.xml
<?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>
<groupId>com.springboot</groupId>
<artifactId>springboot-muti-dataSource</artifactId>
<version>1.0-SNAPSHOT</version>
<!---https://github.com/anyangdp/anyangdp-frame(datajpa集成,clone到本地打包使用,长期更新,麻烦star谢谢。)--->
<parent>
<groupId>com.anyangdp</groupId>
<artifactId>anyangdp-parent</artifactId>
<version>1.0.0</version>
</parent>
<properties>
<java.compile.version>1.8</java.compile.version>
<!-- Maven plugin -->
<maven.compiler.plugin.version>3.2</maven.compiler.plugin.version>
<maven-surefire-plugin.version>2.18.1</maven-surefire-plugin.version>
<maven-source-plugin.version>2.4</maven-source-plugin.version>
<maven-deploy-plugin.version>2.8.2</maven-deploy-plugin.version>
<maven-release-plugin.version>2.5.1</maven-release-plugin.version>
<flyway-maven-plugin.version>4.1.1</flyway-maven-plugin.version>
</properties>
<dependencies>
<dependency>
<groupId>com.anyangdp</groupId>
<artifactId>common-jpa-biz</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
</project>
application.properties:
### master
spring.datasource.url=jdbc:mysql://localhost:3306/master?serverTimezone=UTC&characterEncoding=utf-8&useSSL=false
spring.datasource.username=
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
### cluster
cluster.datasource.url=jdbc:mysql://localhost:3307/slaver?useUnicode=true&characterEncoding=utf8
cluster.datasource.username=
cluster.datasource.password=
cluster.datasource.driverClassName=com.mysql.jdbc.Driver
相关java代码
/**
* @Author anyang
* @CreateTime 2018/3/23
* @Des 数据源配置
*/
@Configuration
public class DataSourceConfiguration {
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource masterDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix = "cluster.datasource")
public DataSource slaveDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
public DataSource routeDataSource() {
return new RoutingDataSource() {{
setDefaultTargetDataSource(masterDataSource());
setTargetDataSources(new HashMap<Object, Object>() {{
put(DataSourceType.MASTER, masterDataSource());
put(DataSourceType.SLAVE, slaveDataSource());
}});
}};
}
@Bean
@Primary
public LazyConnectionDataSourceProxy lazyConnectionDataSourceProxy() {
return new LazyConnectionDataSourceProxy(routeDataSource());
}
}
/**
* @Author anyang
* @CreateTime 2018/3/23
* @Des 数据源获取,设置
*/
public class DataSourceContextHolder {
private static final ThreadLocal<DataSourceType> contextHolder = new ThreadLocal<DataSourceType>();
public static void setDataSourceType(DataSourceType dataSourceType) {
if(dataSourceType == null){
throw new NullPointerException();
}
contextHolder.set(dataSourceType);
}
public static DataSourceType getDataSourceType() {
return contextHolder.get();
}
public static void clearDataSourceType() {
contextHolder.remove();
}
}
/**
* @Author anyang
* @CreateTime 2018/3/23
* @Des
*/
public enum DataSourceType {
MASTER,
SLAVE
}
/**
* @Author anyang
* @CreateTime 2018/3/23
* @Des 切点处理主从切换
*/
@Slf4j
@Aspect
@Configuration
public class DBConnectionAOP {
private final String[] QUERY_PREFIX = {"find"};
// || execution(* com.anyangdp..*.*(..))
@Pointcut("execution(* com.cy.dao.*.*(..))")
public void daoAspect() {
}
@Before("daoAspect()")
public void switchDataSource(JoinPoint point) {
Boolean isQueryMethod = isQueryMethod(point.getSignature().getName());
if (isQueryMethod) {
DataSourceContextHolder.setDataSourceType(DataSourceType.SLAVE);
log.info("Switch DataSource to [{}] in Method [{}]",
DataSourceContextHolder.getDataSourceType(), point.getSignature());
} else {
DataSourceContextHolder.setDataSourceType(DataSourceType.MASTER);
}
}
private Boolean isQueryMethod(String methodName) {
for (String prefix : QUERY_PREFIX) {
if (methodName.startsWith(prefix)) {
return true;
}
}
return false;
}
}
/**
* @Author anyang
* @CreateTime 2018/3/23
* @Des spring jdbc对于多数据源的处理,重写抽象接口
*/
public class RoutingDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
if(DataSourceContextHolder.getDataSourceType() == DataSourceType.MASTER){
return DataSourceType.MASTER;
}
return DataSourceType.SLAVE;
}
}
@SpringBootApplication
@EnableAutoConfiguration(exclude = DataSourceAutoConfiguration.class)###必须添加,禁用springboot自动注入datasource
public class Application{
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}