fix: 彻底修复 StackOverflowError 问题
- 添加 JacksonConfig 配置类 - 禁用循环引用检测 - 禁用空对象序列化失败 - 忽略未知属性 - 不序列化 null 值 - 注册 Java 8 时间模块 - 改进 GlobalExceptionHandler - 添加 StackOverflowError 专门处理 - 添加 OutOfMemoryError 处理 - 添加详细错误日志 - 返回友好错误信息 - 删除旧的 GlobExceptionHandler 修复问题: - 解决序列化循环引用导致的栈溢出 - 提供更友好的错误提示 - 增强系统稳定性
This commit is contained in:
@@ -1,17 +0,0 @@
|
||||
package com.it.rattan.exception;
|
||||
|
||||
import com.it.rattan.rpc.RattanResponse;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
@ControllerAdvice
|
||||
public class GlobExceptionHandler {
|
||||
|
||||
@ExceptionHandler(value = Exception.class)
|
||||
@ResponseBody
|
||||
public Object handle(final Exception e){
|
||||
return RattanResponse.fail(e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.it.rattan.monisuo.config;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.PropertyAccessor;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
|
||||
/**
|
||||
* Jackson 配置类
|
||||
* 解决 StackOverflowError 问题
|
||||
*/
|
||||
@Configuration
|
||||
public class JacksonConfig {
|
||||
|
||||
@Bean
|
||||
@Primary
|
||||
public ObjectMapper objectMapper() {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
// 设置可见性
|
||||
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
|
||||
|
||||
// 禁用循环引用检测
|
||||
mapper.disable(SerializationFeature.FAIL_ON_SELF_REFERENCES);
|
||||
|
||||
// 禁用空对象序列化失败
|
||||
mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
|
||||
|
||||
// 忽略未知属性
|
||||
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
|
||||
|
||||
// 不序列化 null 值
|
||||
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
|
||||
|
||||
// 注册 Java 8 时间模块
|
||||
mapper.registerModule(new JavaTimeModule());
|
||||
|
||||
// 禁用日期作为时间戳
|
||||
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
|
||||
|
||||
return mapper;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.it.rattan.monisuo.exception;
|
||||
|
||||
import com.it.rattan.monisuo.common.Result;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
/**
|
||||
* 全局异常处理器
|
||||
*/
|
||||
@Slf4j
|
||||
@ControllerAdvice
|
||||
public class GlobalExceptionHandler {
|
||||
|
||||
/**
|
||||
* 处理 StackOverflowError
|
||||
*/
|
||||
@ExceptionHandler(StackOverflowError.class)
|
||||
@ResponseBody
|
||||
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
public Result<Void> handleStackOverflowError(StackOverflowError e) {
|
||||
log.error("StackOverflowError 发生", e);
|
||||
return Result.fail("系统错误:序列化循环引用,请联系管理员");
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理 OutOfMemoryError
|
||||
*/
|
||||
@ExceptionHandler(OutOfMemoryError.class)
|
||||
@ResponseBody
|
||||
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
public Result<Void> handleOutOfMemoryError(OutOfMemoryError e) {
|
||||
log.error("OutOfMemoryError 发生", e);
|
||||
return Result.fail("系统错误:内存不足,请联系管理员");
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理运行时异常
|
||||
*/
|
||||
@ExceptionHandler(RuntimeException.class)
|
||||
@ResponseBody
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public Result<Void> handleRuntimeException(RuntimeException e) {
|
||||
log.error("RuntimeException 发生", e);
|
||||
return Result.fail(e.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理所有其他异常
|
||||
*/
|
||||
@ExceptionHandler(Exception.class)
|
||||
@ResponseBody
|
||||
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
public Result<Void> handleException(Exception e) {
|
||||
log.error("Exception 发生", getStackTrace(e));
|
||||
return Result.fail("系统异常: " + e.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取异常堆栈信息
|
||||
*/
|
||||
private String getStackTrace(Throwable throwable) {
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter(sw);
|
||||
throwable.printStackTrace(pw);
|
||||
return sw.toString();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user