文章目录
前言:
dynamic-datasource插件是一款动态数据源的轻量级实现,封装成Spring Starter方式引入,
支持Mybatis、MybatisPlus读写分离,支持通过注解动态切换切换数据源。
1:项目结构
1:项目背景
在项目中访问两个数据库,分别打印出来两个数据库的数据信息
2:项目结构
3:项目地址
https://gitee.com/cangyu1024/spring-druid.git
2:导包
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- <exclusions>-->
<!-- <exclusion>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-logging</artifactId>-->
<!-- </exclusion>-->
<!-- </exclusions>-->
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!--这就是苞米豆的dynamic的多数据源配置-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.23</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
主要的包是:苞米豆的dynamic的多数据源配置包
<!--这就是苞米豆的dynamic的多数据源配置-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
3:配置
1:pom.xml配置
spring:
application:
name: spring-druid
#开始配置数据源
datasource:
dynamic:
#指定一个主数据源,primary表示是主数据源也可以认为是默认数据源,如果不加注解DS(“数据源名字”)则会去主数据源中查询
primary: db1
datasource:
#第一个数据源配置
db1:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/db1?characterEncoding=utf8&useSSL=false&autoReconnect=true&serverTimezone=UTC
username: root
password: 6DEPiNLAN3mfjBEX
type: com.alibaba.druid.pool.DruidDataSource
druid:
initial-size: 5 #连接池初始化大小
min-idle: 10 #最小空闲连接数
max-active: 20 #最大连接数
filters: stat,log4j
#第二个数据源配置
db2:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/db2?characterEncoding=utf8&useSSL=false&autoReconnect=true&serverTimezone=UTC
username: root
password: 6DEPiNLAN3mfjBEX
type: com.alibaba.druid.pool.DruidDataSource
druid:
initial-size: 5 #连接池初始化大小
min-idle: 10 #最小空闲连接数
max-active: 20 #最大连接数
filters: stat,log4j
druid:
web-stat-filter:
exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*" #不统计这些请求数据
#开启druid的监控面板
stat-view-servlet:
enabled: true #为true就是开启
login-username: root
login-password: root
# IP白名单 (没有配置或者为空,则允许所有访问)
#allow: 127.0.0.1,192.168.163.1
# IP黑名单 (存在共同时,deny优先于allow)
#deny: 192.168.10.1
#mybatis
mybatis:
#扫描Mapper接口对应的XML文件
mapper-locations:
- classpath*:mapper/*.xml
#使用mybatis.type-aliases-package来指定POJO扫描包来让mybatis自动扫描到自定义的POJO。
type-aliases-package: com.wkl.springdruid.dto
#如果查询语句中某些字段值是null的,则这个字段就无法返回。对于后台数据处理来说,这是一个致命的问题,于是通过修改Mybatis的配置来解决这个问题。返回一个null的值
configuration:
call-setters-on-nulls: true
server:
port: 8080
2:引入log4j.xml日志配置,要不然会报错
网上随便找的就行
<?xml version="1.0" encoding="UTF-8"?>
<configuration status="OFF">
<appenders>
<Console name="Console" target="SYSTEM_OUT">
<!--只接受程序中DEBUG级别的日志进行处理-->
<ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%file:%line] %-5level %logger{35} - %msg %n"/>
</Console>
<!--处理INFO级别的日志,并把该日志放到logs/info.log文件中-->
<RollingFile name="RollingFileInfo" fileName="./logs/info.log"
filePattern="logs/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log.gz">
<Filters>
<ThresholdFilter level="INFO"/>
<ThresholdFilter level="WARN" onMatch="DENY" onMismatch="NEUTRAL"/>
</Filters>
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%file:%line] %-5level %logger{35} - %msg %n"/>
<Policies>
<SizeBasedTriggeringPolicy size="500 MB"/>
<TimeBasedTriggeringPolicy/>
</Policies>
</RollingFile>
<!--处理WARN级别的日志,并把该日志放到logs/warn.log文件中-->
<RollingFile name="RollingFileWarn" fileName="./logs/warn.log"
filePattern="logs/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log.gz">
<Filters>
<ThresholdFilter level="WARN"/>
<ThresholdFilter level="ERROR" onMatch="DENY" onMismatch="NEUTRAL"/>
</Filters>
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%file:%line] %-5level %logger{35} - %msg %n"/>
<Policies>
<SizeBasedTriggeringPolicy size="500 MB"/>
<TimeBasedTriggeringPolicy/>
</Policies>
</RollingFile>
<!--处理error级别的日志,并把该日志放到logs/error.log文件中-->
<RollingFile name="RollingFileError" fileName="./logs/error.log"
filePattern="logs/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log.gz">
<ThresholdFilter level="ERROR"/>
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%file:%line] %-5level %logger{35} - %msg %n"/>
<Policies>
<SizeBasedTriggeringPolicy size="500 MB"/>
<TimeBasedTriggeringPolicy/>
</Policies>
</RollingFile>
<!--druid的日志记录追加器-->
<RollingFile name="druidSqlRollingFile" fileName="./logs/druid-sql.log"
filePattern="logs/$${date:yyyy-MM}/api-%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%file:%line] %-5level %logger{35} - %msg %n"/>
<Policies>
<SizeBasedTriggeringPolicy size="500 MB"/>
<TimeBasedTriggeringPolicy/>
</Policies>
</RollingFile>
</appenders>
<loggers>
<AsyncRoot level="info">
<appender-ref ref="Console"/>
<appender-ref ref="RollingFileInfo"/>
<appender-ref ref="RollingFileWarn"/>
<appender-ref ref="RollingFileError"/>
</AsyncRoot>
<!--记录druid-sql的记录-->
<AsyncLogger name="druid.sql.Statement" level="debug" additivity="false">
<appender-ref ref="druidSqlRollingFile"/>
</AsyncLogger>
</loggers>
</configuration>
4:编码
1:分别在两个库随便建个表
2:创建实体类
package com.wkl.springdruid.dto;
import lombok.Data;
/**
* @author wangkanglu
* @version 1.0
* @description
* @date 2022-10-14 16:11
*/
@Data
public class TestDto {
Integer id;
String name;
}
3:创建dao实现类-指定数据源
说明:用DS注解指明要使用的数据,
dynamic-datasource官方建议把注解添加到service的方法上
如果不写这个注解的话,那么就使用默认数据源
package com.wkl.springdruid.mapper;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.wkl.springdruid.dto.TestDto;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* @author wangkanglu
* @version 1.0
* @description
* @date 2022-10-14 16:12
*/
public interface TestMapper {
@Select("select * from test1")
@DS("db1")
List<TestDto> selectAll1();
@Select("select * from test2")
@DS("db2")
List<TestDto> selectAll2();
@DS("db1")
List<TestDto> selectAll3();
}
4:mybatis配置相关设置
在application.yml中配置xml扫描的路径和对应的其他配置
在主程序中配置扫描Mapper接口类的位置。
5:mybatis的xml相关配置
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wkl.springdruid.mapper.TestMapper">
<select id="selectAll3" resultType="com.wkl.springdruid.dto.TestDto">
select * from test1
</select>
</mapper>
5:测试
1:测试代码
package com.wkl.springdruid;
import com.wkl.springdruid.dto.TestDto;
import com.wkl.springdruid.mapper.TestMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import java.util.List;
@SpringBootTest
class SpringDruidApplicationTests {
@Resource
TestMapper testMapper;
@Test
void contextLoads() {
}
@Test
public void test1(){
List<TestDto> testDtos = testMapper.selectAll1();
System.out.println(testDtos);
}
@Test
public void test2(){
List<TestDto> testDtos = testMapper.selectAll2();
System.out.println(testDtos);
}
@Test
public void test3(){
List<TestDto> testDtos = testMapper.selectAll3();
System.out.println(testDtos);
}
}