做公司网站需要的材料有哪些,wordpress 返回,字体设计在线生成免费,在线网站制作模拟#x1f3b6;前言
学习springboot配置多数据源#xff0c;先回顾一下springboot配置单数据源的方式 SpringBoot配置mybatis-mysql数据源
#x1f520;主从数据源搭建
项目依赖
本次记录多数据源配置主要是通过druid mybatis plus aop的形式实现的#xff0c;mybatis …前言
学习springboot配置多数据源先回顾一下springboot配置单数据源的方式 SpringBoot配置mybatis-mysql数据源
主从数据源搭建
项目依赖
本次记录多数据源配置主要是通过druid mybatis plus aop的形式实现的mybatis plus是一个很方便的数据库操作框架自己也有实现多数据源的jar包这里没有使用她封装的方法主要是学习所以是自行实现了一遍简单的多数据源配置和动态切换数据源。
!-- mybatis-plus多数据源配置jar --
dependencygroupIdcom.baomidou/groupIdartifactIddynamic-datasource-spring-boot-starter/artifactId
/dependency使用到的依赖
dependencies!-- druid数据连接池 --dependencygroupIdcom.alibaba/groupIdartifactIddruid-spring-boot-starter/artifactId/dependency!-- mybatis plus --dependencygroupIdcom.baomidou/groupIdartifactIdmybatis-plus-boot-starter/artifactId/dependency!-- spring-aop --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-aop/artifactId/dependency!-- springboot配置依赖 --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-configuration-processor/artifactIdoptionaltrue/optional/dependency!-- mysql驱动 --dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdscoperuntime/scope/dependency
/dependenciesYml文件配置数据源
这里可以看到数据源配置属性路径并非spring.datasource, 这里主要是想通过学习spring-boot配置文件自动装配, 来获取配置并初始化数据源。
utmost:# 主从数据源配置datasource:dynamic:master:driverClassName: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://192.168.92.10:3306/utmost_01?useUnicodetruecharacterEncodingutf8zeroDateTimeBehaviorconvertToNulluseSSLtrueserverTimezoneGMT%2B8userName: rootpassword: rootslave:enabled: true # 是否启用从数据源driverClassName: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://192.168.92.10:3306/utmost_02?useUnicodetruecharacterEncodingutf8zeroDateTimeBehaviorconvertToNulluseSSLtrueserverTimezoneGMT%2B8userName: rootpassword: rootGetter
Setter
ConfigurationProperties(prefix UtmostDataSourceProperties.PREFIX)
public class UtmostDataSourceProperties {/*** 配置前缀*/public static final String PREFIX utmost.datasource.dynamic;/*** master数据源配置前缀*/public static final String MASTER_PREFIX utmost.datasource.dynamic.master;/*** slave数据源配置前缀*/public static final String SLAVE_PREFIX utmost.datasource.dynamic.slave;/*** 设置默认数据库, 默认master*/public String primary master;/*** 设置启用数据源, 默认true*/public boolean enabled true;/*** 主数据源*/public SingleDataSourceProperty master;/*** 从数据源*/public SingleDataSourceProperty slave;
}Data
Accessors(chain true)
public class SingleDataSourceProperty {/*** JDBC driver*/private String driverClassName;/*** JDBC 数据库地址*/private String url;/*** JDBC 用户名*/private String userName;/*** JDBC 用户密码*/private String password;
}怎么通过UtmostDataSourceProperties类来获取属性, 主要通过ConfigurationProperties注解实现, 前面依赖中引入了spring-boot-configuration-processor依赖, 在使用yml配置数据源时就会出现一定的提示作用。这是因为在打包编译的时候会生成一个spring-configuration-metadata.json文件这里就不赘述了先了解到这是springboot帮助我们生成的作用于提示的文件就可以了。 mybatis-plus配置
# mybatis-plus 配置
mybatis-plus:configuration:# 开启驼峰map-underscore-to-camel-case: true# 关闭一级缓存local-cache-scope: statement# 关闭二级缓存cache-enabled: false# sql xml文件映射路径mapper-locations: classpath*:/mapper/*.xml# MyBaits 别名包扫描路径通过该属性可以给包中的类注册别名type-aliases-package: com.zy.utmost.entity数据源装配
数据源配置类
Slf4j
Configuration
AllArgsConstructor
EnableConfigurationProperties(UtmostDataSourceProperties.class)
ConditionalOnProperty(prefix UtmostDataSourceProperties.PREFIX, name enabled, havingValue true, matchIfMissing true)
public class UtmostDataSourceAutoConfiguration {private final UtmostDataSourceProperties utmostDataSourceProperties;/*** 主数据源(这里配置写的繁琐一点, 可根据个人喜好进行简化.)** return DataSource*/Bean(name masterDataSource)ConfigurationProperties(UtmostDataSourceProperties.MASTER_PREFIX)public DataSource masterDataSource() {SingleDataSourceProperty master utmostDataSourceProperties.master;DruidDataSource druidDataSource new DruidDataSource();druidDataSource.setName(DataSourceConstants.MASTER);druidDataSource.setDriverClassName(master.getDriverClassName());druidDataSource.setUrl(master.getUrl());druidDataSource.setUsername(master.getUserName());druidDataSource.setPassword(master.getPassword());return druidDataSource;}/*** 从 数据源(这里配置写的繁琐一点, 可根据个人喜好进行简化.)** return DataSource*/Bean(name slaveDataSource)ConfigurationProperties(UtmostDataSourceProperties.SLAVE_PREFIX)ConditionalOnProperty(prefix UtmostDataSourceProperties.SLAVE_PREFIX, name enabled, havingValue true)public DataSource slaveDataSource() {SingleDataSourceProperty slave utmostDataSourceProperties.slave;DruidDataSource druidDataSource new DruidDataSource();druidDataSource.setName(DataSourceConstants.SLAVE);druidDataSource.setDriverClassName(slave.getDriverClassName());druidDataSource.setUrl(slave.getUrl());druidDataSource.setUsername(slave.getUserName());druidDataSource.setPassword(slave.getPassword());return druidDataSource;}/*** 动态数据源** return DynamicDataSource*/BeanPrimarypublic DynamicDataSource dynamicDataSource() {MapObject, Object targetMap new HashMap(2);targetMap.put(DataSourceConstants.MASTER, masterDataSource());targetMap.put(DataSourceConstants.SLAVE, slaveDataSource());DynamicDataSource dynamicDataSource new DynamicDataSource(masterDataSource(), targetMap);log.info(动态数据源装配完成...);return dynamicDataSource;}
}动态数据源实现类
通过继承重写AbstractRoutingDataSource 数据源路由来实现数据源动态切换的功能.
public class DynamicDataSource extends AbstractRoutingDataSource {/*** 使用线程切换数据源*/private static ThreadLocalString contextHandler new ThreadLocal();/*** 数据源key集合*/private static ListObject dataSourceKeys new ArrayList();/*** 配置数据源** param defaultDataSource 主数据源* param targetDataSourceMap 其他数据源集合*/public DynamicDataSource(DataSource defaultDataSource, MapObject, Object targetDataSourceMap) {super.setDefaultTargetDataSource(defaultDataSource);super.setTargetDataSources(targetDataSourceMap);super.afterPropertiesSet();// 初始化所有数据源的keyaddAllDataSourceKeys(targetDataSourceMap.keySet());}public static void setDataSourceKeys(String key) {contextHandler.set(key);}public static ThreadLocalString getDataSourceKeys() {return contextHandler;}public static void removeDataSourceKeys() {contextHandler.remove();}public static boolean containsDataSourceKeys(String key) {return dataSourceKeys.contains(key);}public static boolean addAllDataSourceKeys(Collection? extends Object keys) {return dataSourceKeys.addAll(keys);}Overrideprotected Object determineCurrentLookupKey() {return contextHandler.get();}
}数据源切换注解
/*** 注解命名主要是为了好记所以直接使用了DataSource, 在使用时会发现有很* 多类都是以DataSource命名, 使用时需要注意.* author yanzy*/
Target({ElementType.TYPE, ElementType.METHOD})
Retention(RetentionPolicy.RUNTIME)
Documented
public interface DataSource {String value() default ;
}数据源切换实现
/*** 实现注解织入切换数据源** author yanzy* date 2021/6/10 23:38* since v1.0*/
Aspect
Order(-10)
Component
public class DataSourceAspect {private Logger logger LoggerFactory.getLogger(DataSourceAspect.class);/*** - within扫描类注解, annotation扫描方法上注解* 定义切面*/Pointcut(annotation(com.zy.utmost.annotation.DataSource) || within(com.zy.utmost.annotation.DataSource))public void annotationPointCut() {}/*** 前置事件 方法前切换数据源* param point 织入点* param dataSource 注解实例*/Before(annotationPointCut() annotation(dataSource)))public void beforeMethod(JoinPoint point, DataSource dataSource) {switchDataSource(point, dataSource);}/*** 前置事件 类前切换数据源* param point 织入点* param dataSource 注解实例*/Before(annotationPointCut() within(dataSource)))public void beforeClass(JoinPoint point, DataSource dataSource) {switchDataSource(point, dataSource);}private void switchDataSource(JoinPoint point,DataSource dataSource) {String key dataSource.value();if (!DynamicDataSource.containsDataSourceKeys(key)) {logger.debug(数据源切换失败: [{}] - 数据源不存在, 自动使用默认数据源., key);} else {DynamicDataSource.setDataSourceKeys(key);logger.debug(数据源切换成功: [{}] - 已切换至 - [{}] - 数据源., point.getSignature().getName(), key);}}/*** 后置增强 (方法/类执行完毕后将数据源切回默认)** param point 织入点*/After(annotationPointCut())public void after(JoinPoint point) {if (null ! DynamicDataSource.getDataSourceKeys()) {DynamicDataSource.removeDataSourceKeys();logger.debug(数据源切换成功: 切换为主数据源.);}}
}搭建完测试
测试使用的crud类就不附上代码了, 直接使用spring-boot-test来给数据库插入数据, 验证一下数据源是否可以正常切换.
数据库
首先这里使用了两个数据库, 都创建了utmost这个数据库实例并创建有sys_user表.
service实现类(方法增加注解切换数据源)
Service
public class SysUserServiceImpl implements SysUserService {Resourceprivate SysUserMapper sysUserMapper;// 主库插入Overridepublic Integer insertUserMaster(SysUser sysUser) {return sysUserMapper.insert(sysUser);}// 从库插入OverrideDataSource(value DataSourceConstants.SLAVE)public Integer insertUserSlave(SysUser sysUser) {return sysUserMapper.insert(sysUser);}
}测试类
SpringBootTest
public class SysUserTableTest {Autowiredprivate SysUserService sysUserService;Testpublic void insertByMaster() {SysUser sysUser new SysUser();sysUser.setUserName(admin);sysUser.setLoginName(admin);sysUser.setPassword(admin);sysUserService.insertUserMaster(sysUser);}Testpublic void insertBySlave() {SysUser sysUser new SysUser();sysUser.setUserName(admin);sysUser.setLoginName(admin);sysUser.setPassword(admin);sysUserService.insertUserSlave(sysUser);}
}测试主库插入, 不标注注解时, 默认使用主库.
测试从库插入, 调用使用了切换数据源注解得到方法
类标注注解测试
Service
DataSource(value DataSourceConstants.SLAVE)
public class SysUserServiceImpl implements SysUserService {Resourceprivate SysUserMapper sysUserMapper;Overridepublic Integer insertUserMaster(SysUser sysUser) {return sysUserMapper.insert(sysUser);}Overridepublic Integer insertUserSlave(SysUser sysUser) {return sysUserMapper.insert(sysUser);}
}调用insertUserMaster, 验证数据源是否切换成功.
总结
好啦~ 以上主要记录一下自己在学习过程中是如何配置多数据源的(严格来说代码中的写法应该是主从数据源 嘿嘿)。 一般主从数据源主要是为了做读写分离的后面学习总结完读写分离操作后在进行分享记录啦~~