227 lines
9.7 KiB
Java
227 lines
9.7 KiB
Java
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<Map<String, Object>> handleHttpMediaTypeNotSupportedException(
|
||
HttpMediaTypeNotSupportedException ex,
|
||
HttpServletRequest request,
|
||
WebRequest webRequest) {
|
||
|
||
Map<String, Object> 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<String, Object> dataMap = objectMapper.readValue(dataParam, new TypeReference<Map<String, Object>>() {});
|
||
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<Map<String, Object>> handleMultipartException(
|
||
MultipartException ex,
|
||
HttpServletRequest request) {
|
||
|
||
Map<String, Object> result = new HashMap<>();
|
||
String dataType = null;
|
||
|
||
// 尝试从请求参数中提取 dataType
|
||
try {
|
||
String dataParam = request.getParameter("data");
|
||
if (dataParam != null && !dataParam.trim().isEmpty()) {
|
||
try {
|
||
Map<String, Object> dataMap = objectMapper.readValue(dataParam, new TypeReference<Map<String, Object>>() {});
|
||
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<Map<String, Object>> handleHttpMessageNotReadableException(
|
||
HttpMessageNotReadableException ex,
|
||
HttpServletRequest request) {
|
||
|
||
Map<String, Object> 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<String, Object> dataMap = objectMapper.readValue(dataParam, new TypeReference<Map<String, Object>>() {});
|
||
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);
|
||
}
|
||
}
|
||
|