package com.rj.config; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.web.HttpMediaTypeNotSupportedException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.context.request.WebRequest; import org.springframework.web.multipart.MultipartException; import jakarta.servlet.http.HttpServletRequest; import java.util.HashMap; import java.util.Map; /** * 全局异常处理器 * 用于捕获和处理各种异常,特别是 HttpMediaTypeNotSupportedException * * @author Auto Generated * @since 2025-11-30 */ @Slf4j @ControllerAdvice public class GlobalExceptionHandler { @Autowired private ObjectMapper objectMapper; /** * 处理 HttpMediaTypeNotSupportedException 异常 * 当 Content-Type 不支持时触发,特别是 multipart/form-data 请求使用 @RequestBody 时 */ @ExceptionHandler(HttpMediaTypeNotSupportedException.class) public ResponseEntity> handleHttpMediaTypeNotSupportedException( HttpMediaTypeNotSupportedException ex, HttpServletRequest request, WebRequest webRequest) { Map result = new HashMap<>(); String contentType = ex.getContentType() != null ? ex.getContentType().toString() : "unknown"; String dataType = null; // 尝试从请求参数中提取 dataType try { // 如果是 multipart/form-data,尝试从 data 参数中提取 String dataParam = request.getParameter("data"); if (dataParam != null && !dataParam.trim().isEmpty()) { try { Map dataMap = objectMapper.readValue(dataParam, new TypeReference>() {}); dataType = (String) dataMap.get("dataType"); if (dataType == null || dataType.trim().isEmpty()) { dataType = (String) dataMap.get("pushDataType"); } } catch (Exception e) { log.debug("无法从 data 参数解析 dataType: {}", e.getMessage()); } } // 如果 data 参数中没有,尝试直接从请求参数中获取 if (dataType == null || dataType.trim().isEmpty()) { dataType = request.getParameter("dataType"); if (dataType == null || dataType.trim().isEmpty()) { dataType = request.getParameter("pushDataType"); } } } catch (Exception e) { log.debug("提取 dataType 时发生异常: {}", e.getMessage()); } // 输出错误信息和 dataType 到控制台 String errorMessage = String.format( "HttpMediaTypeNotSupportedException: Content-Type '%s' is not supported. dataType: %s, URI: %s", contentType, dataType != null ? dataType : "unknown", request.getRequestURI() ); log.error(errorMessage); System.out.println("=========================================="); System.out.println("ERROR: " + errorMessage); System.out.println("Content-Type: " + contentType); System.out.println("dataType: " + (dataType != null ? dataType : "unknown")); System.out.println("Request URI: " + request.getRequestURI()); System.out.println("Request Method: " + request.getMethod()); System.out.println("=========================================="); result.put("success", false); result.put("message", "不支持的 Content-Type: " + contentType); result.put("error", "HttpMediaTypeNotSupportedException"); result.put("contentType", contentType); result.put("dataType", dataType); result.put("uri", request.getRequestURI()); return ResponseEntity.status(HttpStatus.UNSUPPORTED_MEDIA_TYPE).body(result); } /** * 处理 MultipartException 异常 * 当 multipart 请求解析失败时触发 */ @ExceptionHandler(MultipartException.class) public ResponseEntity> handleMultipartException( MultipartException ex, HttpServletRequest request) { Map result = new HashMap<>(); String dataType = null; // 尝试从请求参数中提取 dataType try { String dataParam = request.getParameter("data"); if (dataParam != null && !dataParam.trim().isEmpty()) { try { Map dataMap = objectMapper.readValue(dataParam, new TypeReference>() {}); dataType = (String) dataMap.get("dataType"); if (dataType == null || dataType.trim().isEmpty()) { dataType = (String) dataMap.get("pushDataType"); } } catch (Exception e) { log.debug("无法从 data 参数解析 dataType: {}", e.getMessage()); } } if (dataType == null || dataType.trim().isEmpty()) { dataType = request.getParameter("dataType"); if (dataType == null || dataType.trim().isEmpty()) { dataType = request.getParameter("pushDataType"); } } } catch (Exception e) { log.debug("提取 dataType 时发生异常: {}", e.getMessage()); } String errorMessage = String.format( "MultipartException: %s. dataType: %s, URI: %s", ex.getMessage(), dataType != null ? dataType : "unknown", request.getRequestURI() ); log.error(errorMessage, ex); System.out.println("=========================================="); System.out.println("ERROR: " + errorMessage); System.out.println("dataType: " + (dataType != null ? dataType : "unknown")); System.out.println("Request URI: " + request.getRequestURI()); System.out.println("=========================================="); result.put("success", false); result.put("message", "Multipart 请求解析失败: " + ex.getMessage()); result.put("error", "MultipartException"); result.put("dataType", dataType); result.put("uri", request.getRequestURI()); return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(result); } /** * 处理 HttpMessageNotReadableException 异常 * 当请求体无法读取时触发 */ @ExceptionHandler(HttpMessageNotReadableException.class) public ResponseEntity> handleHttpMessageNotReadableException( HttpMessageNotReadableException ex, HttpServletRequest request) { Map result = new HashMap<>(); String contentType = request.getContentType(); String dataType = null; // 尝试从请求参数中提取 dataType try { String dataParam = request.getParameter("data"); if (dataParam != null && !dataParam.trim().isEmpty()) { try { Map dataMap = objectMapper.readValue(dataParam, new TypeReference>() {}); dataType = (String) dataMap.get("dataType"); if (dataType == null || dataType.trim().isEmpty()) { dataType = (String) dataMap.get("pushDataType"); } } catch (Exception e) { log.debug("无法从 data 参数解析 dataType: {}", e.getMessage()); } } if (dataType == null || dataType.trim().isEmpty()) { dataType = request.getParameter("dataType"); if (dataType == null || dataType.trim().isEmpty()) { dataType = request.getParameter("pushDataType"); } } } catch (Exception e) { log.debug("提取 dataType 时发生异常: {}", e.getMessage()); } String errorMessage = String.format( "HttpMessageNotReadableException: %s. Content-Type: %s, dataType: %s, URI: %s", ex.getMessage(), contentType != null ? contentType : "unknown", dataType != null ? dataType : "unknown", request.getRequestURI() ); log.error(errorMessage, ex); System.out.println("=========================================="); System.out.println("ERROR: " + errorMessage); System.out.println("Content-Type: " + (contentType != null ? contentType : "unknown")); System.out.println("dataType: " + (dataType != null ? dataType : "unknown")); System.out.println("Request URI: " + request.getRequestURI()); System.out.println("=========================================="); result.put("success", false); result.put("message", "请求体无法读取: " + ex.getMessage()); result.put("error", "HttpMessageNotReadableException"); result.put("contentType", contentType); result.put("dataType", dataType); result.put("uri", request.getRequestURI()); return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(result); } }