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

}

上一篇下一篇

猜你喜欢

热点阅读