多数据源切换
多数据源框架功能介绍 多数据源框架官方文档: dynamic-datasource文档
简介
dynamic-datasource-spring-boot-starter 是一个基于springboot的快速集成多数据源的启动器。
其支持 Jdk 1.7+, SpringBoot 1.5.x 2.x.x 3.x.x。
JPA用户不建议使用,JPA自带事务,无法连续切库。
特性
支持 数据源分组 ,适用于多种场景 纯粹多库 读写分离 一主多从 混合模式。
支持数据库敏感配置信息 加密(可自定义) ENC()。
支持每个数据库独立初始化表结构schema和数据库database。
支持无数据源启动,支持懒加载数据源(需要的时候再创建连接)。
支持 自定义注解 ,需继承DS(3.2.0+)。
提供并简化对Druid,HikariCp,BeeCp,Dbcp2的快速集成。
提供对Mybatis-Plus,Quartz,ShardingJdbc,P6sy,Jndi等组件的集成方案。
提供 自定义数据源来源 方案(如全从数据库加载)。
提供项目启动后 动态增加移除数据源 方案。
提供Mybatis环境下的 纯读写分离 方案。
提供使用 spel动态参数 解析数据源方案。内置spel,session,header,支持自定义。
支持 多层数据源嵌套切换 。(ServiceA >>> ServiceB >>> ServiceC)。
提供 基于seata的分布式事务方案 。
提供 本地多数据源事务方案。
切换数据源
使用 @DS 切换数据源
注解 | 结果 |
---|---|
没有@DS | 默认数据源 |
@DS("dsName") | dsName可以为组名也可以为具体某个库的名称 |
@Service
@DS("slave")
public class UserServiceImpl implements UserService {
@Autowired
private JdbcTemplate jdbcTemplate;
public List selectAll() {
return jdbcTemplate.queryForList("select * from user");
}
@Override
@DS("slave_1")
public List selectByCondition() {
return jdbcTemplate.queryForList("select * from user where age >10");
}
}
配置数据库
常见问题
问:DS放在哪里合适? DS作为切换数据源核心注解,我应该把他注解在哪里合适?这其实是初次接触多数据源的人常问的问题。 这其实没有一定的要求,只是有一些经验之谈。
首先开发者要了解的基础知识是,DS注解是基于AOP的原理实现的,aop的常见失效场景应清楚。 比如内部调用失效,shiro代理失效。 具体见切换数据源失败。
作者通常建议DS放在serviceImpl的方法上,如事务注解一样。
注解在Controller的方法上或类上 并不是不可以,作者并不建议的原因主要是controller主要作用是参数的检验等一些基础逻辑的处理,这部分操作常常并不涉及数据库。
注解在service的实现类的方法或类上 这是作者建议的方式,service主要是对业务的处理, 在复杂的场景涉及连续切换不同的数据库。 如果你的方法有通用性,其他service也会调用你的方法。 这样别人就不用重复处理切换数据源。
注解在mapper上 通常如果你某个Mapper对应的表只在确定的一个库,也是可以的。 但是建议只注解在Mapper的类上。
接口放行
配置文件放行
- 将需要放行的接口添加到下面即可
- 具体的代码实现
注解放行
建议使用 @SaIgnore 忽略注解
@SaIgnore
支持在类或方法上放行 注意: 动态路径会解析成通配符 请设计好接口路径避免问题
例如: /get/{userId} 会解析成 /get/*
- @Salgnore 修饰方法时代表这个方法可以被游客访问,修饰类时代表这个类中的所有接口都可以游客访问。
- @Salgnore 具有最高优先级,当 @Salgnore 和其它鉴权注解一起出现时,其它鉴权注解都将被忽略。
非数据库字段
- MybatisPlus 的注解
@TableField(exist = false)
- 此功能主要发生在,实体类的属性,对应的在数据库没有此此字段,需要增加一个注解解决
字典翻译
- 此功能主要是将一个属性由数据的值翻译成字典的名称
- 例如字典中有一个性别字段:
SYS_SEX
(0:保密 1:男2:女) - Vo的实体类对应的字段添加
@Dict("SYS_SEX")
- 添加前
{
"sex":"1"
}
- 添加后
{
"sex":"男"
}
数据脱敏
系统使用 Jackson 序列化策略 对标注了 Sensitive 注解的属性进行脱敏处理
- 实体类添加一下注解
// 手机号
@SensitivityEncrypt(type = SensitivityTypeEnum.PHONE)
private String phoneNumber;
- 其他脱敏类型请看
SensitivityTypeEnum.java
枚举类
获取请求IP
在好多的业务场景,我们需要记录请求者的访问真实IP,或者知道哪个区域的这些信息,特此封装了一个简单的工具类
/**
* 请求
*/
@GetMapping("/request")
@SaIgnore
public String request(HttpServletRequest request){
// 获取真实的访问IP(需要真实的外网请求,本地无效)
String ip = IPUtil.getIp(request);
log.info("ip:{}",ip);
// 219.145.7.79
// 依据 ip2region 解析IP获得物理位置
String cityInfo = AddressUtil.getCityInfo(ip);
log.info("cityInfo:{}",cityInfo);
//中国|陕西省|西安市|电信
return "ok";
}