|
|
# 后端中文提示与 UTF-8 响应实施计划
|
|
|
|
|
|
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
|
|
|
|
**Goal:** 所有 API 对外提示使用中文,并以 UTF-8 JSON 返回,避免 Swagger 和前端出现乱码。
|
|
|
|
|
|
**Architecture:** 通过 `ApiResponse` 统一成功提示,通过 Spring Security 的异常写入器统一鉴权提示,通过业务服务中文化可回传的校验信息。应用配置与响应写入器共同确保 UTF-8;错误码保持不变。
|
|
|
|
|
|
**Tech Stack:** Java 8、Spring Boot 2.7、Spring Security、Springdoc OpenAPI、JUnit 5、MockMvc。
|
|
|
|
|
|
## Global Constraints
|
|
|
|
|
|
- 保持现有 `ErrorCode` 枚举值不变。
|
|
|
- 所有面向前端的 `message` 必须为中文。
|
|
|
- JSON 响应必须使用 UTF-8。
|
|
|
- 保留业务校验的具体中文原因;框架参数校验使用统一中文提示。
|
|
|
|
|
|
---
|
|
|
|
|
|
### Task 1: 统一响应和安全异常提示
|
|
|
|
|
|
**Files:**
|
|
|
- Modify: `src/main/java/com/yau/digitalrmb/shared/api/ApiResponse.java`
|
|
|
- Modify: `src/main/java/com/yau/digitalrmb/security/config/SecurityConfig.java`
|
|
|
- Modify: `src/main/resources/application.yml`
|
|
|
- Test: `src/test/java/com/yau/digitalrmb/security/SecurityConfigTest.java`
|
|
|
|
|
|
**Interfaces:**
|
|
|
- Produces: 成功响应的 `message` 为“操作成功”;401、403 响应分别为“未登录或登录已失效”“无访问权限”。
|
|
|
- Produces: 安全异常响应头为 `application/json;charset=UTF-8`。
|
|
|
|
|
|
- [ ] **Step 1: 写失败测试**
|
|
|
|
|
|
```java
|
|
|
mockMvc.perform(get("/api/v1/commercial-banks/issuance/inventory"))
|
|
|
.andExpect(status().isUnauthorized())
|
|
|
.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
|
|
|
.andExpect(content().encoding(StandardCharsets.UTF_8))
|
|
|
.andExpect(jsonPath("$.message").value("未登录或登录已失效"));
|
|
|
```
|
|
|
|
|
|
- [ ] **Step 2: 运行失败测试**
|
|
|
|
|
|
Run: `mvn -B -Dtest=SecurityConfigTest test`
|
|
|
|
|
|
Expected: FAIL,当前消息为 `UNAUTHORIZED` 或响应编码不是 UTF-8。
|
|
|
|
|
|
- [ ] **Step 3: 最小实现**
|
|
|
|
|
|
```java
|
|
|
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
|
|
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
|
|
|
response.getWriter().write(... "未登录或登录已失效" ...);
|
|
|
```
|
|
|
|
|
|
并将 `ApiResponse.success` 的消息改为“操作成功”,在 `application.yml` 添加:
|
|
|
|
|
|
```yaml
|
|
|
server:
|
|
|
servlet:
|
|
|
encoding:
|
|
|
charset: UTF-8
|
|
|
enabled: true
|
|
|
force: true
|
|
|
```
|
|
|
|
|
|
- [ ] **Step 4: 运行测试验证通过**
|
|
|
|
|
|
Run: `mvn -B -Dtest=SecurityConfigTest test`
|
|
|
|
|
|
Expected: PASS。
|
|
|
|
|
|
- [ ] **Step 5: 提交**
|
|
|
|
|
|
```bash
|
|
|
git add src/main/java/com/yau/digitalrmb/shared/api/ApiResponse.java src/main/java/com/yau/digitalrmb/security/config/SecurityConfig.java src/main/resources/application.yml src/test/java/com/yau/digitalrmb/security/SecurityConfigTest.java
|
|
|
git commit -m "fix: return Chinese security messages in UTF-8"
|
|
|
```
|
|
|
|
|
|
### Task 2: 中文化发行模块对外业务提示
|
|
|
|
|
|
**Files:**
|
|
|
- Modify: `src/main/java/com/yau/digitalrmb/issuance/application/service/DenominationPlanService.java`
|
|
|
- Modify: `src/main/java/com/yau/digitalrmb/issuance/application/service/CommercialBankIssuanceApplicationService.java`
|
|
|
- Modify: `src/main/java/com/yau/digitalrmb/issuance/application/service/CentralBankIssuanceQueryService.java`
|
|
|
- Modify: `src/main/java/com/yau/digitalrmb/issuance/interfaces/rest/CommercialBankIssuanceController.java`
|
|
|
- Modify: `src/main/java/com/yau/digitalrmb/security/interfaces/AuthController.java`
|
|
|
- Test: `src/test/java/com/yau/digitalrmb/issuance/interfaces/rest/IssuanceControllerTest.java`
|
|
|
|
|
|
**Interfaces:**
|
|
|
- Produces: 面额总额不一致时 `VALIDATION_ERROR` 消息为“各面额小计之和必须等于申请总金额”。
|
|
|
- Produces: 当前用户审计声明缺失或非法时返回中文未授权提示。
|
|
|
|
|
|
- [ ] **Step 1: 写失败测试**
|
|
|
|
|
|
```java
|
|
|
mockMvc.perform(post("/api/v1/commercial-banks/issuance/denomination-plan/validate")
|
|
|
.with(issuanceJwt()).contentType(MediaType.APPLICATION_JSON)
|
|
|
.content(invalidPlanJson))
|
|
|
.andExpect(jsonPath("$.code").value("VALIDATION_ERROR"))
|
|
|
.andExpect(jsonPath("$.message").value("各面额小计之和必须等于申请总金额"));
|
|
|
```
|
|
|
|
|
|
- [ ] **Step 2: 运行失败测试**
|
|
|
|
|
|
Run: `mvn -B -Dtest=IssuanceControllerTest test`
|
|
|
|
|
|
Expected: FAIL,当前消息为 `denomination total must equal totalAmount`。
|
|
|
|
|
|
- [ ] **Step 3: 最小实现**
|
|
|
|
|
|
将所有会经 `BusinessException` 或校验转换返回前端的英文文本替换为对应中文,包括申请不存在、申请 ID 为空、库存配置不存在、JWT 缺失 `userId` 或 `preferred_username`、金额和面额规则。
|
|
|
|
|
|
- [ ] **Step 4: 运行测试验证通过**
|
|
|
|
|
|
Run: `mvn -B -Dtest=IssuanceControllerTest test`
|
|
|
|
|
|
Expected: PASS。
|
|
|
|
|
|
- [ ] **Step 5: 提交**
|
|
|
|
|
|
```bash
|
|
|
git add src/main/java/com/yau/digitalrmb/issuance src/main/java/com/yau/digitalrmb/security/interfaces/AuthController.java src/test/java/com/yau/digitalrmb/issuance/interfaces/rest/IssuanceControllerTest.java
|
|
|
git commit -m "fix: translate issuance API messages to Chinese"
|
|
|
```
|
|
|
|
|
|
### Task 3: 统一全局校验和验证
|
|
|
|
|
|
**Files:**
|
|
|
- Modify: `src/main/java/com/yau/digitalrmb/shared/web/GlobalExceptionHandler.java`
|
|
|
- Modify: `src/main/java/com/yau/digitalrmb/platformintegration/application/PlatformTokenVerifier.java`
|
|
|
- Test: `src/test/java/com/yau/digitalrmb/shared/GlobalExceptionHandlerTest.java`
|
|
|
|
|
|
**Interfaces:**
|
|
|
- Produces: 框架参数校验统一返回“请求参数校验失败”。
|
|
|
- Produces: 无效平台令牌返回“平台登录凭据无效”。
|
|
|
|
|
|
- [ ] **Step 1: 写失败测试**
|
|
|
|
|
|
```java
|
|
|
mockMvc.perform(post("/api/v1/auth/login").contentType(MediaType.APPLICATION_JSON).content("{}"))
|
|
|
.andExpect(jsonPath("$.code").value("VALIDATION_ERROR"))
|
|
|
.andExpect(jsonPath("$.message").value("请求参数校验失败"));
|
|
|
```
|
|
|
|
|
|
- [ ] **Step 2: 运行失败测试**
|
|
|
|
|
|
Run: `mvn -B -Dtest=GlobalExceptionHandlerTest test`
|
|
|
|
|
|
Expected: FAIL,当前返回框架英文校验文本。
|
|
|
|
|
|
- [ ] **Step 3: 最小实现**
|
|
|
|
|
|
```java
|
|
|
return ApiResponse.failure(ErrorCode.VALIDATION_ERROR, "请求参数校验失败", traceId());
|
|
|
```
|
|
|
|
|
|
并把平台令牌异常内部消息改为中文,避免任何异常链的英文文本进入 API 响应。
|
|
|
|
|
|
- [ ] **Step 4: 执行完整验证**
|
|
|
|
|
|
Run: `mvn -B test`
|
|
|
|
|
|
Expected: 全部测试通过;新增中文/UTF-8 断言通过。
|
|
|
|
|
|
- [ ] **Step 5: 重启与人工验证**
|
|
|
|
|
|
Run: `mvn -B package -DskipTests`,重启本地 `8081` 后端;在 Swagger 调用面额校验接口,确认响应体中文且响应头为 UTF-8。
|
|
|
|
|
|
- [ ] **Step 6: 提交**
|
|
|
|
|
|
```bash
|
|
|
git add src/main/java/com/yau/digitalrmb/shared/web/GlobalExceptionHandler.java src/main/java/com/yau/digitalrmb/platformintegration/application/PlatformTokenVerifier.java src/test/java/com/yau/digitalrmb/shared/GlobalExceptionHandlerTest.java
|
|
|
git commit -m "fix: standardize Chinese validation messages"
|
|
|
```
|