初始化代码
This commit is contained in:
216
doc/后端开发文档.md
216
doc/后端开发文档.md
@@ -828,16 +828,224 @@ lyzsys:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Demo 示例模块
|
||||||
|
|
||||||
|
### 模块简介
|
||||||
|
|
||||||
|
**lyzsys-module-demo** 是一个完整的业务模块示例,展示了如何在 Lyzsys 系统中快速创建一个新的业务模块。该模块实现了项目管理的完整 CRUD 功能,包括增删改查和 Excel 导出。
|
||||||
|
|
||||||
|
### 功能特性
|
||||||
|
|
||||||
|
- ✅ 完整的 CRUD 接口(增删改查)
|
||||||
|
- ✅ 分页查询支持
|
||||||
|
- ✅ 批量删除功能
|
||||||
|
- ✅ Excel 导出功能
|
||||||
|
- ✅ 业务字段唯一性校验
|
||||||
|
- ✅ 权限控制
|
||||||
|
- ✅ 前后端完整实现
|
||||||
|
|
||||||
|
### 模块结构
|
||||||
|
|
||||||
|
```
|
||||||
|
lyzsys-module-demo/
|
||||||
|
├── pom.xml # Maven 配置
|
||||||
|
└── src/main/java/cn/iocoder/lyzsys/module/demo/
|
||||||
|
├── controller/admin/project/ # 控制器层
|
||||||
|
│ ├── ProjectController.java # 项目控制器
|
||||||
|
│ └── vo/ # VO 对象
|
||||||
|
│ ├── ProjectPageReqVO.java # 分页查询请求
|
||||||
|
│ ├── ProjectRespVO.java # 响应 VO
|
||||||
|
│ └── ProjectSaveReqVO.java # 保存请求 VO
|
||||||
|
├── service/project/ # 服务层
|
||||||
|
│ ├── ProjectService.java # 服务接口
|
||||||
|
│ └── ProjectServiceImpl.java # 服务实现
|
||||||
|
├── dal/ # 数据访问层
|
||||||
|
│ ├── dataobject/project/ # 数据对象
|
||||||
|
│ │ └── ProjectDO.java # 项目实体类
|
||||||
|
│ └── mysql/project/ # Mapper 接口
|
||||||
|
│ └── ProjectMapper.java # 项目 Mapper
|
||||||
|
└── enums/ # 枚举类
|
||||||
|
└── ErrorCodeConstants.java # 错误码常量
|
||||||
|
```
|
||||||
|
|
||||||
|
### 核心代码示例
|
||||||
|
|
||||||
|
#### 实体类(ProjectDO)
|
||||||
|
|
||||||
|
```java
|
||||||
|
@TableName("demo_project")
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class ProjectDO extends BaseDO {
|
||||||
|
@TableId
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
// 遵循命名规范:第一个单词不能只有一个字母
|
||||||
|
private String projectName; // ✅ 正确(而非 pName)
|
||||||
|
private String projectCode; // ✅ 正确(而非 pCode)
|
||||||
|
private LocalDateTime establishDate; // ✅ 正确(而非 eDate)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Controller 示例
|
||||||
|
|
||||||
|
```java
|
||||||
|
@Tag(name = "管理后台 - 项目管理")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/demo/project")
|
||||||
|
public class ProjectController {
|
||||||
|
|
||||||
|
@PostMapping("/create")
|
||||||
|
@Operation(summary = "创建项目")
|
||||||
|
@PreAuthorize("@ss.hasPermission('demo:project:create')")
|
||||||
|
public CommonResult<Long> createProject(@Valid @RequestBody ProjectSaveReqVO createReqVO) {
|
||||||
|
return success(projectService.createProject(createReqVO));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 其他 CRUD 方法...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 数据库设计
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE TABLE `demo_project` (
|
||||||
|
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '项目ID',
|
||||||
|
`project_name` varchar(100) NOT NULL COMMENT '项目名称',
|
||||||
|
`project_code` varchar(50) NOT NULL COMMENT '项目编号',
|
||||||
|
`establish_date` datetime NULL COMMENT '立项时间',
|
||||||
|
-- 标准字段
|
||||||
|
`creator` varchar(64) DEFAULT '' COMMENT '创建者',
|
||||||
|
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
`updater` varchar(64) DEFAULT '' COMMENT '更新者',
|
||||||
|
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||||
|
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB COMMENT='项目管理表';
|
||||||
|
```
|
||||||
|
|
||||||
|
### 菜单配置
|
||||||
|
|
||||||
|
Demo 模块的菜单结构:
|
||||||
|
|
||||||
|
```
|
||||||
|
项目管理(一级菜单,sort: 1)
|
||||||
|
└── 项目列表(二级菜单,sort: 1)
|
||||||
|
├── 项目查询(demo:project:query)
|
||||||
|
├── 项目新增(demo:project:create)
|
||||||
|
├── 项目修改(demo:project:update)
|
||||||
|
├── 项目删除(demo:project:delete)
|
||||||
|
└── 项目导出(demo:project:export)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 前端实现
|
||||||
|
|
||||||
|
前端代码位置:
|
||||||
|
- API 接口:`src/api/demo/project/index.ts`
|
||||||
|
- 列表页面:`src/views/demo/project/index.vue`
|
||||||
|
- 表单组件:`src/views/demo/project/ProjectForm.vue`
|
||||||
|
|
||||||
|
### 作为参考模板
|
||||||
|
|
||||||
|
Demo 模块可以作为新业务模块开发的参考模板,包含了:
|
||||||
|
|
||||||
|
1. **标准的代码结构** - 遵循项目分层架构
|
||||||
|
2. **完整的业务逻辑** - 包括校验、异常处理等
|
||||||
|
3. **规范的命名方式** - 遵循驼峰命名规范
|
||||||
|
4. **权限控制示例** - 展示如何配置权限
|
||||||
|
5. **前后端联调** - 完整的前后端交互流程
|
||||||
|
|
||||||
|
**详细开发指南请参考**:
|
||||||
|
- [新模块开发指南](./新模块开发指南.md) - 基于 demo 模块的完整开发教程
|
||||||
|
- [编码规范](./编码规范.md) - 命名规范、菜单结构规范等
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 开发规范
|
||||||
|
|
||||||
|
为确保代码质量和团队协作效率,Lyzsys 项目制定了一系列开发规范。
|
||||||
|
|
||||||
|
### 核心规范文档
|
||||||
|
|
||||||
|
1. **[编码规范](./编码规范.md)** - 必读 ⭐⭐⭐⭐⭐
|
||||||
|
- 驼峰命名规范(重要:第一个单词不能只有一个字母)
|
||||||
|
- 菜单结构规范
|
||||||
|
- 代码结构规范
|
||||||
|
- 数据库设计规范
|
||||||
|
- API 接口规范
|
||||||
|
- 前端开发规范
|
||||||
|
|
||||||
|
2. **[新模块开发指南](./新模块开发指南.md)** - 实战教程 ⭐⭐⭐⭐⭐
|
||||||
|
- 快速开始
|
||||||
|
- 创建后端模块(完整步骤)
|
||||||
|
- 创建前端页面
|
||||||
|
- 配置菜单权限
|
||||||
|
- 以 Demo 模块为参考示例
|
||||||
|
|
||||||
|
### 关键规范要点
|
||||||
|
|
||||||
|
#### 命名规范核心原则
|
||||||
|
|
||||||
|
⚠️ **重要**:所有字段名、类名的驼峰命名中,**第一个单词不能只有一个字母**
|
||||||
|
|
||||||
|
```java
|
||||||
|
// ✅ 正确示例
|
||||||
|
private String projectId; // 而非 pId
|
||||||
|
private String projectName; // 而非 pName
|
||||||
|
private String establishDate; // 而非 eDate
|
||||||
|
|
||||||
|
// ❌ 错误示例
|
||||||
|
private String pId; // 单字母开头,可能导致 MyBatis Plus 映射问题
|
||||||
|
private String mType; // 单字母开头
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 菜单结构规范
|
||||||
|
|
||||||
|
业务功能菜单优先展示,系统管理功能放在最后:
|
||||||
|
|
||||||
|
```
|
||||||
|
1-90. 业务菜单(项目管理、客户管理等)
|
||||||
|
98. 系统管理
|
||||||
|
99. 基础设施
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 权限标识格式
|
||||||
|
|
||||||
|
```
|
||||||
|
格式:{模块名}:{业务}:{操作}
|
||||||
|
|
||||||
|
示例:
|
||||||
|
demo:project:query # 查询
|
||||||
|
demo:project:create # 新增
|
||||||
|
demo:project:update # 修改
|
||||||
|
demo:project:delete # 删除
|
||||||
|
demo:project:export # 导出
|
||||||
|
```
|
||||||
|
|
||||||
|
### 开发流程建议
|
||||||
|
|
||||||
|
1. **阅读规范文档** → 了解编码规范和开发流程
|
||||||
|
2. **参考 Demo 模块** → 理解标准的实现方式
|
||||||
|
3. **按照开发指南** → 逐步创建新模块
|
||||||
|
4. **代码评审** → 确保符合规范要求
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 附录
|
## 附录
|
||||||
|
|
||||||
### 常见问题
|
### 常见问题
|
||||||
|
|
||||||
#### Q1: 如何添加新的业务模块?
|
#### Q1: 如何添加新的业务模块?
|
||||||
|
|
||||||
1. 在 `lyzsys-module-xxx` 目录下创建新模块
|
**推荐方式**:参考 [新模块开发指南](./新模块开发指南.md),以 Demo 模块为模板创建新模块。
|
||||||
2. 按照标准模块结构创建包和类
|
|
||||||
3. 在 `lyzsys-server/pom.xml` 中添加模块依赖
|
**快速步骤**:
|
||||||
4. 在 `application.yaml` 中配置模块扫描路径
|
1. 创建 Maven 模块和目录结构
|
||||||
|
2. 编写数据库表(遵循命名规范)
|
||||||
|
3. 按照 Demo 模块的结构创建后端代码
|
||||||
|
4. 创建前端页面和 API 接口
|
||||||
|
5. 配置菜单和权限
|
||||||
|
|
||||||
#### Q2: 如何自定义异常?
|
#### Q2: 如何自定义异常?
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,6 @@
|
|||||||
<dm8.jdbc.version>8.1.3.140</dm8.jdbc.version>
|
<dm8.jdbc.version>8.1.3.140</dm8.jdbc.version>
|
||||||
<kingbase.jdbc.version>8.6.0</kingbase.jdbc.version>
|
<kingbase.jdbc.version>8.6.0</kingbase.jdbc.version>
|
||||||
<opengauss.jdbc.version>5.1.0</opengauss.jdbc.version>
|
<opengauss.jdbc.version>5.1.0</opengauss.jdbc.version>
|
||||||
<sqlserver.jdbc.version>12.8.1.jre8</sqlserver.jdbc.version>
|
|
||||||
<taos.version>3.7.9</taos.version>
|
<taos.version>3.7.9</taos.version>
|
||||||
<!-- 消息队列 -->
|
<!-- 消息队列 -->
|
||||||
<rocketmq-spring.version>2.3.5</rocketmq-spring.version>
|
<rocketmq-spring.version>2.3.5</rocketmq-spring.version>
|
||||||
@@ -297,11 +296,6 @@
|
|||||||
<version>${kingbase.jdbc.version}</version>
|
<version>${kingbase.jdbc.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.microsoft.sqlserver</groupId>
|
|
||||||
<artifactId>mssql-jdbc</artifactId>
|
|
||||||
<version>${sqlserver.jdbc.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.taosdata.jdbc</groupId>
|
<groupId>com.taosdata.jdbc</groupId>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import javax.validation.Valid;
|
|||||||
/**
|
/**
|
||||||
* API 访问日志的 API 接口
|
* API 访问日志的 API 接口
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public interface ApiAccessLogCommonApi {
|
public interface ApiAccessLogCommonApi {
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import javax.validation.Valid;
|
|||||||
/**
|
/**
|
||||||
* API 错误日志的 API 接口
|
* API 错误日志的 API 接口
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public interface ApiErrorLogCommonApi {
|
public interface ApiErrorLogCommonApi {
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import java.time.LocalDateTime;
|
|||||||
/**
|
/**
|
||||||
* API 访问日志
|
* API 访问日志
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
public class ApiAccessLogCreateReqDTO {
|
public class ApiAccessLogCreateReqDTO {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import java.time.LocalDateTime;
|
|||||||
/**
|
/**
|
||||||
* API 错误日志
|
* API 错误日志
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
public class ApiErrorLogCreateReqDTO {
|
public class ApiErrorLogCreateReqDTO {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* 字典数据 API 接口
|
* 字典数据 API 接口
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public interface DictDataCommonApi {
|
public interface DictDataCommonApi {
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import lombok.Data;
|
|||||||
/**
|
/**
|
||||||
* 字典数据 Response DTO
|
* 字典数据 Response DTO
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
public class DictDataRespDTO {
|
public class DictDataRespDTO {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import javax.validation.Valid;
|
|||||||
/**
|
/**
|
||||||
* 操作日志 API 接口
|
* 操作日志 API 接口
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public interface OperateLogCommonApi {
|
public interface OperateLogCommonApi {
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ public class OperateLogCreateReqDTO {
|
|||||||
private Long bizId;
|
private Long bizId;
|
||||||
/**
|
/**
|
||||||
* 操作内容,记录整个操作的明细
|
* 操作内容,记录整个操作的明细
|
||||||
* 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从lyz改成源码。
|
* 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。
|
||||||
*/
|
*/
|
||||||
@NotEmpty(message = "操作内容不能为空")
|
@NotEmpty(message = "操作内容不能为空")
|
||||||
private String action;
|
private String action;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import javax.validation.Valid;
|
|||||||
/**
|
/**
|
||||||
* OAuth2.0 Token API 接口
|
* OAuth2.0 Token API 接口
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public interface OAuth2TokenCommonApi {
|
public interface OAuth2TokenCommonApi {
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import java.util.Map;
|
|||||||
/**
|
/**
|
||||||
* OAuth2.0 访问令牌的校验 Response DTO
|
* OAuth2.0 访问令牌的校验 Response DTO
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
public class OAuth2AccessTokenCheckRespDTO implements Serializable {
|
public class OAuth2AccessTokenCheckRespDTO implements Serializable {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* OAuth2.0 访问令牌创建 Request DTO
|
* OAuth2.0 访问令牌创建 Request DTO
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
public class OAuth2AccessTokenCreateReqDTO implements Serializable {
|
public class OAuth2AccessTokenCreateReqDTO implements Serializable {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import java.time.LocalDateTime;
|
|||||||
/**
|
/**
|
||||||
* OAuth2.0 访问令牌的信息 Response DTO
|
* OAuth2.0 访问令牌的信息 Response DTO
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
public class OAuth2AccessTokenRespDTO implements Serializable {
|
public class OAuth2AccessTokenRespDTO implements Serializable {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import cn.iocoder.lyzsys.framework.common.biz.system.permission.dto.DeptDataPerm
|
|||||||
/**
|
/**
|
||||||
* 权限 API 接口
|
* 权限 API 接口
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public interface PermissionCommonApi {
|
public interface PermissionCommonApi {
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import java.util.Set;
|
|||||||
/**
|
/**
|
||||||
* 部门的数据权限 Response DTO
|
* 部门的数据权限 Response DTO
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
public class DeptDataPermissionRespDTO {
|
public class DeptDataPermissionRespDTO {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* 多租户的 API 接口
|
* 多租户的 API 接口
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public interface TenantCommonApi {
|
public interface TenantCommonApi {
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import java.io.Serializable;
|
|||||||
/**
|
/**
|
||||||
* Key Value 的键值对
|
* Key Value 的键值对
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import java.util.Arrays;
|
|||||||
/**
|
/**
|
||||||
* 通用状态枚举
|
* 通用状态枚举
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import lombok.Getter;
|
|||||||
/**
|
/**
|
||||||
* 文档地址
|
* 文档地址
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ package cn.iocoder.lyzsys.framework.common.enums;
|
|||||||
*
|
*
|
||||||
* 虽然放在 lyzsys-spring-boot-starter-rpc 会相对合适,但是每个 API 模块需要使用到,所以暂时只好放在此处
|
* 虽然放在 lyzsys-spring-boot-starter-rpc 会相对合适,但是每个 API 模块需要使用到,所以暂时只好放在此处
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class RpcConstants {
|
public class RpcConstants {
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import java.util.Arrays;
|
|||||||
/**
|
/**
|
||||||
* 终端的枚举
|
* 终端的枚举
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@Getter
|
@Getter
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ package cn.iocoder.lyzsys.framework.common.enums;
|
|||||||
*
|
*
|
||||||
* 考虑到每个 starter 都需要用到该工具类,所以放到 common 模块下的 enums 包下
|
* 考虑到每个 starter 都需要用到该工具类,所以放到 common 模块下的 enums 包下
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public interface WebFilterOrderEnum {
|
public interface WebFilterOrderEnum {
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import cn.iocoder.lyzsys.framework.common.exception.ErrorCode;
|
|||||||
* 虽然说,HTTP 响应状态码作为业务使用表达能力偏弱,但是使用在系统层面还是非常不错的
|
* 虽然说,HTTP 响应状态码作为业务使用表达能力偏弱,但是使用在系统层面还是非常不错的
|
||||||
* 比较特殊的是,因为之前一直使用 0 作为成功,就不使用 200 啦。
|
* 比较特殊的是,因为之前一直使用 0 作为成功,就不使用 200 啦。
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public interface GlobalErrorCodeConstants {
|
public interface GlobalErrorCodeConstants {
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ package cn.iocoder.lyzsys.framework.common.exception.enums;
|
|||||||
* 不限制规则。
|
* 不限制规则。
|
||||||
* 一般建议,每个模块自增。
|
* 一般建议,每个模块自增。
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class ServiceErrorCodeRange {
|
public class ServiceErrorCodeRange {
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import java.util.concurrent.Executors;
|
|||||||
/**
|
/**
|
||||||
* Cache 工具类
|
* Cache 工具类
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class CacheUtils {
|
public class CacheUtils {
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ public class CacheUtils {
|
|||||||
// 只阻塞当前数据加载线程,其他线程返回旧值
|
// 只阻塞当前数据加载线程,其他线程返回旧值
|
||||||
.refreshAfterWrite(duration)
|
.refreshAfterWrite(duration)
|
||||||
// 通过 asyncReloading 实现全异步加载,包括 refreshAfterWrite 被阻塞的加载线程
|
// 通过 asyncReloading 实现全异步加载,包括 refreshAfterWrite 被阻塞的加载线程
|
||||||
.build(CacheLoader.asyncReloading(loader, Executors.newCachedThreadPool())); // TODO 鹭鹭:可能要思考下,未来要不要做成可配置
|
.build(CacheLoader.asyncReloading(loader, Executors.newCachedThreadPool())); // TODO 芋艿:可能要思考下,未来要不要做成可配置
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import static cn.iocoder.lyzsys.framework.common.util.collection.CollectionUtils
|
|||||||
/**
|
/**
|
||||||
* Array 工具类
|
* Array 工具类
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class ArrayUtils {
|
public class ArrayUtils {
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import static java.util.Arrays.asList;
|
|||||||
/**
|
/**
|
||||||
* Collection 工具类
|
* Collection 工具类
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class CollectionUtils {
|
public class CollectionUtils {
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import java.util.function.Consumer;
|
|||||||
/**
|
/**
|
||||||
* Map 工具类
|
* Map 工具类
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class MapUtils {
|
public class MapUtils {
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import java.util.Set;
|
|||||||
/**
|
/**
|
||||||
* Set 工具类
|
* Set 工具类
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class SetUtils {
|
public class SetUtils {
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import java.util.Date;
|
|||||||
/**
|
/**
|
||||||
* 时间工具类
|
* 时间工具类
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class DateUtils {
|
public class DateUtils {
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import static cn.hutool.core.date.DatePattern.*;
|
|||||||
/**
|
/**
|
||||||
* 时间工具类,用于 {@link LocalDateTime}
|
* 时间工具类,用于 {@link LocalDateTime}
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class LocalDateTimeUtils {
|
public class LocalDateTimeUtils {
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import java.util.Map;
|
|||||||
/**
|
/**
|
||||||
* HTTP 工具类
|
* HTTP 工具类
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class HttpUtils {
|
public class HttpUtils {
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import java.io.File;
|
|||||||
/**
|
/**
|
||||||
* 文件工具类
|
* 文件工具类
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class FileUtils {
|
public class FileUtils {
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import java.io.InputStream;
|
|||||||
/**
|
/**
|
||||||
* IO 工具类,用于 {@link cn.hutool.core.io.IoUtil} 缺失的方法
|
* IO 工具类,用于 {@link cn.hutool.core.io.IoUtil} 缺失的方法
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class IoUtils {
|
public class IoUtils {
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* JSON 工具类
|
* JSON 工具类
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class JsonUtils {
|
public class JsonUtils {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import org.apache.skywalking.apm.toolkit.trace.TraceContext;
|
|||||||
*
|
*
|
||||||
* 考虑到每个 starter 都需要用到该工具类,所以放到 common 模块下的 util 包下
|
* 考虑到每个 starter 都需要用到该工具类,所以放到 common 模块下的 util 包下
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class TracerUtils {
|
public class TracerUtils {
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import java.math.RoundingMode;
|
|||||||
/**
|
/**
|
||||||
* 金额工具类
|
* 金额工具类
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class MoneyUtils {
|
public class MoneyUtils {
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* 数字的工具类,补全 {@link cn.hutool.core.util.NumberUtil} 的功能
|
* 数字的工具类,补全 {@link cn.hutool.core.util.NumberUtil} 的功能
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class NumberUtils {
|
public class NumberUtils {
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import java.util.function.Consumer;
|
|||||||
* 1. 默认使用 {@link cn.hutool.core.bean.BeanUtil} 作为实现类,虽然不同 bean 工具的性能有差别,但是对绝大多数同学的项目,不用在意这点性能
|
* 1. 默认使用 {@link cn.hutool.core.bean.BeanUtil} 作为实现类,虽然不同 bean 工具的性能有差别,但是对绝大多数同学的项目,不用在意这点性能
|
||||||
* 2. 针对复杂的对象转换,可以搜参考 AuthConvert 实现,通过 mapstruct + default 配合实现
|
* 2. 针对复杂的对象转换,可以搜参考 AuthConvert 实现,通过 mapstruct + default 配合实现
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class BeanUtils {
|
public class BeanUtils {
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import java.util.function.Consumer;
|
|||||||
/**
|
/**
|
||||||
* Object 工具类
|
* Object 工具类
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class ObjectUtils {
|
public class ObjectUtils {
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import static java.util.Collections.singletonList;
|
|||||||
/**
|
/**
|
||||||
* {@link cn.iocoder.lyzsys.framework.common.pojo.PageParam} 工具类
|
* {@link cn.iocoder.lyzsys.framework.common.pojo.PageParam} 工具类
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class PageUtils {
|
public class PageUtils {
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import java.util.Map;
|
|||||||
/**
|
/**
|
||||||
* 客户端工具类
|
* 客户端工具类
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class ServletUtils {
|
public class ServletUtils {
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import java.util.Objects;
|
|||||||
/**
|
/**
|
||||||
* Spring 工具类
|
* Spring 工具类
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class SpringUtils extends SpringUtil {
|
public class SpringUtils extends SpringUtil {
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import java.util.stream.Collectors;
|
|||||||
/**
|
/**
|
||||||
* 字符串工具类
|
* 字符串工具类
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class StrUtils {
|
public class StrUtils {
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import java.util.regex.Pattern;
|
|||||||
/**
|
/**
|
||||||
* 校验工具类
|
* 校验工具类
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class ValidationUtils {
|
public class ValidationUtils {
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* 数据权限的自动配置类
|
* 数据权限的自动配置类
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@AutoConfiguration
|
@AutoConfiguration
|
||||||
public class LyzsysDataPermissionAutoConfiguration {
|
public class LyzsysDataPermissionAutoConfiguration {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* 基于部门的数据权限 AutoConfiguration
|
* 基于部门的数据权限 AutoConfiguration
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@AutoConfiguration
|
@AutoConfiguration
|
||||||
@ConditionalOnClass(LoginUser.class)
|
@ConditionalOnClass(LoginUser.class)
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import java.lang.annotation.*;
|
|||||||
* 数据权限注解
|
* 数据权限注解
|
||||||
* 可声明在类或者方法上,标识使用的数据权限规则
|
* 可声明在类或者方法上,标识使用的数据权限规则
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import org.springframework.aop.support.annotation.AnnotationMatchingPointcut;
|
|||||||
/**
|
/**
|
||||||
* {@link cn.iocoder.lyzsys.framework.datapermission.core.annotation.DataPermission} 注解的 Advisor 实现类
|
* {@link cn.iocoder.lyzsys.framework.datapermission.core.annotation.DataPermission} 注解的 Advisor 实现类
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
* 1. 在执行方法前,将 @DataPermission 注解入栈
|
* 1. 在执行方法前,将 @DataPermission 注解入栈
|
||||||
* 2. 在执行方法后,将 @DataPermission 注解出栈
|
* 2. 在执行方法后,将 @DataPermission 注解出栈
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@DataPermission // 该注解,用于 {@link DATA_PERMISSION_NULL} 的空对象
|
@DataPermission // 该注解,用于 {@link DATA_PERMISSION_NULL} 的空对象
|
||||||
public class DataPermissionAnnotationInterceptor implements MethodInterceptor {
|
public class DataPermissionAnnotationInterceptor implements MethodInterceptor {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* {@link DataPermission} 注解的 Context 上下文
|
* {@link DataPermission} 注解的 Context 上下文
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class DataPermissionContextHolder {
|
public class DataPermissionContextHolder {
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import static cn.iocoder.lyzsys.framework.security.core.util.SecurityFrameworkUt
|
|||||||
* 它的底层,是基于 MyBatis Plus 的 <a href="https://baomidou.com/plugins/data-permission/">数据权限插件</a>
|
* 它的底层,是基于 MyBatis Plus 的 <a href="https://baomidou.com/plugins/data-permission/">数据权限插件</a>
|
||||||
* 核心原理:它会在 SQL 执行前拦截 SQL 语句,并根据用户权限动态添加权限相关的 SQL 片段。这样,只有用户有权限访问的数据才会被查询出来
|
* 核心原理:它会在 SQL 执行前拦截 SQL 语句,并根据用户权限动态添加权限相关的 SQL 片段。这样,只有用户有权限访问的数据才会被查询出来
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class DataPermissionRuleHandler implements MultiDataPermissionHandler {
|
public class DataPermissionRuleHandler implements MultiDataPermissionHandler {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import java.util.Set;
|
|||||||
* 数据权限规则接口
|
* 数据权限规则接口
|
||||||
* 通过实现接口,自定义数据规则。例如说,
|
* 通过实现接口,自定义数据规则。例如说,
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public interface DataPermissionRule {
|
public interface DataPermissionRule {
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import java.util.List;
|
|||||||
* {@link DataPermissionRule} 工厂接口
|
* {@link DataPermissionRule} 工厂接口
|
||||||
* 作为 {@link DataPermissionRule} 的容器,提供管理能力
|
* 作为 {@link DataPermissionRule} 的容器,提供管理能力
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public interface DataPermissionRuleFactory {
|
public interface DataPermissionRuleFactory {
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import java.util.stream.Collectors;
|
|||||||
* 默认的 DataPermissionRuleFactoryImpl 实现类
|
* 默认的 DataPermissionRuleFactoryImpl 实现类
|
||||||
* 支持通过 {@link DataPermissionContextHolder} 过滤数据权限
|
* 支持通过 {@link DataPermissionContextHolder} 过滤数据权限
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class DataPermissionRuleFactoryImpl implements DataPermissionRuleFactory {
|
public class DataPermissionRuleFactoryImpl implements DataPermissionRuleFactory {
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ import java.util.Set;
|
|||||||
* 3)想要保证原 dept_id 和 user_id 都可以看的到,此时使用 dept_id 和 user_id 一起过滤;
|
* 3)想要保证原 dept_id 和 user_id 都可以看的到,此时使用 dept_id 和 user_id 一起过滤;
|
||||||
* 最终过滤条件是 WHERE dept_id = ? OR user_id IN (?, ?, ? ...)
|
* 最终过滤条件是 WHERE dept_id = ? OR user_id IN (?, ?, ? ...)
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@@ -128,7 +128,7 @@ public class DeptDataPermissionRule implements DataPermissionRule {
|
|||||||
Expression deptExpression = buildDeptExpression(tableName,tableAlias, deptDataPermission.getDeptIds());
|
Expression deptExpression = buildDeptExpression(tableName,tableAlias, deptDataPermission.getDeptIds());
|
||||||
Expression userExpression = buildUserExpression(tableName, tableAlias, deptDataPermission.getSelf(), loginUser.getId());
|
Expression userExpression = buildUserExpression(tableName, tableAlias, deptDataPermission.getSelf(), loginUser.getId());
|
||||||
if (deptExpression == null && userExpression == null) {
|
if (deptExpression == null && userExpression == null) {
|
||||||
// TODO 鹭鹭:获得不到条件的时候,暂时不抛出异常,而是不返回数据
|
// TODO 芋艿:获得不到条件的时候,暂时不抛出异常,而是不返回数据
|
||||||
log.warn("[getExpression][LoginUser({}) Table({}/{}) DeptDataPermission({}) 构建的条件为空]",
|
log.warn("[getExpression][LoginUser({}) Table({}/{}) DeptDataPermission({}) 构建的条件为空]",
|
||||||
JsonUtils.toJsonString(loginUser), tableName, tableAlias, JsonUtils.toJsonString(deptDataPermission));
|
JsonUtils.toJsonString(loginUser), tableName, tableAlias, JsonUtils.toJsonString(deptDataPermission));
|
||||||
// throw new NullPointerException(String.format("LoginUser(%d) Table(%s/%s) 构建的条件为空",
|
// throw new NullPointerException(String.format("LoginUser(%d) Table(%s/%s) 构建的条件为空",
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package cn.iocoder.lyzsys.framework.datapermission.core.rule.dept;
|
|||||||
/**
|
/**
|
||||||
* {@link DeptDataPermissionRule} 的自定义配置接口
|
* {@link DeptDataPermissionRule} 的自定义配置接口
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface DeptDataPermissionRuleCustomizer {
|
public interface DeptDataPermissionRuleCustomizer {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* 基于部门的数据权限规则
|
* 基于部门的数据权限规则
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
package cn.iocoder.lyzsys.framework.datapermission.core.rule.dept;
|
package cn.iocoder.lyzsys.framework.datapermission.core.rule.dept;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import java.util.concurrent.Callable;
|
|||||||
/**
|
/**
|
||||||
* 数据权限 Util
|
* 数据权限 Util
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class DataPermissionUtils {
|
public class DataPermissionUtils {
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import static org.mockito.Mockito.when;
|
|||||||
/**
|
/**
|
||||||
* {@link DataPermissionAnnotationInterceptor} 的单元测试
|
* {@link DataPermissionAnnotationInterceptor} 的单元测试
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class DataPermissionAnnotationInterceptorTest extends BaseMockitoUnitTest {
|
public class DataPermissionAnnotationInterceptorTest extends BaseMockitoUnitTest {
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import static org.mockito.Mockito.mock;
|
|||||||
/**
|
/**
|
||||||
* {@link DataPermissionContextHolder} 的单元测试
|
* {@link DataPermissionContextHolder} 的单元测试
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
class DataPermissionContextHolderTest {
|
class DataPermissionContextHolderTest {
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import static org.mockito.Mockito.when;
|
|||||||
* 主要复用了 MyBatis Plus 的 TenantLineInnerInterceptorTest 的单元测试
|
* 主要复用了 MyBatis Plus 的 TenantLineInnerInterceptorTest 的单元测试
|
||||||
* 不过它的单元测试不是很规范,考虑到是复用的,所以暂时不进行修改~
|
* 不过它的单元测试不是很规范,考虑到是复用的,所以暂时不进行修改~
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class DataPermissionRuleHandlerTest extends BaseMockitoUnitTest {
|
public class DataPermissionRuleHandlerTest extends BaseMockitoUnitTest {
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import static org.junit.jupiter.api.Assertions.*;
|
|||||||
/**
|
/**
|
||||||
* {@link DataPermissionRuleFactoryImpl} 单元测试
|
* {@link DataPermissionRuleFactoryImpl} 单元测试
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
class DataPermissionRuleFactoryImplTest extends BaseMockitoUnitTest {
|
class DataPermissionRuleFactoryImplTest extends BaseMockitoUnitTest {
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import static org.mockito.Mockito.when;
|
|||||||
/**
|
/**
|
||||||
* {@link DeptDataPermissionRule} 的单元测试
|
* {@link DeptDataPermissionRule} 的单元测试
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
class DeptDataPermissionRuleTest extends BaseMockitoUnitTest {
|
class DeptDataPermissionRuleTest extends BaseMockitoUnitTest {
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import java.util.List;
|
|||||||
*
|
*
|
||||||
* 数据可见 resources/area.csv 文件
|
* 数据可见 resources/area.csv 文件
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import java.util.Arrays;
|
|||||||
/**
|
/**
|
||||||
* 区域类型枚举
|
* 区域类型枚举
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@Getter
|
@Getter
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import static cn.iocoder.lyzsys.framework.common.util.collection.CollectionUtils
|
|||||||
/**
|
/**
|
||||||
* 区域工具类
|
* 区域工具类
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class AreaUtils {
|
public class AreaUtils {
|
||||||
|
|||||||
@@ -6,6 +6,6 @@
|
|||||||
* 2. 城市功能:查询城市编码对应的城市信息
|
* 2. 城市功能:查询城市编码对应的城市信息
|
||||||
* 基于 https://github.com/modood/Administrative-divisions-of-China 实现
|
* 基于 https://github.com/modood/Administrative-divisions-of-China 实现
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
package cn.iocoder.lyzsys.framework.ip;
|
package cn.iocoder.lyzsys.framework.ip;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
|||||||
/**
|
/**
|
||||||
* {@link AreaUtils} 的单元测试
|
* {@link AreaUtils} 的单元测试
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class AreaUtilsTest {
|
public class AreaUtilsTest {
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import java.util.Set;
|
|||||||
/**
|
/**
|
||||||
* 多租户配置
|
* 多租户配置
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@ConfigurationProperties(prefix = "lyzsys.tenant")
|
@ConfigurationProperties(prefix = "lyzsys.tenant")
|
||||||
@Data
|
@Data
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import java.lang.annotation.*;
|
|||||||
* 1、如果添加到 Controller 类上,则该 URL 自动添加到 {@link TenantProperties#getIgnoreUrls()} 中
|
* 1、如果添加到 Controller 类上,则该 URL 自动添加到 {@link TenantProperties#getIgnoreUrls()} 中
|
||||||
* 2、如果添加到 DO 实体类上,则它对应的表名“相当于”自动添加到 {@link TenantProperties#getIgnoreTables()} 中
|
* 2、如果添加到 DO 实体类上,则它对应的表名“相当于”自动添加到 {@link TenantProperties#getIgnoreTables()} 中
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import org.aspectj.lang.annotation.Aspect;
|
|||||||
*
|
*
|
||||||
* 整体逻辑的实现,和 {@link TenantUtils#executeIgnore(Runnable)} 需要保持一致
|
* 整体逻辑的实现,和 {@link TenantUtils#executeIgnore(Runnable)} 需要保持一致
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@Aspect
|
@Aspect
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import com.alibaba.ttl.TransmittableThreadLocal;
|
|||||||
/**
|
/**
|
||||||
* 多租户上下文 Holder
|
* 多租户上下文 Holder
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class TenantContextHolder {
|
public class TenantContextHolder {
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import lombok.EqualsAndHashCode;
|
|||||||
/**
|
/**
|
||||||
* 拓展多租户的 BaseDO 基类
|
* 拓展多租户的 BaseDO 基类
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import java.util.Map;
|
|||||||
/**
|
/**
|
||||||
* 基于 MyBatis Plus 多租户的功能,实现 DB 层面的多租户的功能
|
* 基于 MyBatis Plus 多租户的功能,实现 DB 层面的多租户的功能
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class TenantDatabaseInterceptor implements TenantLineHandler {
|
public class TenantDatabaseInterceptor implements TenantLineHandler {
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
*
|
*
|
||||||
* 注意,需要保证 JobHandler 的幂等性。因为 Job 因为某个租户执行失败重试时,之前执行成功的租户也会再次执行。
|
* 注意,需要保证 JobHandler 的幂等性。因为 Job 因为某个租户执行失败重试时,之前执行成功的租户也会再次执行。
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@Aspect
|
@Aspect
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@@ -42,7 +42,7 @@ public class TenantJobAspect {
|
|||||||
// 逐个租户,执行 Job
|
// 逐个租户,执行 Job
|
||||||
Map<Long, String> results = new ConcurrentHashMap<>();
|
Map<Long, String> results = new ConcurrentHashMap<>();
|
||||||
tenantIds.parallelStream().forEach(tenantId -> {
|
tenantIds.parallelStream().forEach(tenantId -> {
|
||||||
// TODO 鹭鹭:先通过 parallel 实现并行;1)多个租户,是一条执行日志;2)异常的情况
|
// TODO 芋艿:先通过 parallel 实现并行;1)多个租户,是一条执行日志;2)异常的情况
|
||||||
TenantUtils.execute(tenantId, () -> {
|
TenantUtils.execute(tenantId, () -> {
|
||||||
try {
|
try {
|
||||||
Object result = joinPoint.proceed();
|
Object result = joinPoint.proceed();
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import org.springframework.core.env.ConfigurableEnvironment;
|
|||||||
*
|
*
|
||||||
* Kafka Producer 发送消息时,增加 {@link TenantKafkaProducerInterceptor} 拦截器
|
* Kafka Producer 发送消息时,增加 {@link TenantKafkaProducerInterceptor} 拦截器
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class TenantKafkaEnvironmentPostProcessor implements EnvironmentPostProcessor {
|
public class TenantKafkaEnvironmentPostProcessor implements EnvironmentPostProcessor {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import static cn.iocoder.lyzsys.framework.web.core.util.WebFrameworkUtils.HEADER
|
|||||||
* 1. Producer 发送消息时,将 {@link TenantContextHolder} 租户编号,添加到消息的 Header 中
|
* 1. Producer 发送消息时,将 {@link TenantContextHolder} 租户编号,添加到消息的 Header 中
|
||||||
* 2. Consumer 消费消息时,将消息的 Header 的租户编号,添加到 {@link TenantContextHolder} 中,通过 {@link InvocableHandlerMethod} 实现
|
* 2. Consumer 消费消息时,将消息的 Header 的租户编号,添加到 {@link TenantContextHolder} 中,通过 {@link InvocableHandlerMethod} 实现
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class TenantKafkaProducerInterceptor implements ProducerInterceptor<Object, Object> {
|
public class TenantKafkaProducerInterceptor implements ProducerInterceptor<Object, Object> {
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import org.springframework.beans.factory.config.BeanPostProcessor;
|
|||||||
/**
|
/**
|
||||||
* 多租户的 RabbitMQ 初始化器
|
* 多租户的 RabbitMQ 初始化器
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class TenantRabbitMQInitializer implements BeanPostProcessor {
|
public class TenantRabbitMQInitializer implements BeanPostProcessor {
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import static cn.iocoder.lyzsys.framework.web.core.util.WebFrameworkUtils.HEADER
|
|||||||
* 1. Producer 发送消息时,将 {@link TenantContextHolder} 租户编号,添加到消息的 Header 中
|
* 1. Producer 发送消息时,将 {@link TenantContextHolder} 租户编号,添加到消息的 Header 中
|
||||||
* 2. Consumer 消费消息时,将消息的 Header 的租户编号,添加到 {@link TenantContextHolder} 中,通过 {@link InvocableHandlerMethod} 实现
|
* 2. Consumer 消费消息时,将消息的 Header 的租户编号,添加到 {@link TenantContextHolder} 中,通过 {@link InvocableHandlerMethod} 实现
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class TenantRabbitMQMessagePostProcessor implements MessagePostProcessor {
|
public class TenantRabbitMQMessagePostProcessor implements MessagePostProcessor {
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import static cn.iocoder.lyzsys.framework.web.core.util.WebFrameworkUtils.HEADER
|
|||||||
* 1. Producer 发送消息时,将 {@link TenantContextHolder} 租户编号,添加到消息的 Header 中
|
* 1. Producer 发送消息时,将 {@link TenantContextHolder} 租户编号,添加到消息的 Header 中
|
||||||
* 2. Consumer 消费消息时,将消息的 Header 的租户编号,添加到 {@link TenantContextHolder} 中
|
* 2. Consumer 消费消息时,将消息的 Header 的租户编号,添加到 {@link TenantContextHolder} 中
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class TenantRedisMessageInterceptor implements RedisMessageInterceptor {
|
public class TenantRedisMessageInterceptor implements RedisMessageInterceptor {
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import static cn.iocoder.lyzsys.framework.web.core.util.WebFrameworkUtils.HEADER
|
|||||||
*
|
*
|
||||||
* Consumer 消费消息时,将消息的 Header 的租户编号,添加到 {@link TenantContextHolder} 中,通过 {@link InvocableHandlerMethod} 实现
|
* Consumer 消费消息时,将消息的 Header 的租户编号,添加到 {@link TenantContextHolder} 中,通过 {@link InvocableHandlerMethod} 实现
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class TenantRocketMQConsumeMessageHook implements ConsumeMessageHook {
|
public class TenantRocketMQConsumeMessageHook implements ConsumeMessageHook {
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import org.springframework.beans.factory.config.BeanPostProcessor;
|
|||||||
/**
|
/**
|
||||||
* 多租户的 RocketMQ 初始化器
|
* 多租户的 RocketMQ 初始化器
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class TenantRocketMQInitializer implements BeanPostProcessor {
|
public class TenantRocketMQInitializer implements BeanPostProcessor {
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import static cn.iocoder.lyzsys.framework.web.core.util.WebFrameworkUtils.HEADER
|
|||||||
*
|
*
|
||||||
* Producer 发送消息时,将 {@link TenantContextHolder} 租户编号,添加到消息的 Header 中
|
* Producer 发送消息时,将 {@link TenantContextHolder} 租户编号,添加到消息的 Header 中
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class TenantRocketMQSendMessageHook implements SendMessageHook {
|
public class TenantRocketMQSendMessageHook implements SendMessageHook {
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ import java.util.Set;
|
|||||||
* 2. 如果请求未带租户的编号,检查是否是忽略的 URL,否则也不允许访问。
|
* 2. 如果请求未带租户的编号,检查是否是忽略的 URL,否则也不允许访问。
|
||||||
* 3. 校验租户是合法,例如说被禁用、到期
|
* 3. 校验租户是合法,例如说被禁用、到期
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class TenantSecurityWebFilter extends ApiRequestFilter {
|
public class TenantSecurityWebFilter extends ApiRequestFilter {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* Tenant 框架 Service 接口,定义获取租户信息
|
* Tenant 框架 Service 接口,定义获取租户信息
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public interface TenantFrameworkService {
|
public interface TenantFrameworkService {
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* Tenant 框架 Service 实现类
|
* Tenant 框架 Service 实现类
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class TenantFrameworkServiceImpl implements TenantFrameworkService {
|
public class TenantFrameworkServiceImpl implements TenantFrameworkService {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import static cn.iocoder.lyzsys.framework.web.core.util.WebFrameworkUtils.HEADER
|
|||||||
/**
|
/**
|
||||||
* 多租户 Util
|
* 多租户 Util
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class TenantUtils {
|
public class TenantUtils {
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import java.io.IOException;
|
|||||||
* 多租户 Context Web 过滤器
|
* 多租户 Context Web 过滤器
|
||||||
* 将请求 Header 中的 tenant-id 解析出来,添加到 {@link TenantContextHolder} 中,这样后续的 DB 等操作,可以获得到租户编号。
|
* 将请求 Header 中的 tenant-id 解析出来,添加到 {@link TenantContextHolder} 中,这样后续的 DB 等操作,可以获得到租户编号。
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class TenantContextWebFilter extends OncePerRequestFilter {
|
public class TenantContextWebFilter extends OncePerRequestFilter {
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ import static cn.iocoder.lyzsys.framework.web.core.util.WebFrameworkUtils.HEADER
|
|||||||
* {@link HandlerMethodArgumentResolver}.
|
* {@link HandlerMethodArgumentResolver}.
|
||||||
*
|
*
|
||||||
* 针对 rabbitmq-spring 和 kafka-spring,不存在合适的拓展点,可以实现 Consumer 消费前,读取 Header 中的 tenant-id 设置到 {@link TenantContextHolder} 中
|
* 针对 rabbitmq-spring 和 kafka-spring,不存在合适的拓展点,可以实现 Consumer 消费前,读取 Header 中的 tenant-id 设置到 {@link TenantContextHolder} 中
|
||||||
* TODO 鹭鹭:持续跟进,看看有没新的拓展点
|
* TODO 芋艿:持续跟进,看看有没新的拓展点
|
||||||
*
|
*
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import static cn.iocoder.lyzsys.framework.common.util.collection.CollectionUtils
|
|||||||
/**
|
/**
|
||||||
* 字典工具类
|
* 字典工具类
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class DictFrameworkUtils {
|
public class DictFrameworkUtils {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
/**
|
/**
|
||||||
* Excel 数据字典转换器
|
* Excel 数据字典转换器
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class DictConvert implements Converter<Object> {
|
public class DictConvert implements Converter<Object> {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import cn.idev.excel.metadata.property.ExcelContentProperty;
|
|||||||
/**
|
/**
|
||||||
* Excel Json 转换器
|
* Excel Json 转换器
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class JsonConvert implements Converter<Object> {
|
public class JsonConvert implements Converter<Object> {
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import java.math.RoundingMode;
|
|||||||
*
|
*
|
||||||
* 金额单位:分
|
* 金额单位:分
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class MoneyConvert implements Converter<Integer> {
|
public class MoneyConvert implements Converter<Integer> {
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* Excel 工具类
|
* Excel 工具类
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class ExcelUtils {
|
public class ExcelUtils {
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package cn.iocoder.lyzsys.framework.quartz.core.handler;
|
|||||||
/**
|
/**
|
||||||
* 任务处理器
|
* 任务处理器
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public interface JobHandler {
|
public interface JobHandler {
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import static cn.hutool.core.exceptions.ExceptionUtil.getRootCauseMessage;
|
|||||||
/**
|
/**
|
||||||
* 基础 Job 调用者,负责调用 {@link JobHandler#execute(String)} 执行任务
|
* 基础 Job 调用者,负责调用 {@link JobHandler#execute(String)} 执行任务
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@DisallowConcurrentExecution
|
@DisallowConcurrentExecution
|
||||||
@PersistJobDataAfterExecution
|
@PersistJobDataAfterExecution
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import static cn.iocoder.lyzsys.framework.common.exception.util.ServiceException
|
|||||||
*
|
*
|
||||||
* 另外,jobHandlerName 对应到 Spring Bean 的名字,直接调用
|
* 另外,jobHandlerName 对应到 Spring Bean 的名字,直接调用
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class SchedulerManager {
|
public class SchedulerManager {
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import java.time.LocalDateTime;
|
|||||||
/**
|
/**
|
||||||
* Job 日志 Framework Service 接口
|
* Job 日志 Framework Service 接口
|
||||||
*
|
*
|
||||||
* @author lyz源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public interface JobLogFrameworkService {
|
public interface JobLogFrameworkService {
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user