Commit 75fa00a66de32b6ccbe3abb26ef6d630ff090105

Authored by zichun
1 parent 199a3381

feat(usr): common Result/BizException/AuthErrorCode/GlobalExceptionHandler REQ-USR-004

- Result<T>: ok()/fail() with code/message/data/timestamp
- BizException: carries int code
- AuthErrorCode: 40100/40101/40102/40103 constants
- GlobalExceptionHandler: BizException, validation, fallback 99000
backend/src/main/java/com/example/erp/common/constants/AuthErrorCode.java 0 → 100644
  1 +package com.example.erp.common.constants;
  2 +
  3 +public final class AuthErrorCode {
  4 +
  5 + public static final int USERNAME_OR_PASSWORD_ERROR = 40100;
  6 + public static final int ACCOUNT_DISABLED = 40101;
  7 + public static final int ACCOUNT_LOCKED = 40102;
  8 + public static final int REFRESH_TOKEN_INVALID = 40103;
  9 +
  10 + private AuthErrorCode() {}
  11 +}
... ...
backend/src/main/java/com/example/erp/common/exception/BizException.java 0 → 100644
  1 +package com.example.erp.common.exception;
  2 +
  3 +import lombok.Getter;
  4 +
  5 +@Getter
  6 +public class BizException extends RuntimeException {
  7 +
  8 + private final int code;
  9 +
  10 + public BizException(int code, String message) {
  11 + super(message);
  12 + this.code = code;
  13 + }
  14 +}
... ...
backend/src/main/java/com/example/erp/common/exception/GlobalExceptionHandler.java 0 → 100644
  1 +package com.example.erp.common.exception;
  2 +
  3 +import com.example.erp.common.response.Result;
  4 +import lombok.extern.slf4j.Slf4j;
  5 +import org.springframework.http.HttpStatus;
  6 +import org.springframework.validation.FieldError;
  7 +import org.springframework.web.bind.MethodArgumentNotValidException;
  8 +import org.springframework.web.bind.annotation.ExceptionHandler;
  9 +import org.springframework.web.bind.annotation.ResponseStatus;
  10 +import org.springframework.web.bind.annotation.RestControllerAdvice;
  11 +
  12 +@Slf4j
  13 +@RestControllerAdvice
  14 +public class GlobalExceptionHandler {
  15 +
  16 + @ExceptionHandler(BizException.class)
  17 + public Result<Void> handleBizException(BizException e) {
  18 + return Result.fail(e.getCode(), e.getMessage());
  19 + }
  20 +
  21 + @ExceptionHandler(MethodArgumentNotValidException.class)
  22 + public Result<Void> handleValidation(MethodArgumentNotValidException e) {
  23 + FieldError fe = e.getBindingResult().getFieldErrors().stream().findFirst().orElse(null);
  24 + String msg = fe != null ? fe.getDefaultMessage() : "参数校验失败";
  25 + return Result.fail(40001, msg);
  26 + }
  27 +
  28 + @ExceptionHandler(Exception.class)
  29 + public Result<Void> handleException(Exception e) {
  30 + log.error("未处理异常", e);
  31 + return Result.fail(99000, "系统内部错误");
  32 + }
  33 +}
... ...
backend/src/main/java/com/example/erp/common/response/Result.java 0 → 100644
  1 +package com.example.erp.common.response;
  2 +
  3 +import lombok.Getter;
  4 +
  5 +@Getter
  6 +public class Result<T> {
  7 +
  8 + private final int code;
  9 + private final String message;
  10 + private final T data;
  11 + private final long timestamp;
  12 +
  13 + private Result(int code, String message, T data) {
  14 + this.code = code;
  15 + this.message = message;
  16 + this.data = data;
  17 + this.timestamp = System.currentTimeMillis();
  18 + }
  19 +
  20 + public static <T> Result<T> ok(T data) {
  21 + return new Result<>(200, "操作成功", data);
  22 + }
  23 +
  24 + public static <T> Result<T> fail(int code, String message) {
  25 + return new Result<>(code, message, null);
  26 + }
  27 +}
... ...
backend/src/test/java/com/example/erp/common/ResultTest.java 0 → 100644
  1 +package com.example.erp.common;
  2 +
  3 +import com.example.erp.common.response.Result;
  4 +import org.junit.jupiter.api.Test;
  5 +
  6 +import static org.junit.jupiter.api.Assertions.*;
  7 +
  8 +class ResultTest {
  9 +
  10 + @Test
  11 + void ok_setsCode200AndData() {
  12 + Result<String> result = Result.ok("hello");
  13 + assertEquals(200, result.getCode());
  14 + assertEquals("hello", result.getData());
  15 + assertEquals("操作成功", result.getMessage());
  16 + }
  17 +
  18 + @Test
  19 + void fail_setsCodeAndNullData() {
  20 + Result<Object> result = Result.fail(40100, "用户名或密码错误");
  21 + assertEquals(40100, result.getCode());
  22 + assertNull(result.getData());
  23 + assertEquals("用户名或密码错误", result.getMessage());
  24 + }
  25 +
  26 + @Test
  27 + void ok_hasPositiveTimestamp() {
  28 + Result<Void> result = Result.ok(null);
  29 + assertTrue(result.getTimestamp() > 0);
  30 + }
  31 +}
... ...