【20211127】Spring Boot 手动创建多数据源

Source

时间:2021年11月27日

作者:小蒋聊技术

大家好,欢迎来到小蒋聊技术。小蒋准备和大家一起聊聊技术的那些事。

仅仅看标题,其实这个标题其实并没有什么吸引力,不就是多数据源嘛。

不过,在实际的研发工作中,多数据源却是一个高频需求,必备的一个技能点。小蒋今天就从自己的一个案例中,挑出一个和大家一起来看看。

手动创建jdbcTemplate多数据源

  • 业务场景:

老工程再次添加新需求,需要读取另外的一个数据库。

详细说明:有些工程已经稳定运行很久,突然接到新需求,需要升级。例如,从外部A数据库中获取数据。处理后,再保存到本地B数据库中。

这种老工程再次开发的场景,一般来说是小修、小补、小升级。但对于老工程,因为开发时间比较久,但工程已经经过多次维护和时间的检验,已经进入稳定运行状态。

对于这样的场景,如果工程中的数据源(DataSource)是全局性的,千万要注意,可别小升级带来大麻烦。

如果场景相似,小蒋个人的建议是:尽量“多新增,少修改。能不改,就别改”。

  • 解决方案:

“手动新建数据源,尽量别影响原始的数据源”。

在Spring Boot中,jdbcTemplate、MyBatis、JPA这三种实现都可以配置多数据源。

其中,MyBatis和JPA是两种主流的实现方式。所以,小蒋今天就准备和大家一起通过“手动”新建jdbcTemplate这种实现方式,一起体验一下“多新增,少修改。能不改,就别改” 这个策略。

  • 方案说明:

有些老工程已经开发很久了,当时的工程设计资料可能已经不全了。咱先不聊开发人员是否都在职,就算全部都在职。但是,别小瞧“时间的威力”,研发人员能剩下的记忆也非常有限。这个时候,去修改一个全局的DataSource,其风险是非常大的。所以,如果是“小修、小补、小升级”,这个时候“多新增,少修改。能不改,就别改”这个策略可能更合适。

  • 示例:

        1.选择Spring Boot版本:

(咱们的“业务场景”是一个老工程,小蒋选择Spring Boot 1.5.6.RELEASE 这个版本)

<parent>  
        <groupId>org.springframework.boot</groupId>  
	    <artifactId>spring-boot-starter-parent</artifactId>  
	    <version>1.5.6.RELEASE</version>  
	    <relativePath/> <!-- lookup parent from repository -->  
</parent>  

        2.添加Maven的依赖:

<dependency>  
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-web</artifactId>  
</dependency>  
  
<dependency>  
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-tomcat</artifactId>  
    <scope>provided</scope>  
</dependency>  
  
<!--druid依赖-->  
<dependency>  
    <groupId>com.alibaba</groupId>  
    <artifactId>druid-spring-boot-starter</artifactId>  
    <version>1.1.10</version>  
</dependency>  
  
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->  
<dependency>  
    <groupId>mysql</groupId>  
    <artifactId>mysql-connector-java</artifactId>  
    <version>5.1.49</version>  
    <scope>runtime</scope>  
</dependency>  
  
<dependency>  
    <groupId>org.springframework</groupId>  
    <artifactId>spring-jdbc</artifactId>  
    <version>4.3.8.RELEASE</version>  
</dependency>  

注意:数据库连接池Druid依赖,小蒋选择了druid-spring-boot-starter。优势在于,它是用于帮助使用者在Spring Boot项目中轻松集成Druid数据库连接池和监控的。druid-spring-boot-starter项目地址

        3.配置数据源:

在application.properties文件中配置“两个”,“”的数据源。

注意,这里配置的新数据源”和老项目里原来“jpa的数据源”,配置的key是不同的。

spring.datasource.one.url=jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf-8  
spring.datasource.one.username=root  
spring.datasource.one.password=12345678  
spring.datasource.one.type=com.alibaba.druid.pool.DruidDataSource  
  
spring.datasource.two.url=jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=utf-8  
spring.datasource.two.username=root  
spring.datasource.two.password=12345678  
spring.datasource.two.type=com.alibaba.druid.pool.DruidDataSource  

        4.新增DataSourceConfig类:

在application.properties配置文件中,我们对数据源做了区分“one”和“tow”。KEY的设置不符合spring boot自动加载的规则,所以需要DataSourceConfig类,我们手动加载。

@Configuration  
public class DataSourceConfig {  
  
    @Bean  
    //@Primary  这个注解是设置默认数据源,老项目中原来的数据源应该是默认的。
    @ConfigurationProperties(prefix = "spring.datasource.one")  
    DataSource dsOne() {  
        return DruidDataSourceBuilder.create().build();  
    }  
  
  
    @Bean  
    @ConfigurationProperties(prefix = "spring.datasource.two")  
    DataSource dsTwo() {  
        return DruidDataSourceBuilder.create().build();  
    }  
}

@ConfigurationProperties是Spring Boot提供的类型安全的属性绑定,通过读取配置文件(例如:application.properties)中的前缀(例如:spring.datasource.one)属性去创建数据源,根据我们的配置我们将会有两个不同的数据源。

        5.新增JdbcTemplateConfig类:

接下来我们再通过JdbcTemplateConfig类根据不同的数据源,去创建不同的JdbcTemplate实例

@Configuration  
public class JdbcTemplateConfig {  
  
    @Bean  
    JdbcTemplate jdbcTemplateOne(@Qualifier("dsOne") DataSource dsOne) {  
        return new JdbcTemplate(dsOne);  
    }  
  
    @Bean  
    JdbcTemplate jdbcTemplateTwo(@Qualifier("dsTwo") DataSource dsTwo) {  
        return new JdbcTemplate(dsTwo);  
    }  
}  

@Qualifier注解,表示按照名称查询。也就是就根据不同的数据源,创建了不同的JdbcTemplate实例。

        6.功能验证

通过Controller注入两个不同的JdbcTemplate,这两个JdbcTemplate对应了不同的数据源。

@RestController  
public class HelloController {  
    @Autowired  
    @Qualifier("jdbcTemplateOne")  
    JdbcTemplate jdbcTemplateOne;  
    @Resource(name = "jdbcTemplateTwo")  
    JdbcTemplate jdbcTemplateTwo;  
  
    @GetMapping("/test1")  
    public Integer getTest1() {  
        Integer count = jdbcTemplateOne.queryForObject("SELECT count(*) FROM user",Integer.class);  
        return count;  
    }  
    @GetMapping("/test2")  
    public Integer getTest2() {  
        Integer count = jdbcTemplateTwo.queryForObject("SELECT count(*) FROM fruit", Integer.class);  
        return count;  
    }  

小蒋解释一下注入方式:

  1. 使用JDK提供的@Resource注解,通过byName方式注入。
  2. 使用Spring提供的@Autowrired注解,配合@Qualifier注解,两者联合方式注入。

(这两种注入方式本质上都是ByName,区别无非就是使用JDK提供的,还是使用Spring提供的而已)

测试地址:

  1. http://localhost:8080/test1
  2. http://localhost:8080/test2

源代码地址GitHub - loveflywei/study-mulitple-datasource

老/旧系统升级策略

如果你现在是一名工程师,将来想要成为一名架构师。或者你已经是一名架构师了,还想再进一步提升。接下来,小蒋准备为大家分享一些自己工作中的心得和体会。

在大部分互联网公司里,运行的工程和系统,用“不计其数”来形容一点都不算夸张。有无数的工程和系统支撑着公司日常的业务正常运营。

为了满足业务上的各种需求变动,“老/旧系统的升级或改造”是在正常不过的事了。

但是,每面对这种场景,小蒋我仍然是“嘴唇发干、头皮发麻、脸色煞白、胸闷气短、后背发凉、满头大汗”。

小蒋我没病,但是我紧张。面对“老/旧系统升级或改造”的你是不是也有这样相同的经历呢?!

“老/旧系统升级或改造”不求额外有多少性能/功能的提升,但求正常表现。结果因为老/旧系统开发时间久远研发人员流失设计资料不足系统中相互依赖的各种关系,稍微改动,就全是错误。结果一紧张什么“策略”都忘了,只求妈妈带我回家。

关键时刻“紧张”,影响深远,难以估量。

“紧张”人人有,一旦出现,难以消除,只能缓解。有一种说法是,紧张来源于准备不充分加急功近利。

公式:不充分的程度 急功近利的程度 = 紧张程度

解决方案:

通过这个公式,我们可以洞悉紧张的本质,那就是未知的纰漏和风险。之所以会紧张,就是因为“未知感强烈”,再加上“控制感不足”。

也就是说对于“老/旧系统升级或改造”,一般紧张的原因就是:“我对该系统都不知道是什么、而且升级/改造有没有麻烦、有多大麻烦,我都没办法控制”!

小蒋个人建议,对于不熟悉的“老/旧系统升级或改造”,最开始尽量“小修、小补、小升级”。通过这个策略,充分了解“老/旧系统”,减少“不充分程度”。

多使用“多新增,少修改。能不改,就别改”策略,通过这个策略减少“急功近利程度”。

总结:

通过这个道理,我们自己可以举一反三,找到消除紧张的技巧。多读书,充分了解专业知识,减少盲目的开发,增加确定性。开发前要做解决方案设计,方案要落地与纸上。

年龄的增长不可怕,可怕的是从未成长!

感谢大家支持小蒋,小蒋希望和大家共同成长,谢谢。

音频地址:

【20211127】Spring Boot 手动创建多数据源icon-default.png?t=LA92https://www.ximalaya.com/keji/51588599/476708716