28 KiB
动作和自动化功能设计文档
元数据
- 需求编号:004
- 子需求编号:004-05
- 子需求名称:动作和自动化功能
- 阶段:阶段 2:方案设计
- 创建时间:2026-01-28
- 创建人:AI Assistant
- 状态:已完成
相关文档
1. 架构设计
1.1 系统架构图
graph TB
subgraph "前端层"
A[前端应用]
end
subgraph "API 网关层"
B[API Gateway]
end
subgraph "Controller 层"
C[ToolingActionAutomationController]
end
subgraph "Service 层"
D[IToolingActionAutomationService]
E[ToolingActionAutomationServiceImpl]
end
subgraph "Factory 层"
F[ToolingConnectionFactory]
end
subgraph "Auth 层"
G[SessionManager]
end
subgraph "DAO 层"
H[ToolingActionAutomationLogMapper]
end
subgraph "数据库层"
I[datai_tooling_action_automation_log]
end
subgraph "外部服务"
J[Salesforce Tooling API]
end
A --> B
B --> C
C --> D
D --> E
E --> F
E --> H
F --> G
F --> J
H --> I
style A fill:#e1f5ff
style B fill:#fff4e1
style C fill:#ffe1e1
style D fill:#e1ffe1
style E fill:#e1ffe1
style F fill:#f0e1ff
style G fill:#f0e1ff
style H fill:#ffe1f0
style I fill:#ffe1f0
style J fill:#e1e1ff
1.2 数据流图
sequenceDiagram
participant Client as 前端应用
participant Controller as ToolingActionAutomationController
participant Service as ToolingActionAutomationServiceImpl
participant Factory as ToolingConnectionFactory
participant Auth as SessionManager
participant API as Salesforce Tooling API
participant DB as 数据库
Client->>Controller: 创建动作覆盖
Controller->>Service: createActionOverride(actionOverride)
Service->>Factory: getConnection("source")
Factory->>Auth: getSession("source")
Auth-->>Factory: SessionInfo
Factory-->>Service: ToolingConnection
Service->>API: connection.create()
API-->>Service: SaveResult
Service->>Service: 异步记录操作日志
Service->>DB: insert(log)
Service-->>Controller: ToolingActionResult
Controller-->>Client: 响应结果
1.3 模块依赖关系
graph LR
A[datai-salesforce-tooling] --> B[datai-salesforce-auth]
A --> C[datai-salesforce-common]
A --> D[tooling.jar]
B --> E[datai-salesframework]
C --> E
style A fill:#e1f5ff
style B fill:#fff4e1
style C fill:#ffe1e1
style D fill:#e1ffe1
style E fill:#f0e1ff
2. 技术方案
2.1 核心技术栈
| 技术组件 | 版本 | 用途 |
|---|---|---|
| Java | 22 | 开发语言 |
| Spring Boot | 3.x | 应用框架 |
| MyBatis Plus | 3.x | ORM 框架 |
| Lombok | 1.18.x | 代码简化 |
| Jakarta Validation | 3.x | 参数校验 |
| Salesforce Tooling API | v65.0 | Salesforce 工具 API |
| tooling.jar | 65.0 | Salesforce 官方客户端 |
2.2 设计模式
2.2.1 工厂模式
目的:统一管理 Tooling API 连接的创建和缓存
实现:
- 继承
AbstractConnectionFactory实现ToolingConnectionFactory - 使用
ConcurrentHashMap缓存连接 - 提供
getConnection(String orgType)方法获取连接
2.2.2 服务层模式
目的:封装业务逻辑,提供清晰的接口
实现:
- 定义
IToolingActionAutomationService接口 - 实现
ToolingActionAutomationServiceImpl类 - 使用
@Service注解注册为 Spring Bean
2.2.3 异步日志模式
目的:避免日志记录影响主流程性能
实现:
- 使用
CompletableFuture异步记录操作日志 - 使用自定义线程池
asyncExecutor - 日志记录失败不影响主流程
2.3 连接管理方案
2.3.1 连接获取流程
flowchart TD
A[开始] --> B[调用 getConnection]
B --> C{缓存中是否存在?}
C -->|是| D[返回缓存连接]
C -->|否| E[从 SessionManager 获取 Session]
E --> F{Session 是否有效?}
F -->|否| G[抛出 SalesforceLoginException]
F -->|是| H[创建 ToolingConnection]
H --> I[设置 SessionHeader]
I --> J[缓存连接]
J --> D
D --> K[结束]
G --> K
2.3.2 连接缓存策略
- 缓存键:
orgType(固定为 "source") - 缓存实现:
ConcurrentHashMap<String, ToolingConnection> - 缓存清理:提供
clearCache()方法手动清理 - 缓存失效:Session 失效时自动清理
2.4 异常处理方案
2.4.1 异常转换规则
| Salesforce 异常 | 转换异常 | 错误码 |
|---|---|---|
| INVALID_SESSION_ID | SalesforceAuthException | TOOLING_ACTION_001 |
| CREATE_FAILED | SalesforceAuthException | TOOLING_ACTION_002 |
| UPDATE_FAILED | SalesforceAuthException | TOOLING_ACTION_003 |
| DELETE_FAILED | SalesforceAuthException | TOOLING_ACTION_004 |
| QUERY_EXECUTION_ERROR | SalesforceAuthException | TOOLING_ACTION_005 |
| NETWORK_TIMEOUT | SalesforceAuthException | TOOLING_ACTION_006 |
| INSUFFICIENT_ACCESS | SalesforceAuthException | TOOLING_ACTION_007 |
| RECORD_NOT_FOUND | SalesforceAuthException | TOOLING_ACTION_008 |
| Session 无效 | SalesforceLoginException | TOOLING_ACTION_009 |
2.4.2 异常处理流程
flowchart TD
A[调用 Salesforce API] --> B{是否抛出异常?}
B -->|否| C[返回正常结果]
B -->|是| D{异常类型?}
D -->|INVALID_SESSION_ID| E[转换为 SalesforceAuthException<br/>TOOLING_ACTION_001]
D -->|CREATE_FAILED| F[转换为 SalesforceAuthException<br/>TOOLING_ACTION_002]
D -->|UPDATE_FAILED| G[转换为 SalesforceAuthException<br/>TOOLING_ACTION_003]
D -->|DELETE_FAILED| H[转换为 SalesforceAuthException<br/>TOOLING_ACTION_004]
D -->|QUERY_EXECUTION_ERROR| I[转换为 SalesforceAuthException<br/>TOOLING_ACTION_005]
D -->|NETWORK_TIMEOUT| J[转换为 SalesforceAuthException<br/>TOOLING_ACTION_006]
D -->|INSUFFICIENT_ACCESS| K[转换为 SalesforceAuthException<br/>TOOLING_ACTION_007]
D -->|RECORD_NOT_FOUND| L[转换为 SalesforceAuthException<br/>TOOLING_ACTION_008]
D -->|其他| M[记录日志并抛出通用异常]
E --> N[记录操作日志]
F --> N
G --> N
H --> N
I --> N
J --> N
K --> N
L --> N
N --> O[抛出转换后的异常]
C --> P[记录操作日志]
P --> Q[返回结果]
O --> R[结束]
Q --> R
M --> R
2.5 SOQL 查询方案
2.5.1 查询构建器
使用 SoqlBuilder 构建 SOQL 查询语句:
SoqlBuilder builder = SoqlBuilder.newInstance()
.select("Id, ActionName, Content, FormFactor, PageOrSobjectType, RecordType, Type")
.from("ActionOverride");
if (StringUtils.isNotBlank(pageOrSobjectType)) {
builder.where("PageOrSobjectType = :type")
.setParameter("type", pageOrSobjectType);
}
if (StringUtils.isNotBlank(actionName)) {
builder.where("ActionName = :name")
.setParameter("name", actionName);
}
QueryResult result = connection.query(builder.build());
2.5.2 查询优化
- 字段选择:只查询需要的字段,避免
SELECT * - 过滤条件:在 WHERE 子句中添加过滤条件,减少返回数据量
- 分页查询:支持分页查询,避免一次性返回大量数据
3. 数据模型
3.1 数据库表设计
3.1.1 ToolingActionAutomationLog(动作和自动化操作日志表)
表名:datai_tooling_action_automation_log
字段说明:
| 字段名 | 类型 | 长度 | 允许 NULL | 默认值 | 说明 |
|---|---|---|---|---|---|
| id | BIGINT | - | 否 | AUTO_INCREMENT | 主键 ID |
| operation_type | VARCHAR | 50 | 否 | - | 操作类型 |
| metadata_type | VARCHAR | 100 | 是 | NULL | 元数据类型 |
| metadata_id | VARCHAR | 255 | 是 | NULL | 元数据 ID |
| metadata_name | VARCHAR | 255 | 是 | NULL | 元数据名称 |
| request_data | TEXT | - | 是 | NULL | 请求数据(JSON 格式) |
| response_data | TEXT | - | 是 | NULL | 响应数据(JSON 格式) |
| result_count | INT | - | 否 | 0 | 结果数量 |
| status | VARCHAR | 20 | 否 | - | 操作状态(success/failed) |
| error_code | VARCHAR | 50 | 是 | NULL | 错误码 |
| error_message | TEXT | - | 是 | NULL | 错误消息 |
| operation_time | DATETIME | - | 否 | - | 操作时间 |
| user_id | VARCHAR | 50 | 是 | NULL | 用户 ID |
| create_time | DATETIME | - | 否 | CURRENT_TIMESTAMP | 记录创建时间 |
| update_time | DATETIME | - | 否 | CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | 记录更新时间 |
索引设计:
| 索引名 | 索引类型 | 字段 | 说明 |
|---|---|---|---|
| PRIMARY | 主键 | id | 主键索引 |
| idx_operation_type | 普通索引 | operation_type | 按操作类型查询 |
| idx_metadata_type | 普通索引 | metadata_type | 按元数据类型查询 |
| idx_metadata_id | 普通索引 | metadata_id | 按元数据 ID 查询 |
| idx_metadata_name | 普通索引 | metadata_name | 按元数据名称查询 |
| idx_operation_time | 普通索引 | operation_time | 按操作时间查询 |
| idx_user_id | 普通索引 | user_id | 按用户 ID 查询 |
| idx_status | 普通索引 | status | 按状态查询 |
| idx_metadata_type_operation_time | 复合索引 | metadata_type, operation_time | 按类型和时间范围查询 |
| idx_operation_type_status | 复合索引 | operation_type, status | 按操作类型和状态查询 |
建表 SQL:
CREATE TABLE IF NOT EXISTS `datai_tooling_action_automation_log` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`operation_type` VARCHAR(50) NOT NULL COMMENT '操作类型(create_action_override、update_action_override、delete_action_override、query_action_overrides、query_actionable_lists、get_action_override_types、get_action_subtypes、get_actionable_list_types、get_actionable_list_source_types、get_action_task_assigned_to_types、get_action_http_methods、get_action_email_sender_types)',
`metadata_type` VARCHAR(100) DEFAULT NULL COMMENT '元数据类型(ActionOverride、ActionableList、ActionOverrideType、ActionSubtype、ActionableListType、ActionableListSourceType、ActionTaskAssignedToTypes、ActionHttpMethod、ActionEmailSenderType)',
`metadata_id` VARCHAR(255) DEFAULT NULL COMMENT '元数据ID(Salesforce返回的ID)',
`metadata_name` VARCHAR(255) DEFAULT NULL COMMENT '元数据名称(API名称)',
`request_data` TEXT DEFAULT NULL COMMENT '请求数据(JSON格式,记录完整的请求参数)',
`response_data` TEXT DEFAULT NULL COMMENT '响应数据(JSON格式,记录完整的响应数据)',
`result_count` INT NOT NULL DEFAULT 0 COMMENT '结果数量',
`status` VARCHAR(20) NOT NULL COMMENT '操作状态(success-成功、failed-失败)',
`error_code` VARCHAR(50) DEFAULT NULL COMMENT '错误码(失败时记录)',
`error_message` TEXT DEFAULT NULL COMMENT '错误消息(失败时记录详细错误信息)',
`operation_time` DATETIME NOT NULL COMMENT '操作时间',
`user_id` VARCHAR(50) DEFAULT NULL COMMENT '操作用户ID',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '记录创建时间',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '记录更新时间',
PRIMARY KEY (`id`),
KEY `idx_operation_type` (`operation_type`),
KEY `idx_metadata_type` (`metadata_type`),
KEY `idx_metadata_id` (`metadata_id`),
KEY `idx_metadata_name` (`metadata_name`),
KEY `idx_operation_time` (`operation_time`),
KEY `idx_user_id` (`user_id`),
KEY `idx_status` (`status`),
KEY `idx_metadata_type_operation_time` (`metadata_type`, `operation_time`),
KEY `idx_operation_type_status` (`operation_type`, `status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Tooling API 动作和自动化操作日志表';
3.2 实体类设计
3.2.1 ToolingActionAutomationLog
包路径:com.datai.tooling.domain.entity.ToolingActionAutomationLog
类定义:
package com.datai.tooling.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@TableName("datai_tooling_action_automation_log")
public class ToolingActionAutomationLog {
@TableId(type = IdType.AUTO)
private Long id;
private String operationType;
private String metadataType;
private String metadataId;
private String metadataName;
private String requestData;
private String responseData;
private Integer resultCount;
private String status;
private String errorCode;
private String errorMessage;
private LocalDateTime operationTime;
private String userId;
private LocalDateTime createTime;
private LocalDateTime updateTime;
}
3.3 DTO 设计
3.3.1 ActionOverrideRequest
包路径:com.datai.tooling.domain.dto.ActionOverrideRequest
类定义:
package com.datai.tooling.domain.dto;
import lombok.Data;
import jakarta.validation.constraints.NotBlank;
@Data
public class ActionOverrideRequest {
@NotBlank(message = "动作名称不能为空")
private String actionName;
@NotBlank(message = "内容不能为空")
private String content;
private String formFactor;
private String pageOrSobjectType;
private String recordType;
private String type;
}
3.3.2 ActionOverrideUpdateRequest
包路径:com.datai.tooling.domain.dto.ActionOverrideUpdateRequest
类定义:
package com.datai.tooling.domain.dto;
import lombok.Data;
import jakarta.validation.constraints.NotBlank;
@Data
public class ActionOverrideUpdateRequest {
@NotBlank(message = "记录ID不能为空")
private String id;
@NotBlank(message = "动作名称不能为空")
private String actionName;
@NotBlank(message = "内容不能为空")
private String content;
private String formFactor;
private String pageOrSobjectType;
private String recordType;
private String type;
}
3.3.3 ActionOverrideQueryRequest
包路径:com.datai.tooling.domain.dto.ActionOverrideQueryRequest
类定义:
package com.datai.tooling.domain.dto;
import lombok.Data;
@Data
public class ActionOverrideQueryRequest {
private String pageOrSobjectType;
private String actionName;
}
3.3.4 ActionableListQueryRequest
包路径:com.datai.tooling.domain.dto.ActionableListQueryRequest
类定义:
package com.datai.tooling.domain.dto;
import lombok.Data;
@Data
public class ActionableListQueryRequest {
private String listType;
}
3.4 VO 设计
3.4.1 ToolingActionResult
包路径:com.datai.tooling.domain.vo.ToolingActionResult
类定义:
package com.datai.tooling.domain.vo;
import lombok.Data;
import java.util.List;
@Data
public class ToolingActionResult {
private boolean success;
private String id;
private String createdById;
private String createdBy;
private String createdDate;
private String lastModifiedById;
private String lastModifiedBy;
private String lastModifiedDate;
private List<Error> errors;
}
3.4.2 ActionOverrideVO
包路径:com.datai.tooling.domain.vo.ActionOverrideVO
类定义:
package com.datai.tooling.domain.vo;
import lombok.Data;
import java.util.Calendar;
@Data
public class ActionOverrideVO {
private String id;
private String actionName;
private String content;
private String formFactor;
private String pageOrSobjectType;
private String recordType;
private String type;
private String createdById;
private String createdBy;
private Calendar createdDate;
private String lastModifiedById;
private String lastModifiedBy;
private Calendar lastModifiedDate;
private String systemModstamp;
}
3.4.3 ActionableListVO
包路径:com.datai.tooling.domain.vo.ActionableListVO
类定义:
package com.datai.tooling.domain.vo;
import lombok.Data;
@Data
public class ActionableListVO {
private String id;
private String name;
private String type;
private String sourceType;
}
4. 接口设计
4.1 Service 接口
4.1.1 IToolingActionAutomationService
包路径:com.datai.tooling.service.IToolingActionAutomationService
接口定义:
package com.datai.tooling.service;
import com.datai.tooling.domain.dto.ActionOverrideRequest;
import com.datai.tooling.domain.dto.ActionOverrideUpdateRequest;
import com.datai.tooling.domain.dto.ActionOverrideQueryRequest;
import com.datai.tooling.domain.dto.ActionableListQueryRequest;
import com.datai.tooling.domain.vo.ToolingActionResult;
import com.datai.tooling.domain.vo.ActionOverrideVO;
import com.datai.tooling.domain.vo.ActionableListVO;
import java.util.List;
public interface IToolingActionAutomationService {
ToolingActionResult createActionOverride(ActionOverrideRequest request);
ToolingActionResult updateActionOverride(ActionOverrideUpdateRequest request);
ToolingActionResult deleteActionOverride(String id);
List<ActionOverrideVO> queryActionOverrides(String pageOrSobjectType, String actionName);
List<ActionableListVO> queryActionableLists(String listType);
List<?> getActionOverrideTypes();
List<?> getActionSubtypes();
List<?> getActionableListTypes();
List<?> getActionableListSourceTypes();
List<?> getActionTaskAssignedToTypes();
List<?> getActionHttpMethods();
List<?> getActionEmailSenderTypes();
}
4.2 Controller 接口
4.2.1 ToolingActionAutomationController
包路径:com.datai.tooling.controller.ToolingActionAutomationController
接口定义:
package com.datai.tooling.controller;
import com.datai.common.core.domain.AjaxResult;
import com.datai.common.core.page.TableDataInfo;
import com.datai.tooling.domain.dto.ActionOverrideRequest;
import com.datai.tooling.domain.dto.ActionOverrideUpdateRequest;
import com.datai.tooling.domain.dto.ActionOverrideQueryRequest;
import com.datai.tooling.domain.dto.ActionableListQueryRequest;
import com.datai.tooling.domain.vo.ToolingActionResult;
import com.datai.tooling.domain.vo.ActionOverrideVO;
import com.datai.tooling.domain.vo.ActionableListVO;
import com.datai.tooling.service.IToolingActionAutomationService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Api(tags = "Tooling API - 动作和自动化功能")
@RestController
@RequestMapping("/salesforce/tooling/action-automation")
public class ToolingActionAutomationController {
@Autowired
private IToolingActionAutomationService toolingActionAutomationService;
@ApiOperation("创建动作覆盖")
@PostMapping("/action-override/create")
public AjaxResult createActionOverride(@RequestBody ActionOverrideRequest request) {
return AjaxResult.success(toolingActionAutomationService.createActionOverride(request));
}
@ApiOperation("更新动作覆盖")
@PutMapping("/action-override/update")
public AjaxResult updateActionOverride(@RequestBody ActionOverrideUpdateRequest request) {
return AjaxResult.success(toolingActionAutomationService.updateActionOverride(request));
}
@ApiOperation("删除动作覆盖")
@DeleteMapping("/action-override/delete")
public AjaxResult deleteActionOverride(@RequestParam String id) {
return AjaxResult.success(toolingActionAutomationService.deleteActionOverride(id));
}
@ApiOperation("查询动作覆盖")
@GetMapping("/action-override/query")
public TableDataInfo queryActionOverrides(
@RequestParam(required = false) String pageOrSobjectType,
@RequestParam(required = false) String actionName) {
List<ActionOverrideVO> list = toolingActionAutomationService.queryActionOverrides(pageOrSobjectType, actionName);
return getDataTable(list);
}
@ApiOperation("查询可操作列表")
@GetMapping("/actionable-list/query")
public TableDataInfo queryActionableLists(@RequestParam(required = false) String listType) {
List<?> list = toolingActionAutomationService.queryActionableLists(listType);
return getDataTable(list);
}
@ApiOperation("获取动作覆盖类型")
@GetMapping("/action-override/types")
public TableDataInfo getActionOverrideTypes() {
List<?> list = toolingActionAutomationService.getActionOverrideTypes();
return getDataTable(list);
}
@ApiOperation("获取动作子类型")
@GetMapping("/action/subtypes")
public TableDataInfo getActionSubtypes() {
List<?> list = toolingActionAutomationService.getActionSubtypes();
return getDataTable(list);
}
@ApiOperation("获取可操作列表类型")
@GetMapping("/actionable-list/types")
public TableDataInfo getActionableListTypes() {
List<?> list = toolingActionAutomationService.getActionableListTypes();
return getDataTable(list);
}
@ApiOperation("获取可操作列表源类型")
@GetMapping("/actionable-list/source-types")
public TableDataInfo getActionableListSourceTypes() {
List<?> list = toolingActionAutomationService.getActionableListSourceTypes();
return getDataTable(list);
}
@ApiOperation("获取动作任务分配类型")
@GetMapping("/action-task/assigned-to-types")
public TableDataInfo getActionTaskAssignedToTypes() {
List<?> list = toolingActionAutomationService.getActionTaskAssignedToTypes();
return getDataTable(list);
}
@ApiOperation("获取动作 HTTP 方法")
@GetMapping("/action/http-methods")
public TableDataInfo getActionHttpMethods() {
List<?> list = toolingActionAutomationService.getActionHttpMethods();
return getDataTable(list);
}
@ApiOperation("获取动作邮件发送者类型")
@GetMapping("/action/email-sender-types")
public TableDataInfo getActionEmailSenderTypes() {
List<?> list = toolingActionAutomationService.getActionEmailSenderTypes();
return getDataTable(list);
}
}
4.3 Mapper 接口
4.3.1 ToolingActionAutomationLogMapper
包路径:com.datai.tooling.mapper.ToolingActionAutomationLogMapper
接口定义:
package com.datai.tooling.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.datai.tooling.domain.entity.ToolingActionAutomationLog;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface ToolingActionAutomationLogMapper extends BaseMapper<ToolingActionAutomationLog> {
}
5. 错误码定义
5.1 ToolingActionErrCode
包路径:com.datai.tooling.enums.ToolingActionErrCode
枚举定义:
package com.datai.tooling.enums;
import lombok.Getter;
@Getter
public enum ToolingActionErrCode {
TOOLING_ACTION_001("TOOLING_ACTION_001", "Session 无效"),
TOOLING_ACTION_002("TOOLING_ACTION_002", "创建失败"),
TOOLING_ACTION_003("TOOLING_ACTION_003", "更新失败"),
TOOLING_ACTION_004("TOOLING_ACTION_004", "删除失败"),
TOOLING_ACTION_005("TOOLING_ACTION_005", "查询失败"),
TOOLING_ACTION_006("TOOLING_ACTION_006", "网络超时"),
TOOLING_ACTION_007("TOOLING_ACTION_007", "权限不足"),
TOOLING_ACTION_008("TOOLING_ACTION_008", "记录不存在"),
TOOLING_ACTION_009("TOOLING_ACTION_009", "未登录");
private final String code;
private final String message;
ToolingActionErrCode(String code, String message) {
this.code = code;
this.message = message;
}
}
6. 代码规范
6.1 命名规范
| 类型 | 命名规范 | 示例 |
|---|---|---|
| 类名 | 大驼峰 | ToolingActionAutomationServiceImpl |
| 方法名 | 小驼峰 | createActionOverride |
| 变量名 | 小驼峰 | actionOverride |
| 常量名 | 全大写下划线分隔 | OPERATION_TYPE_CREATE |
| 包名 | 全小写 | com.datai.tooling.service |
6.2 注释规范
- 类注释:包含类功能描述、作者、创建时间
- 方法注释:包含功能描述、参数说明、返回值说明、异常说明
- 字段注释:包含字段用途说明
6.3 导入规范
- 按照以下顺序导入:
- Java 标准库
- Jakarta 注解
- 第三方库
- 项目内部类
6.4 包结构
com.datai.tooling
├── controller # Controller 层
├── service # Service 层
│ └── impl # Service 实现层
├── domain # 领域对象
│ ├── dto # 数据传输对象
│ ├── vo # 视图对象
│ └── entity # 实体类
├── mapper # Mapper 层
├── enums # 枚举类
├── factory # 工厂类
└── exception # 异常类
7. 测试要求
7.1 单元测试
- 覆盖率要求:≥ 80%
- 测试框架:JUnit 5 + Mockito
- 测试场景:
- 正常场景测试
- 异常场景测试
- 边界条件测试
- 并发场景测试
7.2 集成测试
- 测试目标:验证各层之间的交互
- 测试场景:
- Controller → Service → Factory → API
- Service → Mapper → Database
- 异常处理流程
8. 部署要求
8.1 环境要求
- JDK:Java 22
- 数据库:MySQL 8.0+
- 应用服务器:Spring Boot 内置 Tomcat
8.2 配置要求
- Session 配置:配置 SessionManager 的数据源
- 日志配置:配置日志级别和输出路径
- 线程池配置:配置异步日志记录线程池
9. 性能要求
9.1 响应时间
- 创建动作覆盖:< 2s
- 更新动作覆盖:< 2s
- 删除动作覆盖:< 1s
- 查询动作覆盖:< 1s
- 查询可操作列表:< 1s
- 获取枚举类型:< 1s
9.2 并发支持
- 并发用户数:≥ 100
- QPS:≥ 50
10. 安全要求
10.1 认证授权
- 使用
datai-salesforce-auth模块的 SessionManager 进行认证 - 所有接口都需要有效的 Session ID
10.2 数据安全
- 敏感数据加密存储
- 操作日志记录用户行为
- 支持 SQL 注入防护
11. 扩展性设计
11.1 预留扩展点
- 新增动作类型:通过扩展 Service 接口和 Controller 接口
- 新增查询条件:通过扩展 DTO 和 VO 类
- 新增日志字段:通过扩展数据库表和实体类
11.2 插件化设计
- 支持通过插件方式扩展动作和自动化功能
- 提供统一的插件接口规范
12. 注意事项
- 连接复用:必须使用 ToolingConnectionFactory 获取连接,避免重复创建
- 异步日志:操作日志必须异步记录,不影响主流程性能
- 异常处理:必须统一使用 datai-salesforce-common 模块的异常体系
- 参数校验:所有入参必须使用 Jakarta Validation 进行校验
- 事务管理:数据库操作必须使用 Spring 事务管理
- 日志记录:关键操作必须记录应用日志
- 错误码:所有错误必须使用 ToolingActionErrCode 枚举定义
- RESTful 规范:API 接口必须符合 RESTful 规范
- 文档同步:代码变更后必须同步更新相关文档
- 测试覆盖:代码变更后必须运行测试并确保通过
- 代码审查:代码提交前必须经过代码审查
- 版本控制:使用 Git 进行版本控制,遵循分支管理策略
- 性能监控:关键接口必须进行性能监控
- 安全审计:定期进行安全审计,及时修复安全漏洞
- 数据备份:定期备份操作日志数据