fix: return numeric api response codes

agent/payment-training-progress
chenyuan 2 weeks ago
parent bdc2bed8a6
commit dbf45e5902

@ -75,7 +75,7 @@ public class SecurityConfig {
String traceId = response.getHeader(TraceIdFilter.HEADER_NAME); String traceId = response.getHeader(TraceIdFilter.HEADER_NAME);
if (traceId == null) traceId = UUID.randomUUID().toString(); if (traceId == null) traceId = UUID.randomUUID().toString();
String message = code == ErrorCode.UNAUTHORIZED ? "未登录或登录已失效" : "无访问权限"; String message = code == ErrorCode.UNAUTHORIZED ? "未登录或登录已失效" : "无访问权限";
response.getWriter().write("{\"code\":\"" + code.name() + "\",\"message\":\"" + message response.getWriter().write("{\"code\":" + code.getCode() + ",\"message\":\"" + message
+ "\",\"data\":null,\"traceId\":\"" + traceId + "\"}"); + "\",\"data\":null,\"traceId\":\"" + traceId + "\"}");
} }
} }

@ -11,9 +11,9 @@ import java.time.Instant;
@ApiModel(description = "接口统一响应结构") @ApiModel(description = "接口统一响应结构")
@Schema(description = "接口统一响应结构") @Schema(description = "接口统一响应结构")
public class ApiResponse<T> { public class ApiResponse<T> {
@Schema(description = "业务响应码SUCCESS表示成功", example = "SUCCESS") @Schema(description = "业务响应码;与 HTTP 状态码一致", example = "200")
private final String code; private final int code;
@Schema(description = "业务响应消息", example = "success") @Schema(description = "业务响应消息", example = "操作成功")
private final String message; private final String message;
@Schema(description = "接口实际返回的业务数据") @Schema(description = "接口实际返回的业务数据")
private final T data; private final T data;
@ -22,18 +22,18 @@ public class ApiResponse<T> {
@Schema(description = "服务器生成响应的时间", example = "2026-08-05T21:00:00Z") @Schema(description = "服务器生成响应的时间", example = "2026-08-05T21:00:00Z")
private final Instant timestamp; private final Instant timestamp;
public ApiResponse(String code, String message, T data, String traceId, Instant timestamp) { public ApiResponse(int code, String message, T data, String traceId, Instant timestamp) {
this.code = code; this.code = code;
this.message = message; this.message = message;
this.data = data; this.data = data;
this.traceId = traceId; this.traceId = traceId;
this.timestamp = timestamp; this.timestamp = timestamp;
} }
public String code() { return code; } public int code() { return code; }
public String message() { return message; } public String message() { return message; }
public T data() { return data; } public T data() { return data; }
public String traceId() { return traceId; } public String traceId() { return traceId; }
public Instant timestamp() { return timestamp; } public Instant timestamp() { return timestamp; }
public static <T> ApiResponse<T> success(T data, String traceId) { return new ApiResponse<T>(ErrorCode.SUCCESS.name(), "操作成功", data, traceId, Instant.now()); } public static <T> ApiResponse<T> success(T data, String traceId) { return new ApiResponse<T>(ErrorCode.SUCCESS.getCode(), "操作成功", data, traceId, Instant.now()); }
public static <T> ApiResponse<T> failure(ErrorCode errorCode, String message, String traceId) { return new ApiResponse<T>(errorCode.name(), message, null, traceId, Instant.now()); } public static <T> ApiResponse<T> failure(ErrorCode errorCode, String message, String traceId) { return new ApiResponse<T>(errorCode.getCode(), message, null, traceId, Instant.now()); }
} }

@ -1,10 +1,20 @@
package com.yau.digitalrmb.shared.api; package com.yau.digitalrmb.shared.api;
public enum ErrorCode { public enum ErrorCode {
SUCCESS, SUCCESS(200),
VALIDATION_ERROR, VALIDATION_ERROR(400),
UNAUTHORIZED, UNAUTHORIZED(401),
FORBIDDEN, FORBIDDEN(403),
RESOURCE_NOT_FOUND, RESOURCE_NOT_FOUND(404),
INTERNAL_ERROR INTERNAL_ERROR(500);
private final int code;
ErrorCode(int code) {
this.code = code;
}
public int getCode() {
return code;
}
} }

@ -28,6 +28,7 @@ class SecurityConfigTest {
.andExpect(status().isUnauthorized()) .andExpect(status().isUnauthorized())
.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
.andExpect(content().encoding(StandardCharsets.UTF_8)) .andExpect(content().encoding(StandardCharsets.UTF_8))
.andExpect(jsonPath("$.code").value(401))
.andExpect(jsonPath("$.message").value("未登录或登录已失效")); .andExpect(jsonPath("$.message").value("未登录或登录已失效"));
} }
} }

@ -20,11 +20,18 @@ class GlobalExceptionHandlerTest {
@Autowired @Autowired
private MockMvc mvc; private MockMvc mvc;
@Test
void successfulResponseUsesNumericCode() throws Exception {
mvc.perform(get("/api/v1/diagnostics/validation").param("value", "valid"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(200));
}
@Test @Test
void blankParameterReturnsStandardBadRequest() throws Exception { void blankParameterReturnsStandardBadRequest() throws Exception {
mvc.perform(get("/api/v1/diagnostics/validation").param("value", "")) mvc.perform(get("/api/v1/diagnostics/validation").param("value", ""))
.andExpect(status().isBadRequest()) .andExpect(status().isBadRequest())
.andExpect(jsonPath("$.code").value("VALIDATION_ERROR")) .andExpect(jsonPath("$.code").value(400))
.andExpect(jsonPath("$.traceId").isNotEmpty()); .andExpect(jsonPath("$.traceId").isNotEmpty());
} }
@ -32,7 +39,7 @@ class GlobalExceptionHandlerTest {
void invalidRequestBodyReturnsChineseValidationMessage() throws Exception { void invalidRequestBodyReturnsChineseValidationMessage() throws Exception {
mvc.perform(post("/api/v1/auth/login").contentType("application/json").content("{}")) mvc.perform(post("/api/v1/auth/login").contentType("application/json").content("{}"))
.andExpect(status().isBadRequest()) .andExpect(status().isBadRequest())
.andExpect(jsonPath("$.code").value("VALIDATION_ERROR")) .andExpect(jsonPath("$.code").value(400))
.andExpect(jsonPath("$.message").value("请求参数校验失败")); .andExpect(jsonPath("$.message").value("请求参数校验失败"));
} }
} }

Loading…
Cancel
Save