package com.xuqm.bugcollect.controller; import com.xuqm.common.exception.BusinessException; import com.xuqm.common.model.ApiResponse; import com.xuqm.bugcollect.service.BugCollectDisabledException; import jakarta.servlet.http.HttpServletRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.validation.FieldError; import org.springframework.web.HttpRequestMethodNotSupportedException; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.MissingServletRequestParameterException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.multipart.MaxUploadSizeExceededException; import java.util.stream.Collectors; @RestControllerAdvice public class GlobalExceptionHandler { private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class); @ExceptionHandler(BugCollectDisabledException.class) public ResponseEntity> handle(BugCollectDisabledException ex) { return ResponseEntity.status(HttpStatus.FORBIDDEN) .body(ApiResponse.error(403, BugCollectDisabledException.ERROR_CODE)); } @ExceptionHandler(BusinessException.class) public ResponseEntity> handle(BusinessException ex, HttpServletRequest request) { if (ex.getCode() >= 500) { log.error("[{}] {} code={} msg={}", request.getMethod(), request.getRequestURI(), ex.getCode(), ex.getMessage(), ex); } else { log.warn("[{}] {} code={} msg={}", request.getMethod(), request.getRequestURI(), ex.getCode(), ex.getMessage()); } return ResponseEntity.status(resolveStatus(ex.getCode())) .body(ApiResponse.error(ex.getCode(), ex.getMessage())); } @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity> handle(MethodArgumentNotValidException ex, HttpServletRequest request) { String message = ex.getBindingResult().getFieldErrors().stream() .map(FieldError::getDefaultMessage) .collect(Collectors.joining("; ")); log.warn("[{}] {} validation failed: {}", request.getMethod(), request.getRequestURI(), message); return ResponseEntity.badRequest().body(ApiResponse.badRequest(message)); } @ExceptionHandler(MissingServletRequestParameterException.class) public ResponseEntity> handle(MissingServletRequestParameterException ex, HttpServletRequest request) { log.warn("[{}] {} missing param: {}", request.getMethod(), request.getRequestURI(), ex.getParameterName()); return ResponseEntity.badRequest() .body(ApiResponse.badRequest("缺少必填参数: " + ex.getParameterName())); } @ExceptionHandler(IllegalArgumentException.class) public ResponseEntity> handle(IllegalArgumentException ex, HttpServletRequest request) { log.warn("[{}] {} illegal argument: {}", request.getMethod(), request.getRequestURI(), ex.getMessage()); return ResponseEntity.badRequest() .body(ApiResponse.badRequest(ex.getMessage() == null ? "参数错误" : ex.getMessage())); } @ExceptionHandler(HttpMessageNotReadableException.class) public ResponseEntity> handle(HttpMessageNotReadableException ex, HttpServletRequest request) { log.warn("[{}] {} request body unreadable: {}", request.getMethod(), request.getRequestURI(), ex.getMessage()); return ResponseEntity.badRequest().body(ApiResponse.badRequest("请求体格式错误")); } @ExceptionHandler(MaxUploadSizeExceededException.class) public ResponseEntity> handle(MaxUploadSizeExceededException ex, HttpServletRequest request) { log.warn("[{}] {} file too large: {}", request.getMethod(), request.getRequestURI(), ex.getMessage()); return ResponseEntity.badRequest().body(ApiResponse.badRequest("文件大小超出限制")); } @ExceptionHandler(HttpRequestMethodNotSupportedException.class) public ResponseEntity> handle(HttpRequestMethodNotSupportedException ex, HttpServletRequest request) { log.warn("[{}] {} method not supported: {}", request.getMethod(), request.getRequestURI(), ex.getMethod()); return ResponseEntity.status(HttpStatus.METHOD_NOT_ALLOWED) .body(ApiResponse.error(405, "请求方法不支持: " + ex.getMethod())); } @ExceptionHandler(Exception.class) public ResponseEntity> handle(Exception ex, HttpServletRequest request) { log.error("[{}] {} unhandled exception: {}", request.getMethod(), request.getRequestURI(), ex.getMessage(), ex); return ResponseEntity.internalServerError() .body(ApiResponse.error(500, "服务器内部错误")); } private HttpStatus resolveStatus(int code) { return switch (code) { case 400 -> HttpStatus.BAD_REQUEST; case 401 -> HttpStatus.UNAUTHORIZED; case 403 -> HttpStatus.FORBIDDEN; case 404 -> HttpStatus.NOT_FOUND; default -> HttpStatus.INTERNAL_SERVER_ERROR; }; } }