springboot datajpa 多数据库主从分离代码实现

pom.xml



    4.0.0

    com.springboot
    springboot-muti-dataSource
    1.0-SNAPSHOT


    
        com.anyangdp
        anyangdp-parent
        1.0.0
    

    
        1.8

        
        3.2
        2.18.1
        2.4
        2.8.2
        2.5.1
        4.1.1
    

    

        
            com.anyangdp
            common-jpa-biz
            1.0.0
        

        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.boot
            spring-boot-starter-data-jpa
        

        
            org.springframework.boot
            spring-boot-starter-data-jdbc
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
        
            org.springframework.boot
            spring-boot-devtools
            true
        

        
            org.projectlombok
            lombok
        

        
            mysql
            mysql-connector-java
        

    



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() {{
                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 contextHolder = new ThreadLocal();

    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);
    }

}

你可能感兴趣的:(springboot datajpa 多数据库主从分离代码实现)