租户端
引言
租户端是指圣钰SaaS的租户端,是所有租户共用的一个共享端。
- 每个租户有自己独立的rbac用户、角色、部门等体系
- 每个租户都可以接入统一的短信、文件管理等基础服务
- 统一的插件应用市场使用
本文档指在告诉用户如何在租户端开发自己想要的功能以及相关注意事项
一、数据库业务表创建
1、租户端的表名的前缀开头没有特殊要求,租户端会默认根据租户idtenant_id进行隔离操作(假定这个表有租户id的前提)。
注意点:
- 主键id请以
bigint NOT NULL AUTO_INCREMENT COMMENT '用户ID'格式来书写,其中bigint对应后端Java的Long类型 - 如下统一字段被创建。
sql
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',2、如下配置决定了哪些表或接口会进行租户id进行隔离操作
md
├─shengyu-server
| ├─src
| | ├─main
| | | ├─resources
| | | | └application.yaml其中application.yaml文件如下地方调整。添加上你想要的前缀格式或表名,添加后的才不会隔离,否则租户端默认隔离
md
tenant: # 多租户相关配置项
#忽略多租户的表
ignore-tables:
- system_saas_user
#忽略多租户表的前缀
ignore-tables-prefix:
- platform
- tenant
- infra二、业务代码处理
1、首先第一步得清晰的认识你想要开发在哪个模块
├─shengyu-module-system #租户端模块
| ├─shengyu-module-system-biz #租户端业务子模块
| | ├─src
| | | ├─main
| | | | ├─java
| | | | | ├─com
| | | | | | ├─shengyu
| | | | | | | ├─module
| | | | | | | | ├─system
| | | | | | | | | ├─util #工具包
| | | | | | | | | ├─service #业务接口与实现
| | | | | | | | | ├─job #定时任务
| | | | | | | | | ├─framework #核心配置
| | | | | | | | | ├─dal #实体类
| | | | | | | | | ├─convert #转换模块
| | | | | | | | | ├─controller #控制器
| | | | | | | | | | ├─app #app端
| | | | | | | | | | ├─admin #web端
| | | | | | | | | ├─api #对外api接口实现
| ├─shengyu-module-system-api #租户端对外api2、首先开发接口总体分为几个步骤
orm数据库持久层
参考平台端的orm数据库持久层开发模式-> orm数据库持久层
控制器层
java
package com.shengyu.module.system.controller.admin.user;
import cn.hutool.core.collection.CollUtil;
import com.shengyu.framework.common.enums.CommonStatusEnum;
import com.shengyu.framework.common.pojo.CommonResult;
import com.shengyu.framework.common.pojo.PageParam;
import com.shengyu.framework.common.pojo.PageResult;
import com.shengyu.framework.common.util.object.BeanUtils;
import com.shengyu.framework.common.util.validation.ValidGroup;
import com.shengyu.framework.excel.core.util.ExcelUtils;
import com.shengyu.framework.operatelog.core.annotations.OperateLog;
import com.shengyu.module.system.controller.admin.user.vo.user.*;
import com.shengyu.module.system.convert.user.UserConvert;
import com.shengyu.module.system.dal.dataobject.dept.DeptDO;
import com.shengyu.module.system.dal.dataobject.user.AdminUserDO;
import com.shengyu.framework.common.enums.common.SexEnum;
import com.shengyu.module.system.service.dept.DeptService;
import com.shengyu.module.system.service.user.AdminUserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import static com.shengyu.framework.common.pojo.CommonResult.success;
import static com.shengyu.framework.common.util.collection.CollectionUtils.convertList;
import static com.shengyu.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
@Tag(name = "管理后台 - 用户")
@RestController
@RequestMapping("/system/user")
@Validated
public class UserController {
@Resource
private AdminUserService userService;
@Resource
private DeptService deptService;
@PostMapping("/create")
@Operation(summary = "新增用户")
@PreAuthorize("@ss.hasPermission('system:user:create')")
public CommonResult<Long> createUser(@Valid @RequestBody UserSaveReqVO reqVO) {
Long id = userService.createUser(reqVO);
return success(id);
}
@PutMapping("update")
@Operation(summary = "修改用户")
@PreAuthorize("@ss.hasPermission('system:user:update')")
public CommonResult<Boolean> updateUser(@Valid @RequestBody UserUpdateReqVO reqVO) {
userService.updateUser(reqVO);
return success(true);
}
}注意点
@PreAuthorize("@ss.hasPermission('system:user:create')")是属于租户端的接口权限注解,根据ss这个标识符来确定是属于租户端的。开发者 将这个已经封装在了底层- 其他注意事项参考平台端的 -> 注意点
业务实现层service
参考平台端的业务实现层service开发模式-> 业务实现层service
三、数据权限 Configuration
java
package com.shengyu.module.system.framework.datapermission.config;
import com.shengyu.module.system.dal.dataobject.dept.DeptDO;
import com.shengyu.module.system.dal.dataobject.user.AdminUserDO;
import com.shengyu.framework.datapermission.core.rule.dept.DeptDataPermissionRuleCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* system 模块的数据权限 Configuration
*
* @author 圣钰科技
*/
@Configuration(proxyBeanMethods = false)
public class DataPermissionConfiguration {
@Bean
public DeptDataPermissionRuleCustomizer sysDeptDataPermissionRuleCustomizer() {
return rule -> {
// dept
rule.addDeptColumn(AdminUserDO.class);
rule.addDeptColumn(DeptDO.class, "id");
// user
rule.addUserColumn(AdminUserDO.class, "id");
};
}
}1、数据权限配置在com.shengyu.module.system.framework.datapermission.config下面的DataPermissionConfiguration配置类。 如上图所示增加了部门级别的数据权限过滤,用户级别的数据权限过滤