package com.xuqm.im.controller; import com.xuqm.common.exception.BusinessException; import com.xuqm.common.model.ApiResponse; 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.authorization.AuthorizationDeniedException; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; 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> handleBusiness(BusinessException e) { return ResponseEntity.status(resolveStatus(e.getCode())) .body(ApiResponse.error(e.getCode(), e.getMessage())); } @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity> handleValidation(MethodArgumentNotValidException e) { return ResponseEntity.badRequest().body(ApiResponse.badRequest(e.getBindingResult() .getFieldErrors() .stream() .findFirst() .map(error -> error.getDefaultMessage()) .orElse("参数错误"))); } @ExceptionHandler(IllegalArgumentException.class) public ResponseEntity> handleIllegalArgument(IllegalArgumentException e) { return ResponseEntity.badRequest().body(ApiResponse.badRequest(e.getMessage() == null ? "参数错误" : e.getMessage())); } @ExceptionHandler(HttpMessageNotReadableException.class) public ResponseEntity> handleUnreadable(HttpMessageNotReadableException e) { return ResponseEntity.badRequest().body(ApiResponse.badRequest("请求体格式错误")); } @ExceptionHandler(AuthorizationDeniedException.class) public ResponseEntity> handleAuthorizationDenied(AuthorizationDeniedException e) { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); String principal = authentication == null ? null : String.valueOf(authentication.getPrincipal()); String authorities = authentication == null ? "[]" : authentication.getAuthorities().toString(); log.warn("Access denied path={} principal={} authorities={} reason={}", "im-service", principal, authorities, e.getMessage()); return ResponseEntity.status(HttpStatus.FORBIDDEN) .body(ApiResponse.error(403, "Forbidden: current token lacks required role")); } @ExceptionHandler(Exception.class) public ResponseEntity> handleException(Exception e) { log.error("Unhandled exception", e); 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; }; } }