Initial commit
This commit is contained in:
154
后端架构设计/11-通用基础设施-part1-响应与异常.md
Normal file
154
后端架构设计/11-通用基础设施-part1-响应与异常.md
Normal file
@@ -0,0 +1,154 @@
|
||||
# 通用基础设施开发文档 - Part 1(响应封装 + 异常处理)
|
||||
|
||||
---
|
||||
|
||||
## 一、统一响应封装 Result.java
|
||||
|
||||
```java
|
||||
package com.openclaw.common;
|
||||
|
||||
import lombok.Data;
|
||||
import java.time.Instant;
|
||||
|
||||
@Data
|
||||
public class Result<T> {
|
||||
private int code;
|
||||
private String message;
|
||||
private T data;
|
||||
private long timestamp;
|
||||
|
||||
public static <T> Result<T> ok(T data) {
|
||||
Result<T> r = new Result<>();
|
||||
r.code = 200; r.message = "success";
|
||||
r.data = data;
|
||||
r.timestamp = Instant.now().toEpochMilli();
|
||||
return r;
|
||||
}
|
||||
|
||||
public static <T> Result<T> ok() { return ok(null); }
|
||||
|
||||
public static <T> Result<T> fail(int code, String message) {
|
||||
Result<T> r = new Result<>();
|
||||
r.code = code; r.message = message;
|
||||
r.timestamp = Instant.now().toEpochMilli();
|
||||
return r;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 二、ErrorCode.java
|
||||
|
||||
```java
|
||||
package com.openclaw.constant;
|
||||
|
||||
public interface ErrorCode {
|
||||
// ---------- 通用 ----------
|
||||
int[] PARAM_ERROR = {400, "请求参数错误"};
|
||||
int[] UNAUTHORIZED = {401, "请先登录"};
|
||||
int[] FORBIDDEN = {403, "无权限"};
|
||||
int[] NOT_FOUND = {404, "资源不存在"};
|
||||
|
||||
// ---------- 用户 1xxx ----------
|
||||
int[] USER_NOT_FOUND = {1001, "用户不存在"};
|
||||
int[] WRONG_PASSWORD = {1002, "密码错误"};
|
||||
int[] PHONE_REGISTERED = {1003, "手机号已注册"};
|
||||
int[] USER_BANNED = {1004, "账号已被封禁"};
|
||||
|
||||
// ---------- Skill 2xxx ----------
|
||||
int[] SKILL_NOT_FOUND = {2001, "Skill不存在"};
|
||||
int[] SKILL_ALREADY_OWNED = {2002, "已拥有该Skill"};
|
||||
int[] SKILL_STATUS_ERROR = {2003, "Skill状态不允许此操作"};
|
||||
|
||||
// ---------- 积分 3xxx ----------
|
||||
int[] POINTS_NOT_ENOUGH = {3001, "积分不足"};
|
||||
int[] POINTS_RULE_NOT_FOUND = {3002, "积分规则不存在"};
|
||||
|
||||
// ---------- 订单 4xxx ----------
|
||||
int[] ORDER_NOT_FOUND = {4001, "订单不存在"};
|
||||
int[] ORDER_STATUS_ERROR = {4002, "订单状态不允许此操作"};
|
||||
|
||||
// ---------- 退款 5xxx ----------
|
||||
int[] REFUND_NOT_FOUND = {5001, "退款单不存在"};
|
||||
int[] REFUND_STATUS_ERROR = {5002, "退款状态不允许此操作"};
|
||||
|
||||
// ---------- 邀请 6xxx ----------
|
||||
int[] INVITE_CODE_INVALID = {6001, "邀请码无效"};
|
||||
int[] INVITE_SELF_NOT_ALLOWED = {6002, "不能邀请自己"};
|
||||
int[] INVITE_CODE_EXHAUSTED = {6003, "邀请码已达使用上限"};
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、BusinessException.java
|
||||
|
||||
```java
|
||||
package com.openclaw.exception;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class BusinessException extends RuntimeException {
|
||||
private final int code;
|
||||
private final String msg;
|
||||
|
||||
public BusinessException(int code, String msg) {
|
||||
super(msg);
|
||||
this.code = code;
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
/** 接受 int[] {code, message} 格式的 ErrorCode 常量 */
|
||||
public BusinessException(int[] errorCode) {
|
||||
this(errorCode[0], String.valueOf(errorCode[1]));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、GlobalExceptionHandler.java
|
||||
|
||||
```java
|
||||
package com.openclaw.exception;
|
||||
|
||||
import com.openclaw.common.Result;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.validation.FieldError;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@Slf4j
|
||||
@RestControllerAdvice
|
||||
public class GlobalExceptionHandler {
|
||||
|
||||
@ExceptionHandler(BusinessException.class)
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
public Result<?> handleBusiness(BusinessException e) {
|
||||
return Result.fail(e.getCode(), e.getMsg());
|
||||
}
|
||||
|
||||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public Result<?> handleValidation(MethodArgumentNotValidException e) {
|
||||
String msg = e.getBindingResult().getFieldErrors().stream()
|
||||
.findFirst()
|
||||
.map(FieldError::getDefaultMessage)
|
||||
.orElse("参数校验失败");
|
||||
return Result.fail(400, msg);
|
||||
}
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
public Result<?> handleUnknown(Exception e) {
|
||||
log.error("未知异常", e);
|
||||
return Result.fail(500, "服务器内部错误");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
**文档版本**:v1.0 | **创建日期**:2026-03-16
|
||||
Reference in New Issue
Block a user