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> handleBiz(BizException e) { log.warn("[BizException] code={} message={} hasData={}", e.getCode(), e.getMessage(), e.getData() != null); Result 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> 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> handleConstraint(ConstraintViolationException e) { return ResponseEntity .status(400) .body(Result.fail(ErrorCode.BAD_REQUEST, e.getMessage())); } @ExceptionHandler(Exception.class) public ResponseEntity> handleFallback(Exception e) { log.error("[Unhandled] {}", e.getMessage(), e); return ResponseEntity .status(500) .body(Result.fail(ErrorCode.INTERNAL_ERROR, "服务器内部错误")); } }