XuqmGroup-Server/im-service/src/main/java/com/xuqm/im/controller/GlobalExceptionHandler.java

100 行
5.6 KiB
Java

package com.xuqm.im.controller;
import com.xuqm.common.exception.BusinessException;
import com.xuqm.common.model.ApiResponse;
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.security.access.AccessDeniedException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
@ExceptionHandler(BusinessException.class)
public ResponseEntity<ApiResponse<Void>> handleBusiness(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<ApiResponse<Void>> handleValidation(MethodArgumentNotValidException ex, HttpServletRequest request) {
String message = ex.getBindingResult().getFieldErrors().stream()
.findFirst()
.map(error -> error.getDefaultMessage())
.orElse("参数错误");
log.warn("[{}] {} validation failed: {}", request.getMethod(), request.getRequestURI(), message);
return ResponseEntity.badRequest().body(ApiResponse.badRequest(message));
}
@ExceptionHandler(MissingServletRequestParameterException.class)
public ResponseEntity<ApiResponse<Void>> handleMissingParam(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<ApiResponse<Void>> handleIllegalArgument(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<ApiResponse<Void>> handleUnreadable(HttpMessageNotReadableException ex, HttpServletRequest request) {
log.warn("[{}] {} request body unreadable: {}", request.getMethod(), request.getRequestURI(), ex.getMessage());
return ResponseEntity.badRequest().body(ApiResponse.badRequest("请求体格式错误"));
}
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
public ResponseEntity<ApiResponse<Void>> handleMethodNotSupported(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(AccessDeniedException.class)
public ResponseEntity<ApiResponse<Void>> handleAuthorizationDenied(AccessDeniedException ex, HttpServletRequest request) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String principal = authentication == null ? "anonymous" : String.valueOf(authentication.getPrincipal());
String authorities = authentication == null ? "[]" : authentication.getAuthorities().toString();
log.warn("[{}] {} authorization denied: principal={} authorities={} reason={}",
request.getMethod(), request.getRequestURI(), principal, authorities, ex.getMessage());
return ResponseEntity.status(HttpStatus.FORBIDDEN)
.body(ApiResponse.error(403, "权限不足"));
}
@ExceptionHandler(Exception.class)
public ResponseEntity<ApiResponse<Void>> handleException(Exception ex, HttpServletRequest request) {
log.error("[{}] {} unhandled exception: {}", request.getMethod(), request.getRequestURI(), ex.getMessage(), ex);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.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;
};
}
}