mybatis-mate 数据权限 mybatis-plus团队新作mybatis-mate实现数据权限
如梦技术 人气:0一、主要功能
- 字典绑定
- 字段加密
- 数据脱敏
- 表结构动态维护
- 数据审计记录
- 数据范围(数据权限)
- 数据库分库分表、动态据源、读写分离、数据库健康检查自动切换。
二、使用
2.1 依赖导入
Spring Boot 引入自动依赖注解包
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-mate-starter</artifactId> <version>1.0.8</version> </dependency>
注解(实体分包使用)
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-mate-annotation</artifactId> <version>1.0.8</version> </dependency>
2.2 字典绑定
例如 user_sex 类型 sex 字典结果映射到 sexText 属性
@FieldDict(type = "user_sex", target = "sexText") private Integer sex; private String sexText;
实现 IDataDict 接口提供字典数据源,注入到 Spring 容器即可。
@Component public class DataDict implements IDataDict { /** * 从数据库或缓存中获取 */ private Map<String, String> SEX_MAP = new ConcurrentHashMap<String, String>() {{ put("0", "女"); put("1", "男"); }}; @Override public String getNameByCode(FieldDict fieldDict, String code) { System.err.println("字段类型:" + fieldDict.type() + ",编码:" + code); return SEX_MAP.get(code); } }
2.3 字段加密
属性 @FieldEncrypt 注解即可加密存储,会自动解密查询结果,支持全局配置加密密钥算法,及注解密钥算法,可以实现 IEncryptor 注入自定义算法。
@FieldEncrypt(algorithm = Algorithm.PBEWithMD5AndDES) private String password;
2.4 数据脱敏
属性 @FieldSensitive 注解即可自动按照预设策略对源数据进行脱敏处理,默认 SensitiveType 内置 9 种常用脱敏策略。例如:中文名、银行卡账号、手机号码、固话号码、邮寄地址、电子邮箱、SFZ号码、密码、车牌号 脱敏策略,也可以自定义策略如下:
@FieldSensitive(type = "testStrategy") private String username; @FieldSensitive(type = SensitiveType.mobile) private String mobile;
自定义脱敏策略 testStrategy 添加到默认策略中注入 Spring 容器即可。
@Configuration public class SensitiveStrategyConfig { /** * 注入脱敏策略 */ @Bean public ISensitiveStrategy sensitiveStrategy() { // 自定义 testStrategy 类型脱敏处理 return new SensitiveStrategy().addStrategy("testStrategy", t -> t + "***test***"); } }
2.5 DDL 数据结构自动维护
解决升级表结构初始化,版本发布更新 SQL 维护问题,目前支持 MySql、PostgreSQL。
@Component public class PostgresDdl implements IDdl { /** * 执行 SQL 脚本方式 */ @Override public List<String> getSqlFiles() { return Arrays.asList( // 内置包方式 "db/tag-schema.sql", // 文件绝对路径方式 "D:\\db\\tag-data.sql" ); } }
不仅仅可以固定执行,也可以动态执行!!
ddlScript.run(new StringReader("DELETE FROM user;\n" + "INSERT INTO user (id, username, password, sex, email) VALUES\n" + "(20, 'Duo', '123456', 0, 'Duo@baomidou.com');"));
这样就完了吗??当然没有,它还支持多数据源执行!!!
@Component public class MysqlDdl implements IDdl { @Override public void sharding(Consumer<IDdl> consumer) { // 多数据源指定,主库初始化从库自动同步 String group = "mysql"; ShardingGroupProperty sgp = ShardingKey.getDbGroupProperty(group); if (null != sgp) { // 主库 sgp.getMasterKeys().forEach(key -> { ShardingKey.change(group + key); consumer.accept(this); }); // 从库 sgp.getSlaveKeys().forEach(key -> { ShardingKey.change(group + key); consumer.accept(this); }); } } /** * 执行 SQL 脚本方式 */ @Override public List<String> getSqlFiles() { return Arrays.asList("db/user-mysql.sql"); } }
2.6 动态多数据源主从自由切换
@Sharding 注解支持一句话使数据源不限制随意使用切换,你可以在 mapper 层添加注解,按需求指哪打哪!!
@Mapper @Sharding("mysql") public interface UserMapper extends BaseMapper<User> { @Sharding("postgres") Long selectByUsername(String username); }
你也可以自定义策略统一调兵遣将
@Component public class MyShardingStrategy extends RandomShardingStrategy { /** * 决定切换数据源 key {@link ShardingDatasource} * * @param group 动态数据库组 * @param invocation {@link Invocation} * @param sqlCommandType {@link SqlCommandType} */ @Override public void determineDatasourceKey(String group, Invocation invocation, SqlCommandType sqlCommandType) { // 数据源组 group 自定义选择即可, keys 为数据源组内主从多节点,可随机选择或者自己控制 this.changeDatabaseKey(group, sqlCommandType, keys -> chooseKey(keys, invocation)); } }
可以开启主从策略,当然也是可以开启健康检查!!!
2.7 数据权限
mapper 层添加注解:
// 测试 test 类型数据权限范围,混合分页模式 @DataScope(type = "test", value = { // 关联表 user 别名 u 指定部门字段权限 @DataColumn(alias = "u", name = "department_id"), // 关联表 user 别名 u 指定手机号字段(自己判断处理) @DataColumn(alias = "u", name = "mobile") }) @Select("select u.* from user u") List<User> selectTestList(IPage<User> page, Long id, @Param("name") String username);
模拟业务处理逻辑:
@Bean public IDataScopeProvider dataScopeProvider() { return new AbstractDataScopeProvider() { @Override protected void setWhere(PlainSelect plainSelect, Object[] args, DataScopeProperty dataScopeProperty) { // args 中包含 mapper 方法的请求参数,需要使用可以自行获取 /* // 测试数据权限,最终执行 SQL 语句 SELECT u.* FROM user u WHERE (u.department_id IN ('1', '2', '3', '5')) AND u.mobile LIKE '%1533%' */ if ("test".equals(dataScopeProperty.getType())) { // 业务 test 类型 List<DataColumnProperty> dataColumns = dataScopeProperty.getColumns(); for (DataColumnProperty dataColumn : dataColumns) { if ("department_id".equals(dataColumn.getName())) { // 追加部门字段 IN 条件,也可以是 SQL 语句 Set<String> deptIds = new HashSet<>(); deptIds.add("1"); deptIds.add("2"); deptIds.add("3"); deptIds.add("5"); ItemsList itemsList = new ExpressionList(deptIds.stream().map(StringValue::new).collect(Collectors.toList())); InExpression inExpression = new InExpression(new Column(dataColumn.getAliasDotName()), itemsList); if (null == plainSelect.getWhere()) { // 不存在 where 条件 plainSelect.setWhere(new Parenthesis(inExpression)); } else { // 存在 where 条件 and 处理 plainSelect.setWhere(new AndExpression(plainSelect.getWhere(), inExpression)); } } else if ("mobile".equals(dataColumn.getName())) { // 支持一个自定义条件 LikeExpression likeExpression = new LikeExpression(); likeExpression.setLeftExpression(new Column(dataColumn.getAliasDotName())); likeExpression.setRightExpression(new StringValue("%1533%")); plainSelect.setWhere(new AndExpression(plainSelect.getWhere(), likeExpression)); } } } } }; }
最终执行 SQL 输出:
SELECT u.* FROM user u WHERE (u.department_id IN ('1', '2', '3', '5')) AND u.mobile LIKE '%1533%' LIMIT 1, 10
三、最后
大家好,我是 如梦技术春哥(mica 微服务组件开源作者)笔者使用 mybatis-plus 已有 4 年多(资深老粉),mybatis-plus 帮助我们大大提升了开发效率,统一了企业内代码开发风格,降低维护成本。
如果大家在企业内有 mybatis-mate 使用场景,不妨支持一下。更多 mybatis-mate 使用示例详见:https://gitee.com/baomidou/mybatis-mate-examples
加载全部内容