GlobalExceptionHandler.java 2.28 KB
package com.xly.erp.common.exception;

import com.xly.erp.common.response.ErrorCode;
import com.xly.erp.common.response.Result;
import jakarta.validation.ConstraintViolationException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * 全局异常处理器。
 * 把 BizException / 参数校验异常 / 兜底异常转 Result.fail 统一响应。
 * docs/04 § 1.4。
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    @ExceptionHandler(BizException.class)
    public ResponseEntity<Result<Object>> handleBiz(BizException e) {
        log.warn("[BizException] code={} message={} hasData={}", e.getCode(), e.getMessage(), e.getData() != null);
        Result<Object> body = e.getData() != null
                ? Result.fail(e.getCode(), e.getMessage(), e.getData())
                : Result.fail(e.getCode(), e.getMessage());
        return ResponseEntity
                .status(ErrorCode.toHttpStatus(e.getCode()))
                .body(body);
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Result<Void>> handleValidation(MethodArgumentNotValidException e) {
        String msg = e.getBindingResult().getFieldErrors().stream()
                .findFirst()
                .map(fe -> fe.getField() + " " + fe.getDefaultMessage())
                .orElse("参数校验失败");
        return ResponseEntity
                .status(400)
                .body(Result.fail(ErrorCode.BAD_REQUEST, msg));
    }

    @ExceptionHandler(ConstraintViolationException.class)
    public ResponseEntity<Result<Void>> handleConstraint(ConstraintViolationException e) {
        return ResponseEntity
                .status(400)
                .body(Result.fail(ErrorCode.BAD_REQUEST, e.getMessage()));
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<Result<Void>> handleFallback(Exception e) {
        log.error("[Unhandled] {}", e.getMessage(), e);
        return ResponseEntity
                .status(500)
                .body(Result.fail(ErrorCode.INTERNAL_ERROR, "服务器内部错误"));
    }
}