package com.iflytop.gd.common.handler; import com.iflytop.gd.common.exception.AppException; import com.iflytop.gd.common.result.Result; import com.iflytop.gd.common.result.ResultCode; import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.ConstraintViolationException; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.BindException; import org.springframework.web.HttpRequestMethodNotSupportedException; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import java.util.stream.Collectors; @Slf4j @RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(HttpRequestMethodNotSupportedException.class) public Result handleMethodNotSupported(HttpRequestMethodNotSupportedException ex, HttpServletRequest request) { String method = request.getMethod(); String uri = request.getRequestURI(); String allowed = ex.getSupportedHttpMethods() != null ? ex.getSupportedHttpMethods().toString() : "[]"; String msg = String.format( "请求方法 '%s' 不支持 (URL: %s)。支持的方法有:%s", method, uri, allowed); log.error(msg, ex); return Result.failed(ResultCode.METHOD_NOT_ALLOWED.getCode(), msg); } // 1) JSON Body 校验失败 @ExceptionHandler(MethodArgumentNotValidException.class) public Result handleBodyValid(MethodArgumentNotValidException ex) { String msg = ex.getBindingResult().getFieldErrors().stream() .map(f -> f.getField() + ": " + f.getDefaultMessage()) .collect(Collectors.joining("; ")); return Result.failed(ResultCode.INVALID_PARAMETER.getCode(), msg); } // 2) 方法级参数校验失败(PathVariable/RequestParam) @ExceptionHandler(ConstraintViolationException.class) public Result handleParamValid(ConstraintViolationException ex) { String msg = ex.getConstraintViolations().stream() .map(v -> { String path = v.getPropertyPath().toString(); String field = path.substring(path.lastIndexOf('.') + 1); return field + ": " + v.getMessage(); }) .collect(Collectors.joining("; ")); return Result.failed(ResultCode.INVALID_PARAMETER.getCode(), msg); } // 3) 表单绑定失败 @ExceptionHandler(BindException.class) public Result handleBind(BindException ex) { String msg = ex.getFieldErrors().stream() .map(f -> f.getField() + ": " + f.getDefaultMessage()) .collect(Collectors.joining("; ")); return Result.failed(ResultCode.INVALID_PARAMETER.getCode(), msg); } @ExceptionHandler(Exception.class) public Result handleException(Exception ex) { if (ex instanceof AppException ae) { log.warn("AppException:", ae); return Result.failed(ae.getResultCode()); } log.error("Unhandled exception:", ex); return Result.failed(ResultCode.SYSTEM_ERROR.getCode(), ex.getMessage()); } }