jsharness 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.harness/README.md +199 -0
- package/.harness/agents/code-reviewer/contract.yaml +64 -0
- package/.harness/agents/developer/contract.yaml +72 -0
- package/.harness/agents/gate-controller/contract.yaml +64 -0
- package/.harness/agents/project-manager/contract.yaml +77 -0
- package/.harness/agents/prompt-templates.md +352 -0
- package/.harness/agents/requirements-analyst/contract.yaml +64 -0
- package/.harness/agents/solution-designer/contract.yaml +75 -0
- package/.harness/agents/tester/contract.yaml +92 -0
- package/.harness/config/models.yaml +67 -0
- package/.harness/dev-map/backend/api-definition.md +131 -0
- package/.harness/dev-map/backend/auth-security.md +131 -0
- package/.harness/dev-map/backend/conventions-java.md +471 -0
- package/.harness/dev-map/backend/conventions.md +192 -0
- package/.harness/dev-map/backend/database.md +106 -0
- package/.harness/dev-map/backend/structure.md +140 -0
- package/.harness/dev-map/decisions.md +275 -0
- package/.harness/dev-map/frontend/api-integration.md +139 -0
- package/.harness/dev-map/frontend/components.md +178 -0
- package/.harness/dev-map/frontend/conventions.md +416 -0
- package/.harness/dev-map/frontend/state-management.md +170 -0
- package/.harness/dev-map/frontend/structure.md +103 -0
- package/.harness/dev-map/overview.md +267 -0
- package/.harness/docs/integration-test-plan.md +248 -0
- package/.harness/docs/team-guidelines/README.md +161 -0
- package/.harness/docs/team-guidelines/arch-team.md +811 -0
- package/.harness/docs/team-guidelines/collaboration.md +556 -0
- package/.harness/docs/team-guidelines/pm-team.md +337 -0
- package/.harness/docs/team-guidelines/qa-team.md +562 -0
- package/.harness/docs/team-guidelines/rd-team.md +714 -0
- package/.harness/docs/training-materials.md +280 -0
- package/.harness/gate/baseline.js +220 -0
- package/.harness/gate/checks/build-gates-frontend.js +152 -0
- package/.harness/gate/checks/build-gates-java.js +155 -0
- package/.harness/gate/checks/build-gates.js +119 -0
- package/.harness/gate/checks/engineering-consistency.js +138 -0
- package/.harness/gate/checks/security-quality.js +129 -0
- package/.harness/gate/checks/static-compliance.js +313 -0
- package/.harness/gate/checks/test-compliance.js +114 -0
- package/.harness/gate/index.js +315 -0
- package/.harness/mcp/config.yaml +435 -0
- package/.harness/rules/global/coding-standard.md +232 -0
- package/.harness/rules/global/commit-convention.md +165 -0
- package/.harness/rules/global/process-discipline.md +192 -0
- package/.harness/rules/global/security-baseline.md +306 -0
- package/.harness/rules/project/frontend-vue3.md +293 -0
- package/.harness/rules/project/java-backend.md +460 -0
- package/.harness/rules/project/web-specific.md +231 -0
- package/.harness/skills/build.md +192 -0
- package/.harness/skills/code-review.md +251 -0
- package/.harness/skills/docker-build.md +227 -0
- package/.harness/skills/docs-update.md +164 -0
- package/.harness/skills/java-build.md +261 -0
- package/.harness/skills/lint-check.md +482 -0
- package/.harness/skills/task-board-maintenance.md +105 -0
- package/.harness/skills/test-api.md +461 -0
- package/.harness/skills/test-e2e.md +431 -0
- package/.harness/skills/test-unit.md +649 -0
- package/.harness/skills/vue-frontend-build.md +344 -0
- package/.harness/specs/quality-feedback/implementation-guide.md +350 -0
- package/.harness/task-board.md +121 -0
- package/.harness/workflow/definition.yaml +504 -0
- package/.harness/workflow/validate.js +320 -0
- package/.harness/workflow/variants.yaml +253 -0
- package/README.md +237 -0
- package/bin/jsharness.js +53 -0
- package/lib/index.mjs +778 -0
- package/package.json +1 -0
|
@@ -0,0 +1,460 @@
|
|
|
1
|
+
# Java Spring Boot 后端开发规范 (java-backend)
|
|
2
|
+
|
|
3
|
+
> **级别**: 项目级强制 | **适用范围**: Java 后端项目
|
|
4
|
+
> **来源**: `files/java-backend-coding-standards/SKILL.md` (JSCICD 项目后端 Java 规范)
|
|
5
|
+
> **归档日期**: 2026-05-21
|
|
6
|
+
> **技术栈**: Spring Boot 3.2.12 / JDK 21 (虚拟线程) / MySQL 8.0 / Redis 5.x / MyBatis-Plus
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 1. 架构约束 — 双服务分层与依赖规则
|
|
11
|
+
|
|
12
|
+
### 1.1 双服务架构
|
|
13
|
+
|
|
14
|
+
| 服务 | 定位 | 职责 |
|
|
15
|
+
|------|------|------|
|
|
16
|
+
| `app` | 面向用户 | 用户侧功能入口 |
|
|
17
|
+
| `dashboard` | 后台管理 | 管理侧功能入口 |
|
|
18
|
+
|
|
19
|
+
两服务共享 `domain` 和 `common` 模块。
|
|
20
|
+
|
|
21
|
+
### 1.2 模块依赖链(强制方向)
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
controller → service → mapper → database
|
|
25
|
+
↑ ↑
|
|
26
|
+
└──→ common ←──┘
|
|
27
|
+
↑
|
|
28
|
+
integration(第三方集成)
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**依赖规则**:
|
|
32
|
+
- ✅ 允许: `controller → service → mapper`
|
|
33
|
+
- ❌ 禁止: controller 直接调用 mapper
|
|
34
|
+
- ❌ 禁止: 反向依赖(mapper 依赖 service)
|
|
35
|
+
- ❌ 禁止: 跨层跳跃依赖
|
|
36
|
+
|
|
37
|
+
### 1.3 Controller 职责边界
|
|
38
|
+
|
|
39
|
+
Controller 层 **只** 负责:
|
|
40
|
+
1. 路由分发(`@RequestMapping` / `@PostMapping`)
|
|
41
|
+
2. 参数校验(JSR 303 注解)
|
|
42
|
+
3. 权限校验(注解或拦截器)
|
|
43
|
+
4. 统一返回 JSON 格式
|
|
44
|
+
|
|
45
|
+
Controller **禁止**:
|
|
46
|
+
- ❌ 编写业务逻辑
|
|
47
|
+
- ❌ 直接操作数据库
|
|
48
|
+
- ❌ 处理 HTTP 请求/响应对象细节(如直接写 HttpServletResponse)
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## 2. Maven 四层模块结构与包命名
|
|
53
|
+
|
|
54
|
+
### 2.1 四层模块划分
|
|
55
|
+
|
|
56
|
+
| 模块 | 职责 | 内容 |
|
|
57
|
+
|------|------|------|
|
|
58
|
+
| `app` | 启动入口、配置类 | Application 主类、配置文件 |
|
|
59
|
+
| `domain` | 业务逻辑核心 | entity, dto, vo, service, mapper, controller |
|
|
60
|
+
| `integration` | 第三方集成 | 外部 API 客户端、消息队列生产者/消费者 |
|
|
61
|
+
| `common` | 公共工具 | 工具类、常量、枚举、异常定义、通用组件 |
|
|
62
|
+
|
|
63
|
+
### 2.2 包名规范
|
|
64
|
+
|
|
65
|
+
| 规则 | 要求 | 违规后果 |
|
|
66
|
+
|------|------|----------|
|
|
67
|
+
| 基础包名 | 必须为 `com.jieshun` | Code Review FAIL |
|
|
68
|
+
| 禁止包名 | 禁止使用 `com.jscicd` | Code Review FAIL |
|
|
69
|
+
|
|
70
|
+
### 2.3 类后缀规范(9 种标准后缀)
|
|
71
|
+
|
|
72
|
+
| 层级 | 后缀 | 示例 | 说明 |
|
|
73
|
+
|------|------|------|------|
|
|
74
|
+
| 实体 | Entity | `UserEntity` | 数据库表映射 |
|
|
75
|
+
| 数据传输对象 | DTO | `UserDTO` | 跨层数据传输 |
|
|
76
|
+
| 视图对象 | VO | `UserVO` | 向前端展示的数据 |
|
|
77
|
+
| 请求对象 | ReqVO | `UserCreateReqVO` | 接收前端请求参数 |
|
|
78
|
+
| 响应对象 | RespVO | `UserRespVO` | 返回给前端的响应数据 |
|
|
79
|
+
| 枚举 | Enum | `UserStatusEnum` | 状态码/类型码 |
|
|
80
|
+
| 服务接口 | Service | `UserService` | 业务接口定义 |
|
|
81
|
+
| 服务实现 | ServiceImpl | `UserServiceImpl` | 业务实现类 |
|
|
82
|
+
| 控制器 | Controller | `UserController` | REST API 入口 |
|
|
83
|
+
| 数据访问 | Mapper | `UserMapper` | 数据库操作接口 |
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## 3. Controller 层编码规范
|
|
88
|
+
|
|
89
|
+
### 3.1 标准注解组合
|
|
90
|
+
|
|
91
|
+
```java
|
|
92
|
+
@RestController
|
|
93
|
+
@RequestMapping("/api/v1/user")
|
|
94
|
+
@RequiredArgsConstructor
|
|
95
|
+
@Tag(name = "用户管理")
|
|
96
|
+
public class UserController {
|
|
97
|
+
|
|
98
|
+
private final UserService userService;
|
|
99
|
+
|
|
100
|
+
@PostMapping("/create")
|
|
101
|
+
@Operation(summary = "创建用户")
|
|
102
|
+
public CommonResult<UserRespVO> create(@Valid @RequestBody UserCreateReqVO reqVO) {
|
|
103
|
+
return success(userService.createUser(reqVO));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
@PostMapping("/page")
|
|
107
|
+
@Operation(summary = "分页查询用户")
|
|
108
|
+
public CommonResult<PageResult<UserRespVO>> page(@Valid UserPageReqVO reqVO) {
|
|
109
|
+
return success(userService.getUserPage(reqVO));
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### 3.2 参数校验规范
|
|
115
|
+
|
|
116
|
+
- **必须** 使用 JSR 303/349 校验注解:`@NotNull`, `@NotEmpty`, `@Size`, `@Pattern`, `@Min`, `@Max`
|
|
117
|
+
- 入参对象使用 `@Valid` 或 `@Validated` 触发级联校验
|
|
118
|
+
- HTTP 方法统一使用 `@PostMapping`(RESTful 风格但 POST 优先)
|
|
119
|
+
|
|
120
|
+
### 3.3 分层参数传递
|
|
121
|
+
|
|
122
|
+
| 规则 | 要求 | 违规后果 |
|
|
123
|
+
|------|------|----------|
|
|
124
|
+
| 入参格式 | 必须为 ReqVO 对象(经过校验的请求对象) | Code Review WARNING |
|
|
125
|
+
| 出参格式 | 封装为 RespVO 对象(不直接暴露 Entity) | Code Review WARNING |
|
|
126
|
+
| 禁止 Map | 禁止使用 Map 作为方法参数或返回值 | Code Review FAIL |
|
|
127
|
+
| 禁止 Entity | 禁止将 Entity 对象直接返回给前端 | Code Review FAIL |
|
|
128
|
+
| 统一封装 | 必须使用统一的 Result 包装类(如 `CommonResult<T>`) | Code Review WARNING |
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## 4. Service 层编码规范
|
|
133
|
+
|
|
134
|
+
### 4.1 接口与实现分离模式
|
|
135
|
+
|
|
136
|
+
```java
|
|
137
|
+
// 接口定义
|
|
138
|
+
public interface UserService {
|
|
139
|
+
Long createUser(UserCreateReqVO reqVO);
|
|
140
|
+
PageResult<UserRespVO> getUserPage(UserPageReqVO reqVO);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// 实现
|
|
144
|
+
@Service
|
|
145
|
+
@RequiredArgsConstructor
|
|
146
|
+
@Slf4j
|
|
147
|
+
public class UserServiceImpl implements UserService {
|
|
148
|
+
|
|
149
|
+
private final UserMapper userMapper;
|
|
150
|
+
private final RedisKeyConstants redisKeys;
|
|
151
|
+
|
|
152
|
+
@Override
|
|
153
|
+
@Transactional(rollbackFor = Exception.class)
|
|
154
|
+
public Long createUser(UserCreateReqVO reqVO) {
|
|
155
|
+
// 1. 参数校验与转换
|
|
156
|
+
// 2. 业务逻辑编排
|
|
157
|
+
// 3. 数据持久化
|
|
158
|
+
// 4. 返回结果
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### 4.2 Service 职责定位
|
|
164
|
+
|
|
165
|
+
Service 层负责 **业务编排**:
|
|
166
|
+
- 协调多个 Mapper 完成数据操作
|
|
167
|
+
- 协调外部服务完成集成调用
|
|
168
|
+
- 编排事务边界内的操作序列
|
|
169
|
+
|
|
170
|
+
**禁止**:
|
|
171
|
+
- ❌ 在 Service 中直接操作 HTTP 请求/响应对象
|
|
172
|
+
- ❌ 在 Service 中进行参数校验注解之外的校验逻辑(应在 Controller)
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## 5. Mapper 层与数据库规范
|
|
177
|
+
|
|
178
|
+
### 5.1 Mapper 接口定义
|
|
179
|
+
|
|
180
|
+
| 规则 | 要求 |
|
|
181
|
+
|------|------|
|
|
182
|
+
| 接口形态 | Mapper 为纯接口,**不继承 BaseMapper** |
|
|
183
|
+
| SQL 位置 | 复杂 SQL 必须写在 XML 映射文件中 |
|
|
184
|
+
| 注解限制 | 禁止使用 `@Select/@Insert/@Update/@Delete` 写复杂 SQL |
|
|
185
|
+
|
|
186
|
+
```java
|
|
187
|
+
// 正确示例
|
|
188
|
+
public interface UserMapper {
|
|
189
|
+
List<UserDO> selectList(@Param("reqVO") UserPageReqVO reqVO);
|
|
190
|
+
UserDO selectById(@Param("id") Long id);
|
|
191
|
+
void insert(@Param("entity") UserDO entity);
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### 5.2 分页查询
|
|
196
|
+
|
|
197
|
+
- 使用 MyBatis-Plus 分页拦截器自动追加 LIMIT
|
|
198
|
+
- 手动 SQL 中 **禁止** 自行写 LIMIT 子句
|
|
199
|
+
|
|
200
|
+
### 5.3 数据库设计规范
|
|
201
|
+
|
|
202
|
+
| 规则 | 要求 | 原因 |
|
|
203
|
+
|------|------|------|
|
|
204
|
+
| 字符集 | utf8mb4 | 支持完整 Unicode(含 emoji)|
|
|
205
|
+
| 外键约束 | 禁止使用 | 应用层维护引用完整性,避免性能问题 |
|
|
206
|
+
| 表结构变更 | 必须通过 ALTER 脚本执行 | 不可删除重建表 |
|
|
207
|
+
| 时间字段 | 必须使用 `LocalDateTime` | 禁止 `Date` 或 `Timestamp` |
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## 6. 错误码与异常处理体系
|
|
212
|
+
|
|
213
|
+
### 6.1 错误码段分配(7 个模块段)
|
|
214
|
+
|
|
215
|
+
| 模块 | 错误码范围 | 示例 |
|
|
216
|
+
|------|-----------|------|
|
|
217
|
+
| 用户模块 | 1000-1999 | 1001=用户不存在, 1002=密码错误 |
|
|
218
|
+
| 权限模块 | 2000-2999 | |
|
|
219
|
+
| 内容模块 | 3000-3999 | |
|
|
220
|
+
| 订单模块 | 4000-4999 | |
|
|
221
|
+
| 支付模块 | 5000-5999 | |
|
|
222
|
+
| 系统模块 | 9000-9999 | |
|
|
223
|
+
| ... | (按需扩展) | |
|
|
224
|
+
|
|
225
|
+
### 6.2 异常抛出规范
|
|
226
|
+
|
|
227
|
+
```java
|
|
228
|
+
// ✅ 正确:统一使用业务异常
|
|
229
|
+
throw new JscicdBizException(ErrorCode.USER_NOT_FOUND);
|
|
230
|
+
|
|
231
|
+
// ❌ 错误:禁止直接 throw RuntimeException
|
|
232
|
+
throw new RuntimeException("用户不存在");
|
|
233
|
+
|
|
234
|
+
// ❌ 错误:禁止返回错误码数字
|
|
235
|
+
return Result.fail(1001); // 应该用枚举常量
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### 6.3 异常分层捕获策略
|
|
239
|
+
|
|
240
|
+
| 异常类型 | 处理方式 | 全局处理器行为 |
|
|
241
|
+
|---------|----------|---------------|
|
|
242
|
+
| BusinessException | 返回业务错误信息(含错误码和消息) | 直接透传 message |
|
|
243
|
+
| SystemException | 记录日志 + 返回通用错误信息 | 隐藏内部细节 |
|
|
244
|
+
| 未预期异常 | 记录完整堆栈 + 返回安全错误信息 | 保护系统信息不外泄 |
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## 7. 日志规范
|
|
249
|
+
|
|
250
|
+
| 规则 | 要求 | 示例 |
|
|
251
|
+
|------|------|------|
|
|
252
|
+
| 占位符 | 必须使用 `{}` 占位符(SLF4J 参数化) | `log.info("用户登录 userId={}", userId)` |
|
|
253
|
+
| 禁止拼接 | 禁止字符串拼接(影响性能) | ❌ `"用户" + id + "登录"` |
|
|
254
|
+
| 单条长度 | 不超过 1KB | 大对象序列化为摘要信息 |
|
|
255
|
+
| 链路追踪 | 必须包含 `traceId` 和 `spanId` | 用于全链路追踪 |
|
|
256
|
+
| 异常保留 | catch 时必须保留异常对象 e | `log.error("描述", e)` |
|
|
257
|
+
|
|
258
|
+
```java
|
|
259
|
+
// ✅ 正确示例
|
|
260
|
+
log.info("[createUser][reqVO({})]", reqVO);
|
|
261
|
+
log.warn("[loginFail][mobile({})][reason({})]", mobile, reason);
|
|
262
|
+
log.error("[queryUser][id({})] error", id, e);
|
|
263
|
+
|
|
264
|
+
// ❌ 错误示例
|
|
265
|
+
log.info("创建用户: " + reqVO.toString()); // 字符串拼接
|
|
266
|
+
log.error("查询失败: " + e.getMessage()); // 丢失堆栈信息
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## 8. Redis 使用规范
|
|
272
|
+
|
|
273
|
+
| # | 规则 | 要求 | 违规后果 |
|
|
274
|
+
|---|------|------|----------|
|
|
275
|
+
| R-01 | 定位 | Redis 仅用于 **缓存** 用途,禁止作为持久存储 | Code Review FAIL |
|
|
276
|
+
| R-02 | TTL | 必须 设置过期时间,禁永不过期的 key | Gate FAIL |
|
|
277
|
+
| R-03 | Hash 容量 | 单个 Hash 的 field 数量 ≤ 50000 | Code Review WARNING |
|
|
278
|
+
| R-04 | Key 命名 | 统一定义到 `RedisKeyConstants` 常量类 | Code Review WARNING |
|
|
279
|
+
| R-05 | Key 格式 | `模块:业务:唯一标识`(如 `user:login:token:{userId}`) | Code Review WARNING |
|
|
280
|
+
| R-06 | 分布式锁 | 必须使用 Redisson 客户端,禁止手写 SETNX+EXPIRE | Code Review FAIL |
|
|
281
|
+
|
|
282
|
+
**RedisKeyConstants 示例**:
|
|
283
|
+
```java
|
|
284
|
+
public final class RedisKeyConstants {
|
|
285
|
+
public static final String USER_LOGIN_TOKEN = "user:login:token:%s";
|
|
286
|
+
public static final String USER_CAPTCHA = "user:captcha:%s";
|
|
287
|
+
public static final String CACHE_PREFIX = "cache:%s:%s"; // 模块:唯一标识
|
|
288
|
+
}
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
---
|
|
292
|
+
|
|
293
|
+
## 9. JDK 21 虚拟线程规范
|
|
294
|
+
|
|
295
|
+
| # | 规则 | 要求 | 原因 |
|
|
296
|
+
|---|------|------|------|
|
|
297
|
+
| VT-01 | 启用配置 | `spring.threads.virtual.enabled=true` 必须开启 | 启用虚拟线程支持 |
|
|
298
|
+
| VT-02 | 禁 synchronized | **虚拟线程中禁止使用 synchronized 关键字** | synchronized 导致 pinning(固定到平台线程),失去虚拟线程优势 |
|
|
299
|
+
| VT-03 | 替代方案 | 改用 `ReentrantLock` 替代 synchronized | ReentrantLock 不导致 pinning |
|
|
300
|
+
|
|
301
|
+
```java
|
|
302
|
+
// ✅ 正确:虚拟线程中使用 ReentrantLock
|
|
303
|
+
private final ReentrantLock lock = new ReentrantLock();
|
|
304
|
+
|
|
305
|
+
public void processWithVirtualThread() {
|
|
306
|
+
lock.lock();
|
|
307
|
+
try {
|
|
308
|
+
// 业务逻辑
|
|
309
|
+
} finally {
|
|
310
|
+
lock.unlock();
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// ❌ 错误:虚拟线程中使用 synchronized
|
|
315
|
+
public synchronized void badMethod() { // 导致 pinning!
|
|
316
|
+
// ...
|
|
317
|
+
}
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
322
|
+
## 10. 事务管理规范
|
|
323
|
+
|
|
324
|
+
| # | 规则 | 要求 | 原因 |
|
|
325
|
+
|---|------|------|------|
|
|
326
|
+
| TX-01 | 最小化 | 事务范围最小化 | 减少锁持有时间 |
|
|
327
|
+
| TX-02 | 外部调用放事务外 | 禁止在事务中进行 HTTP 调用、文件操作、消息发送 | 避免长事务 |
|
|
328
|
+
| TX-03 | 分批提交 | 批量操作每批 ≤ 500 条 | 避免长时间持锁 |
|
|
329
|
+
| TX-04 | rollbackFor | `@Transactional(rollbackFor = Exception.class)` | 确保所有异常回滚 |
|
|
330
|
+
|
|
331
|
+
```java
|
|
332
|
+
// ✅ 正确:外部调用在事务外
|
|
333
|
+
@Transactional(rollbackFor = Exception.class)
|
|
334
|
+
public Long createUser(UserCreateReqVO reqVO) {
|
|
335
|
+
// 1. DB 操作(在事务内)
|
|
336
|
+
Long userId = userMapper.insert(entity);
|
|
337
|
+
|
|
338
|
+
// 2. 返回后在外部发送消息/调用HTTP(在事务外)
|
|
339
|
+
return userId; // 调用方负责后续操作
|
|
340
|
+
}
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
---
|
|
344
|
+
|
|
345
|
+
## 11. 安全规范 — 国密 SM4 与脱敏
|
|
346
|
+
|
|
347
|
+
### 11.1 敏感数据加密存储
|
|
348
|
+
|
|
349
|
+
| 数据类型 | 加密方式 | 要求 |
|
|
350
|
+
|---------|---------|------|
|
|
351
|
+
| 手机号 | 国密 SM4 | 存储前加密,查询时解密 |
|
|
352
|
+
| 身份证号 | 国密 SM4 | 全字段加密 |
|
|
353
|
+
| 密码 | bcrypt(不可逆哈希) | cost ≥ 12 |
|
|
354
|
+
| 银行卡号 | 国密 SM4 | 仅存后4位明文,其余加密 |
|
|
355
|
+
|
|
356
|
+
**强制**: 敏感信息 **必须** 使用国密 SM4 算法加密后存库,禁止明文存储。
|
|
357
|
+
|
|
358
|
+
### 11.2 API 响应脱敏格式
|
|
359
|
+
|
|
360
|
+
| 数据类型 | 脱敏格式 | 示例 |
|
|
361
|
+
|---------|---------|------|
|
|
362
|
+
| 手机号 | 中间4位* | `138****1234` |
|
|
363
|
+
| 密码 | 返回 null 或 `******` | null |
|
|
364
|
+
| 邮箱 | @前部分脱敏 | `u***@example.com` |
|
|
365
|
+
| 身份证 | 中间* | `110***********1234` |
|
|
366
|
+
| 银行卡号 | 显示后4位 | `************5678` |
|
|
367
|
+
|
|
368
|
+
### 11.3 SQL 注入防护
|
|
369
|
+
|
|
370
|
+
| 规则 | 要求 | 违规后果 |
|
|
371
|
+
|------|------|----------|
|
|
372
|
+
| 预编译 | 必须 使用 `#{}` 预编译参数绑定 | **安全红线 FAIL** |
|
|
373
|
+
| 禁拼接 | 禁止 `${}` 直接拼接 SQL | **安全红线 FAIL** |
|
|
374
|
+
| 例外 | 动态表名等特殊场景需有白名单校验 | 必须代码审查确认 |
|
|
375
|
+
|
|
376
|
+
---
|
|
377
|
+
|
|
378
|
+
## 12. Nacos 配置规范
|
|
379
|
+
|
|
380
|
+
| 规则 | 要求 |
|
|
381
|
+
|------|------|
|
|
382
|
+
| 本地配置最小化 | 本地仅保留 Nacos 连接地址等最小必要配置 |
|
|
383
|
+
| 配置拉取 | 其他配置从 Nacos 动态拉取 |
|
|
384
|
+
| Key 格式 | camelCase 驼峰格式 |
|
|
385
|
+
| 禁 shared-configs | 避免共享过多公共配置,按需显式引入 |
|
|
386
|
+
|
|
387
|
+
---
|
|
388
|
+
|
|
389
|
+
## 13. 测试规范
|
|
390
|
+
|
|
391
|
+
| 规则 | 要求 |
|
|
392
|
+
|------|------|
|
|
393
|
+
| 测试框架 | JUnit 5 + Mockito |
|
|
394
|
+
| 测试路径 | 测试类路径对应源码目录结构 |
|
|
395
|
+
| 行覆盖率 | ≥ **80%** |
|
|
396
|
+
| 核心业务覆盖率 | ≥ **90%** |
|
|
397
|
+
| 覆盖率收集工具 | JaCoCo |
|
|
398
|
+
|
|
399
|
+
```xml
|
|
400
|
+
<!-- pom.xml JaCoCo 配置 -->
|
|
401
|
+
<plugin>
|
|
402
|
+
<groupId>org.jacoco</groupId>
|
|
403
|
+
<artifactId>jacoco-maven-plugin</artifactId>
|
|
404
|
+
<executions>
|
|
405
|
+
<execution><goals><goal>prepare-agent</goal></goals></execution>
|
|
406
|
+
<execution><id>report</id><phase>test</phase><goals><goal>report</goal></goals></execution>
|
|
407
|
+
</executions>
|
|
408
|
+
</plugin>
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
---
|
|
412
|
+
|
|
413
|
+
## 14. 后端代码审查 22 项检查清单
|
|
414
|
+
|
|
415
|
+
### 架构与分层(第 1-4 项)
|
|
416
|
+
|
|
417
|
+
| # | 检查项 | 标准 |
|
|
418
|
+
|---|--------|------|
|
|
419
|
+
| JB-01 | Controller 是否只做路由和校验 | 无业务逻辑 |
|
|
420
|
+
| JB-02 | Service 是否做业务编排 | 非 CRUD 直通 |
|
|
421
|
+
| JB-03 | Mapper 是否纯接口且 SQL 在 XML 中 | 不继承 BaseMapper,无注解 SQL |
|
|
422
|
+
| JB-04 | 模块依赖方向是否正确 | 无循环/反向/跨层跳跃依赖 |
|
|
423
|
+
|
|
424
|
+
### 命名与规范(第 5-9 项)
|
|
425
|
+
|
|
426
|
+
| # | 检查项 | 标准 |
|
|
427
|
+
|---|--------|------|
|
|
428
|
+
| JB-05 | 包名是否为 `com.jieshun` | 非 com.jscicd |
|
|
429
|
+
| JB-06 | 类后缀是否符合 9 种标准后缀 | Entity/DTO/VO/ReqVO/RespVO/Enum/ServiceImpl/Controller/Mapper |
|
|
430
|
+
| JB-07 | 是否有完整的 Javadoc 注释 | public 类必须有 |
|
|
431
|
+
| JB-08 | 方法命名是否清晰表达意图 | 动词开头,语义明确 |
|
|
432
|
+
| JB-09 | 常量是否使用 UPPER_SNAKE_CASE | 枚举值除外 |
|
|
433
|
+
|
|
434
|
+
### 参数与返回值(第 10-13 项)
|
|
435
|
+
|
|
436
|
+
| # | 检查项 | 标准 |
|
|
437
|
+
|---|--------|------|
|
|
438
|
+
| JB-10 | Controller 参数是否有 JSR303 校验注解 | @Valid/@Validated |
|
|
439
|
+
| JB-11 | 是否使用了 ReqVO/RespVO 分层传参 | 禁 Map/Entity 直通 |
|
|
440
|
+
| JB-12 | 禁止 Map 和 Entity 直接暴露 | 必须转换 |
|
|
441
|
+
| JB-13 | 返回值是否用统一 Result 封装 | CommonResult<T> |
|
|
442
|
+
|
|
443
|
+
### 数据库与 SQL(第 14-16 项)
|
|
444
|
+
|
|
445
|
+
| # | 检查项 | 标准 |
|
|
446
|
+
|---|--------|------|
|
|
447
|
+
| JB-14 | SQL 是否使用 `#{}` 预编译 | 防 SQL 注入 |
|
|
448
|
+
| JB-15 | 分页是否使用拦截器 | 非手动 LIMIT |
|
|
449
|
+
| JB-16 | 表结构变更是否有 ALTER 脚本 | 不可删重建表 |
|
|
450
|
+
|
|
451
|
+
### 安全与质量(第 17-22 项)
|
|
452
|
+
|
|
453
|
+
| # | 检查项 | 标准 |
|
|
454
|
+
|---|--------|------|
|
|
455
|
+
| JB-17 | 敏感数据是否 SM4 加密存储 | 手机号/身份证等 |
|
|
456
|
+
| JB-18 | 响应数据是否已脱敏 | 手机号/邮箱/身份证格式 |
|
|
457
|
+
| JB-19 | Redis key 是否有 TTL | 禁永不过期 |
|
|
458
|
+
| JB-20 | 日志是否使用 `{}` 参数化 | 禁字符串拼接 |
|
|
459
|
+
| JB-21 | 事务范围是否最小化 | 外部调用放事务外 |
|
|
460
|
+
| JB-22 | 虚拟线程中是否无 synchronized | 改用 ReentrantLock |
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
# Web 应用特有规则 (web-specific)
|
|
2
|
+
|
|
3
|
+
> **级别**: 必须遵守 | **适用范围**: Web 全栈项目
|
|
4
|
+
|
|
5
|
+
## 1. 前端 i18n 合规要求
|
|
6
|
+
|
|
7
|
+
### 1.1 国际化基础规范
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
// ❌ 硬编码中文字符串(无法国际化)
|
|
11
|
+
<Button>提交</Button>
|
|
12
|
+
<span>暂无数据</span>
|
|
13
|
+
alert('操作成功');
|
|
14
|
+
|
|
15
|
+
// ✅ 正确:使用 i18n 工具函数
|
|
16
|
+
<Button>{t('common.submit')}</Button>
|
|
17
|
+
<span>{t('message.noData')}</span>
|
|
18
|
+
toast.success(t('toast.operationSuccess'));
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### 1.2 i18n 文件组织结构
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
locales/
|
|
25
|
+
├── zh-CN.json # 简体中文(默认语言)
|
|
26
|
+
├── en-US.json # 英语
|
|
27
|
+
├── ja-JP.json # 日语(按需扩展)
|
|
28
|
+
└── index.ts # 导出 i18n 实例
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### 1.3 特殊情况处理
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
// ✅ 占位符插值
|
|
35
|
+
t('greeting', { name: userName }) // "你好,{{name}}"
|
|
36
|
+
|
|
37
|
+
// ✅ 复数形式
|
|
38
|
+
t('itemCount', { count: items.length }) // "{{count}} 个项目"
|
|
39
|
+
|
|
40
|
+
// ⚠️ 允许硬编码的场景(需注释说明)
|
|
41
|
+
// 技术标识符、CSS 类名、日志 key、测试数据
|
|
42
|
+
const TEST_USER_ID = 'test-user-001'; // Test fixture, no need to i18n
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 2. API 调用规范
|
|
48
|
+
|
|
49
|
+
### 2.1 统一客户端封装
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
// 所有 API 调用必须经过统一封装层,禁止直接使用 fetch/axios
|
|
53
|
+
|
|
54
|
+
// ✅ 正确:使用封装的 apiClient
|
|
55
|
+
import { apiClient } from '@/lib/api-client';
|
|
56
|
+
|
|
57
|
+
const users = await apiClient.get('/users', { params: { page: 1 } });
|
|
58
|
+
|
|
59
|
+
// 封装层应内置:
|
|
60
|
+
// - 自动附加认证 token
|
|
61
|
+
// - 统一错误处理
|
|
62
|
+
// - 请求/响应拦截器
|
|
63
|
+
// - 请求取消支持(AbortController)
|
|
64
|
+
// - 重试机制(幂等接口自动重试)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### 2.2 接口调用约定
|
|
68
|
+
|
|
69
|
+
| 约定 | 要求 |
|
|
70
|
+
|------|------|
|
|
71
|
+
| **错误处理** | 使用统一的错误边界组件或 hook |
|
|
72
|
+
| **Loading 状态** | 每次请求必须展示 loading 态 |
|
|
73
|
+
| **缓存策略** | GET 请求默认缓存(Pinia Plugin / keepAlive)|
|
|
74
|
+
| **乐观更新** | 写操作支持乐观更新(mutation)|
|
|
75
|
+
| **请求去重** | 相同请求在 pending 时不重复发送 |
|
|
76
|
+
|
|
77
|
+
### 2.3 RESTful URL 规范
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
# 资源命名:名词复数
|
|
81
|
+
GET /api/v1/users # 获取用户列表
|
|
82
|
+
GET /api/v1/users/:id # 获取单个用户
|
|
83
|
+
POST /api/v1/users # 创建用户
|
|
84
|
+
PUT /api/v1/users/:id # 全量更新
|
|
85
|
+
PATCH /api/v1/users/:id # 部分更新
|
|
86
|
+
DELETE /api/v1/users/:id # 删除用户
|
|
87
|
+
|
|
88
|
+
# 动作命名:动词
|
|
89
|
+
POST /api/v1/users/:id/activate # 激活用户
|
|
90
|
+
POST /api/v1/orders/:id/cancel # 取消订单
|
|
91
|
+
|
|
92
|
+
# 过滤/排序/分页
|
|
93
|
+
GET /api/v1/users?role=admin&page=1&pageSize=20&sort=createdAt-desc
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## 3. 前后端接口约定
|
|
99
|
+
|
|
100
|
+
### 3.1 统一响应格式
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
// 成功响应
|
|
104
|
+
interface SuccessResponse<T> {
|
|
105
|
+
code: 0;
|
|
106
|
+
data: T;
|
|
107
|
+
message: string;
|
|
108
|
+
timestamp: number;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// 错误响应
|
|
112
|
+
interface ErrorResponse {
|
|
113
|
+
code: number; // 业务错误码(非 HTTP 状态码)
|
|
114
|
+
message: string; // 可展示给用户的错误信息
|
|
115
|
+
details?: ErrorDetail[];
|
|
116
|
+
timestamp: number;
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### 3.2 业务错误码规范
|
|
121
|
+
|
|
122
|
+
| 错误码范围 | 含义 | 示例 |
|
|
123
|
+
|-----------|------|------|
|
|
124
|
+
| 0 | 成功 | - |
|
|
125
|
+
| 1xxxx | 参数错误 | 10001: 缺少必填参数 |
|
|
126
|
+
| 2xxxx | 认证/授权错误 | 20001: Token 已过期 |
|
|
127
|
+
| 3xxxx | 业务逻辑错误 | 30001: 用户名已存在 |
|
|
128
|
+
| 4xxxx | 资源错误 | 40001: 资源不存在 |
|
|
129
|
+
| 5xxxx | 第三方服务错误 | 50001: 支付网关超时 |
|
|
130
|
+
| 9xxxx | 系统内部错误 | 90001: 数据库连接失败 |
|
|
131
|
+
|
|
132
|
+
### 3.3 版本控制
|
|
133
|
+
|
|
134
|
+
- URL 中携带版本号:`/api/v1/...`
|
|
135
|
+
- 向后兼容:新增字段不影响旧版本
|
|
136
|
+
- 废弃接口保留至少 2 个大版本周期
|
|
137
|
+
- Response Header 中标注 API 版本
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## 4. 前端性能规则
|
|
142
|
+
|
|
143
|
+
### 4.1 打包体积约束
|
|
144
|
+
|
|
145
|
+
| 指标 | 限制 |
|
|
146
|
+
|------|------|
|
|
147
|
+
| 首屏 JS bundle | ≤ 200KB(gzip 后)|
|
|
148
|
+
| 单页面路由 chunk | ≤ 100KB(gzip 后)|
|
|
149
|
+
| 图片大小 | ≤ 200KB(压缩后),WebP 格式优先 |
|
|
150
|
+
| 字体文件 | ≤ 50KB(subset 后)|
|
|
151
|
+
| 总资源体积(首屏)| ≤ 1MB |
|
|
152
|
+
|
|
153
|
+
### 4.2 渲染性能
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
// ✅ 正确:大数据量列表必须虚拟滚动
|
|
157
|
+
import { useVirtualList } from '@vueuse/core';
|
|
158
|
+
const { list, containerProps, wrapperProps } = useVirtualList(items, { itemHeight: 48 });
|
|
159
|
+
|
|
160
|
+
// ✅ 正确:避免不必要的重渲染(Vue3 组件默认细粒度更新,无需额外 memo)
|
|
161
|
+
// Vue3 使用 shallowRef / triggerRef 控制深层响应式开销
|
|
162
|
+
|
|
163
|
+
// ✅ 正确:图片懒加载
|
|
164
|
+
<img loading="lazy" :src="url" :alt="description" />
|
|
165
|
+
|
|
166
|
+
// ❌ 禁止:内联大对象作为 prop(每次创建新引用)
|
|
167
|
+
<List :items="[...largeArray]" />
|
|
168
|
+
|
|
169
|
+
// ✅ 正确:computed 稳定引用
|
|
170
|
+
const items = computed(() => largeArray.map(transform));
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### 4.3 SEO 与元数据
|
|
174
|
+
|
|
175
|
+
每个公共页面必须设置:
|
|
176
|
+
|
|
177
|
+
```tsx
|
|
178
|
+
<Head>
|
|
179
|
+
<title>{pageTitle} - {siteName}</title>
|
|
180
|
+
<meta name="description" content={pageDescription} />
|
|
181
|
+
<meta property="og:title" content={pageTitle} />
|
|
182
|
+
<meta property="og:description" content={pageDescription} />
|
|
183
|
+
<link rel="canonical" href={canonicalUrl} />
|
|
184
|
+
</Head>
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## 5. 响应式设计规则
|
|
190
|
+
|
|
191
|
+
### 断点标准(Tailwind CSS)
|
|
192
|
+
|
|
193
|
+
| 断点名称 | 最小宽度 | 设备 |
|
|
194
|
+
|----------|---------|------|
|
|
195
|
+
| `sm` | 640px | 大屏手机 |
|
|
196
|
+
| `md` | 768px | 平板竖屏 |
|
|
197
|
+
| `lg` | 1024px | 平板横屏/小笔记本 |
|
|
198
|
+
| `xl` | 1280px | 桌面显示器 |
|
|
199
|
+
| `2xl` | 1536px | 大屏桌面 |
|
|
200
|
+
|
|
201
|
+
### 设计原则
|
|
202
|
+
|
|
203
|
+
- **Mobile First**:默认样式适配移动端,媒体查询向上扩展
|
|
204
|
+
- **触控友好**:点击区域最小 44×44px
|
|
205
|
+
- **字体缩放**:使用 `rem` 单位,尊重系统字号偏好设置
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## 6. 浏览器兼容性
|
|
210
|
+
|
|
211
|
+
| 目标浏览器 | 最低版本 |
|
|
212
|
+
|-----------|---------|
|
|
213
|
+
| Chrome | 最近 2 个主版本 |
|
|
214
|
+
| Firefox | 最近 2 个主版本 |
|
|
215
|
+
| Safari | 最近 2 个主版本 |
|
|
216
|
+
| Edge | 最近 2 个主版本 |
|
|
217
|
+
| IE | **不支持**(明确声明) |
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## 7. Web 安全专项(补充 security-baseline)
|
|
222
|
+
|
|
223
|
+
| 检查项 | 要求 |
|
|
224
|
+
|--------|------|
|
|
225
|
+
| CSP 策略 | 生产环境启用 Content-Security-Policy |
|
|
226
|
+
| X-Frame-Options | DENY 或 SAMEORIGIN |
|
|
227
|
+
| X-Content-Type-Options | nosniff |
|
|
228
|
+
| Referrer-Policy | strict-origin-when-cross-origin |
|
|
229
|
+
| Permissions-Policy | 限制摄像头/麦克风/地理位置等 |
|
|
230
|
+
| CORS | 明确指定允许的 Origin,避免 `*` |
|
|
231
|
+
| Cookie 安全 | Secure; HttpOnly; SameSite=Strict(生产环境)|
|