SpringBoot配置多数据源

SpringBoot配置多数据源

工具: spring tool suite

整体架构为:

 

  1. 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.hrf</groupId>

         <artifactId>springboot_2-1</artifactId>

         <version>0.0.1-SNAPSHOT</version>

         <packaging>jar</packaging>


         <name>spring-boot-5-2</name>

         <description>Demo project for Spring Boot</description>


         <parent>

                   <groupId>org.springframework.boot</groupId>

                   <artifactId>spring-boot-starter-parent</artifactId>

                   <version>1.5.15.RELEASE</version>

                   <relativePath/> <!-- lookup parent from repository -->

         </parent>


         <properties>

                   <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

                   <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

                   <java.version>1.8</java.version>

         </properties>


         <dependencies>

         <!--Spring data JPA依赖  -->

                   <dependency>

                            <groupId>org.springframework.boot</groupId>

                            <artifactId>spring-boot-starter-data-jpa</artifactId>

                   </dependency>

                   <dependency>

                            <groupId>org.springframework.boot</groupId>

                            <artifactId>spring-boot-starter-web</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>

                   </dependency>

                   <!-- mysql驱动 -->

                   <dependency>

                       <groupId>mysql</groupId>

                       <artifactId>mysql-connector-java</artifactId>

                   </dependency>

         </dependencies>


         <build>

                   <plugins>

                            <plugin>

                                     <groupId>org.springframework.boot</groupId>

                                     <artifactId>spring-boot-maven-plugin</artifactId>

                            </plugin>

                   </plugins>

         </build>



</project>

(2)

application.properties

# 主数据源

spring.datasource.driver-class-name=com.mysql.jdbc.Driver

spring.datasource.url=jdbc:mysql://localhost:3306/springbootdb

spring.datasource.username=root

spring.datasource.password=


custom.datasource.names=ds1,ds2

custom.datasource.ds1.driver-class-name=com.mysql.jdbc.Driver

custom.datasource.ds1.url=jdbc:mysql://localhost:3306/springbootdb

custom.datasource.ds1.username=root

custom.datasource.ds1.password=


custom.datasource.ds2.driver-class-name=com.mysql.jdbc.Driver

custom.datasource.ds2.url=jdbc:mysql://localhost:3306/springbootdb

custom.datasource.ds2.username=root

custom.datasource.ds2.password=

 

 

(3)

Multipart.java


 

package com.hrf;

import java.util.HashMap; 

import java.util.Map; 

import java.util.Map.Entry; 

 

import javax.sql.DataSource; 

 

import org.springframework.beans.BeansException; 

import org.springframework.beans.MutablePropertyValues; 

import org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefinition; 

import org.springframework.beans.factory.config.BeanDefinition; 

import org.springframework.beans.factory.config.BeanDefinitionHolder; 

import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; 

import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; 

import org.springframework.beans.factory.support.BeanDefinitionRegistry; 

import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; 

import org.springframework.beans.factory.support.BeanNameGenerator; 

import org.springframework.boot.bind.RelaxedPropertyResolver; 

import org.springframework.context.EnvironmentAware; 

import org.springframework.context.annotation.AnnotationBeanNameGenerator; 

import org.springframework.context.annotation.AnnotationConfigUtils; 

import org.springframework.context.annotation.AnnotationScopeMetadataResolver; 

import org.springframework.context.annotation.Configuration; 

import org.springframework.context.annotation.ScopeMetadata; 

import org.springframework.context.annotation.ScopeMetadataResolver; 

import org.springframework.core.env.Environment; 

 

/** 

 *  

 * 动态创建多数据源注册到Spring中 接口:BeanDefinitionRegistryPostProcessor主要是注入bean 

 *  

 * 接口:接口 EnvironmentAware 重写方法 setEnvironment 

 * 可以在工程启动时,获取到系统环境变量和application配置文件中的变量。 

 *  

 * 方法的执行顺序是: setEnvironment()-->postProcessBeanDefinitionRegistry() --> 

 * postProcessBeanFactory() 

 *  

 * @author Administrator 

 * 

 */ 

@Configuration 

public class Multipart 

        implements BeanDefinitionRegistryPostProcessor, EnvironmentAware { 

 

    // 作用域对象. 

    private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver(); 

    // bean名称生成器. 

    private BeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator(); 

    // 如配置文件中未指定数据源类型,使用该默认值 

    private static final Object DATASOURCE_TYPE_DEFAULT = "org.apache.tomcat.jdbc.pool.DataSource"; 

    // 存放DataSource配置的集合; 

    private Map<String, Map<String, Object>> dataSourceMap = new HashMap<String, Map<String, Object>>(); 

 

    @Override 

    public void setEnvironment(Environment environment) { 

        System.out.println("MultipleDataSourceBeanDefinitionRegistryPostProcessor.setEnvironment()"); 

        /* 

         * 获取application.properties配置的多数据源配置,添加到map中, 

         * 之后在postProcessBeanDefinitionRegistry进行注册。 

         */ 

 

        // 获取到前缀是"custom.datasource." 的属性列表值. 

        RelaxedPropertyResolver propertyResolver = new RelaxedPropertyResolver(environment, "custom.datasource."); 

 

        // 获取到所有数据源的名称. 

        String dsPrefixs = propertyResolver.getProperty("names"); 

        String[] dsPrefixsArr = dsPrefixs.split(","); 

        for (String dsPrefix : dsPrefixsArr) { 

            /* 

             * 获取到子属性,对应一个map; 也就是这个map的key就是 

             * 

             * type、driver-class-name等; 

             * 

             */ 

            Map<String, Object> dsMap = propertyResolver.getSubProperties(dsPrefix + "."); 

            // 存放到一个map集合中,之后在注入进行使用. 

            dataSourceMap.put(dsPrefix, dsMap); 

 

        } 

 

    } 

 

    @Override 

    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { 

 

        // 设置为主数据源; 

        beanFactory.getBeanDefinition("dataSource").setPrimary(true); 

 

        if (!dataSourceMap.isEmpty()) { 

            // 不为空的时候. 

            BeanDefinition bd = null; 

            Map<String, Object> dsMap = null; 

            MutablePropertyValues mpv = null; 

            for (Entry<String, Map<String, Object>> entry : dataSourceMap.entrySet()) { 

                bd = beanFactory.getBeanDefinition(entry.getKey()); 

                mpv = bd.getPropertyValues(); 

                dsMap = entry.getValue(); 

                mpv.addPropertyValue("driverClassName", dsMap.get("driverClassName")); 

                mpv.addPropertyValue("url", dsMap.get("url")); 

                mpv.addPropertyValue("username", dsMap.get("username")); 

                mpv.addPropertyValue("password", dsMap.get("password")); 

            } 

        } 

 

    } 

 

    @SuppressWarnings("unchecked") 

    @Override 

    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { 

        System.out.println("MultipleDataSourceBeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry()"); 

        try { 

            if (!dataSourceMap.isEmpty()) { 

 

                // 不为空的时候,进行注册bean. 

                for (Entry<String, Map<String, Object>> entry : dataSourceMap.entrySet()) { 

                    Object type = entry.getValue().get("type");// 获取数据源类型,没有设置为默认的数据源. 

                    if (type == null) { 

                        type = DATASOURCE_TYPE_DEFAULT; 

                    } 

                    registerBean(registry, entry.getKey(), 

                            (Class<? extends DataSource>) Class.forName(type.toString())); 

                } 

            } 

        } catch (ClassNotFoundException e) { 

            // 异常捕捉. 

            e.printStackTrace(); 

        } 

    } 

 

    /** 

     * 注册Bean到Spring 

     *  

     * @param registry 

     * @param name 

     * @param beanClass 

     */ 

    private void registerBean(BeanDefinitionRegistry registry, String name, Class<?> beanClass) { 

 

        AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass); 

 

        // 单例还是原型等等...作用域对象. 

        ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd); 

        abd.setScope(scopeMetadata.getScopeName()); 

        // 可以自动生成name 

        String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, registry)); 

  

        AnnotationConfigUtils.processCommonDefinitionAnnotations(abd); 

 

        BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName); 

        BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry); 

    } 

 

}

(4)

TestController.java


 

package com.hrf;

import java.sql.ResultSet; 

import java.sql.SQLException; 

 

import javax.sql.DataSource; 

 

import org.springframework.beans.factory.annotation.Autowired; 

import org.springframework.beans.factory.annotation.Qualifier; 

import org.springframework.jdbc.core.JdbcTemplate; 

import org.springframework.jdbc.core.RowMapper; 

import org.springframework.web.bind.annotation.RequestMapping; 

import org.springframework.web.bind.annotation.RestController; 

 

@RestController 

public class TestController { 

    // 没有指定为主数据源. 

    @Autowired 

    private DataSource dataSource; 

 

    @Autowired 

    @Qualifier("ds1") 

    private DataSource dataSource1; 

 

    @Autowired 

    @Qualifier("ds2") 

    private DataSource dataSource2; 

 

    private JdbcTemplate jdbcTemplate; 

 

    @Autowired 

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { 

        System.out.println("TestController.setJdbcTemplate()"); 

        jdbcTemplate.setDataSource(dataSource1);// 设置dataSource 

        this.jdbcTemplate = jdbcTemplate; 

    } 

 

    @RequestMapping("/get") 

    public String get() { 

        // 观察控制台的打印信息. 

        System.out.println(dataSource); 

        return "ok"; 

    } 

 

    @RequestMapping("/get1") 

    public String get1() { 

        // 观察控制台的打印信息. 

        System.out.println(dataSource1); 

        return "ok.1"; 

    } 

 

    @RequestMapping("/get2") 

    public String get2() { 

        // 观察控制台的打印信息. 

        System.out.println(dataSource2); 

        return "ok.2"; 

    } 

 

    @RequestMapping("/get3") 

    public String get3() { 

        // 观察控制台的打印信息. 

        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource1); 

        System.out.println(jdbcTemplate.getDataSource()); 

        System.out.println(jdbcTemplate); 

 

        /* 

         * Demo1只在test1中存在,test并没有此数据库; 需要自己自己进行复制,不然会报错:Table 'test1.demo1' 

         * doesn't exist 

         */ 

        String sql = "select * from user_info"; 

        jdbcTemplate.query(sql, new RowMapper<String>() { 

 

            @Override 

            public String mapRow(ResultSet rs, int rowNum) throws SQLException { 

                System.out.println(rs.getLong("uid") + "---" + rs.getString("name")); 

                return ""; 

            } 

 

        }); 

 

        return "ok.3"; 

    } 

 

    @RequestMapping("/get4") 

    public String get4() { 

        // 观察控制台的打印信息. 

        System.out.println(jdbcTemplate.getDataSource()); 

        System.out.println(jdbcTemplate); 

 

        /* 

         * Demo1只在test1中存在,test并没有此数据库; 需要自己自己进行复制,不然会报错:Table 'test1.demo1' 

         * doesn't exist 

         */ 

        String sql = "select *from user_info"; 

        jdbcTemplate.query(sql, new RowMapper<String>() { 

 

            @Override 

            public String mapRow(ResultSet rs, int rowNum) throws SQLException { 

                System.out.println(rs.getLong("uid") + "---" + rs.getString("name")); 

                return ""; 

            } 

 

        }); 

 

        return "ok.4"; 

    } 

} 

(5)

SpringBoot52Application.java

package com.hrf;


import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;


@SpringBootApplication

public class SpringBoot52Application {


         public static void main(String[] args) {

                   SpringApplication.run(SpringBoot52Application.class, args);

         }

}

 

让我们来体验一把:

找到SpringBoot52Application.java文件 ——》右击Run As  JavaApplication——》浏览器访问: http://localhost:8080/get

结果为:ok

欢迎关注博客:

https://blog.csdn.net/h_r_f

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值