refactor: 重构实体类equals和hashCode方法 fix: 修复WebSocketService消息发送逻辑 style: 格式化代码和优化导入 docs: 更新JacksonConfig日期序列化格式 test: 添加CompanyFilePathTableCell测试类 chore: 清理无用代码和注释
243 lines
10 KiB
Java
243 lines
10 KiB
Java
package com.ecep.contract.config;
|
||
|
||
import java.io.IOException;
|
||
import java.time.LocalDate;
|
||
import java.time.LocalDateTime;
|
||
import java.time.LocalTime;
|
||
import java.time.format.DateTimeFormatter;
|
||
import java.util.Collection;
|
||
import java.util.Collections;
|
||
|
||
import org.hibernate.Hibernate;
|
||
import org.hibernate.collection.spi.PersistentCollection;
|
||
import org.hibernate.proxy.HibernateProxy;
|
||
import org.springframework.context.annotation.Bean;
|
||
import org.springframework.context.annotation.Configuration;
|
||
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
||
|
||
import com.ecep.contract.model.IdentityEntity;
|
||
import com.fasterxml.jackson.core.JsonGenerator;
|
||
import com.fasterxml.jackson.databind.BeanDescription;
|
||
import com.fasterxml.jackson.databind.JsonSerializer;
|
||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||
import com.fasterxml.jackson.databind.SerializationConfig;
|
||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
|
||
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
|
||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
|
||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
|
||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
|
||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
|
||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
|
||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
|
||
|
||
/**
|
||
* Jackson配置类,用于配置JSON序列化相关的设置,解决循环引用问题
|
||
*/
|
||
@Configuration
|
||
public class JacksonConfig {
|
||
|
||
@Bean
|
||
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
|
||
ObjectMapper objectMapper = builder.build();
|
||
|
||
// 关闭日期时间格式化输出为时间戳,而是输出为ISO格式的字符串
|
||
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
|
||
|
||
// 配置处理循环引用的策略,使用INDENT_OUTPUT格式化输出
|
||
objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
|
||
// 处理循环引用,启用引用处理功能
|
||
objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
|
||
|
||
// 配置Java 8时间模块的序列化格式
|
||
JavaTimeModule javaTimeModule = new JavaTimeModule();
|
||
// LocalDate
|
||
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ISO_LOCAL_DATE));
|
||
javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ISO_LOCAL_DATE));
|
||
// LocalTime
|
||
javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ISO_LOCAL_TIME));
|
||
javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ISO_LOCAL_TIME));
|
||
// LocalDateTime
|
||
javaTimeModule.addSerializer(LocalDateTime.class,
|
||
new LocalDateTimeSerializer(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
|
||
javaTimeModule.addDeserializer(LocalDateTime.class,
|
||
new LocalDateTimeDeserializer(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
|
||
|
||
objectMapper.registerModule(javaTimeModule);
|
||
|
||
// 添加自定义模块,用于处理JPA/Hibernate代理对象
|
||
SimpleModule proxyModule = new SimpleModule("HibernateProxyModule");
|
||
|
||
// 添加代理对象序列化器,只输出ID字段
|
||
proxyModule.addSerializer(HibernateProxy.class, new HibernateProxySerializer());
|
||
// 使用BeanSerializerModifier来处理IdentityEntity类型,避免递归调用
|
||
proxyModule.setSerializerModifier(new BeanSerializerModifier() {
|
||
@Override
|
||
public JsonSerializer<?> modifySerializer(SerializationConfig config,
|
||
BeanDescription beanDesc,
|
||
JsonSerializer<?> serializer) {
|
||
// 只对IdentityEntity类型进行修改
|
||
if (IdentityEntity.class.isAssignableFrom(beanDesc.getBeanClass()) &&
|
||
!HibernateProxy.class.isAssignableFrom(beanDesc.getBeanClass())) {
|
||
return new IdentityEntitySerializer(serializer);
|
||
}
|
||
return serializer;
|
||
}
|
||
});
|
||
|
||
objectMapper.registerModule(proxyModule);
|
||
|
||
return objectMapper;
|
||
}
|
||
|
||
/**
|
||
* 专门用于处理Hibernate代理对象的序列化器
|
||
*/
|
||
private static class HibernateProxySerializer extends StdSerializer<HibernateProxy> {
|
||
|
||
protected HibernateProxySerializer() {
|
||
super(HibernateProxy.class);
|
||
}
|
||
|
||
@Override
|
||
public void serialize(HibernateProxy value, JsonGenerator gen, SerializerProvider serializers)
|
||
throws IOException {
|
||
// 尝试初始化代理对象,如果未初始化则只输出ID
|
||
try {
|
||
Object unwrapped = value.getHibernateLazyInitializer().getImplementation();
|
||
// 检查是否为IdentityEntity实现类
|
||
if (unwrapped instanceof IdentityEntity) {
|
||
gen.writeStartObject();
|
||
gen.writeNumberField("id", ((IdentityEntity) unwrapped).getId());
|
||
gen.writeEndObject();
|
||
} else {
|
||
// 如果不是IdentityEntity,使用默认序列化
|
||
serializers.defaultSerializeValue(unwrapped, gen);
|
||
}
|
||
} catch (Exception e) {
|
||
// 如果初始化失败,只输出ID
|
||
if (value instanceof IdentityEntity) {
|
||
gen.writeStartObject();
|
||
gen.writeNumberField("id", ((IdentityEntity) value).getId());
|
||
gen.writeEndObject();
|
||
} else {
|
||
// 如果不是IdentityEntity,输出对象的基本信息
|
||
gen.writeStartObject();
|
||
gen.writeStringField("class", value.getClass().getName());
|
||
gen.writeEndObject();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 用于处理集合类型的序列化器,避免懒加载集合在会话关闭时无法序列化的问题
|
||
*/
|
||
private static class CollectionSerializer extends StdSerializer<Collection<?>> {
|
||
|
||
protected CollectionSerializer() {
|
||
super((Class<Collection<?>>) (Class<?>) Collection.class);
|
||
}
|
||
|
||
@Override
|
||
public void serialize(Collection<?> value, JsonGenerator gen, SerializerProvider serializers)
|
||
throws IOException {
|
||
// 检查集合是否为Hibernate的持久化集合
|
||
if (value instanceof PersistentCollection) {
|
||
PersistentCollection persistentCollection = (PersistentCollection) value;
|
||
// 如果集合未初始化,返回空集合
|
||
if (!persistentCollection.wasInitialized()) {
|
||
gen.writeStartArray();
|
||
gen.writeEndArray();
|
||
return;
|
||
}
|
||
}
|
||
|
||
// 如果已初始化,使用默认序列化
|
||
serializers.defaultSerializeValue(value, gen);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 用于处理IdentityEntity类型的序列化器包装器
|
||
*/
|
||
private static class IdentityEntitySerializer extends StdSerializer<Object> {
|
||
private final JsonSerializer<?> delegate;
|
||
|
||
protected IdentityEntitySerializer(JsonSerializer<?> delegate) {
|
||
super(Object.class);
|
||
this.delegate = delegate;
|
||
}
|
||
|
||
@Override
|
||
public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers)
|
||
throws IOException {
|
||
// 对于IdentityEntity对象,如果未初始化,则只输出ID
|
||
if (value instanceof IdentityEntity && !Hibernate.isInitialized(value)) {
|
||
gen.writeStartObject();
|
||
gen.writeNumberField("id", ((IdentityEntity) value).getId());
|
||
gen.writeStringField("_proxy_", value.getClass().getName());
|
||
gen.writeEndObject();
|
||
} else {
|
||
// 已初始化的实体,使用原始的序列化器进行序列化,避免递归调用
|
||
((JsonSerializer<Object>) delegate).serialize(value, gen, serializers);
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 用于处理对象引用的序列化器,通过检测和管理对象引用避免循环引用问题
|
||
*/
|
||
private static class IdentityReferenceSerializer extends StdSerializer<Object> {
|
||
private final JsonSerializer<?> delegate;
|
||
private final ThreadLocal<java.util.Set<Object>> visitedObjects = ThreadLocal
|
||
.withInitial(java.util.HashSet::new);
|
||
|
||
protected IdentityReferenceSerializer(JsonSerializer<?> delegate) {
|
||
super(Object.class);
|
||
this.delegate = delegate;
|
||
}
|
||
|
||
@Override
|
||
public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
|
||
// 处理null值
|
||
if (value == null) {
|
||
serializers.defaultSerializeNull(gen);
|
||
return;
|
||
}
|
||
|
||
java.util.Set<Object> visited = visitedObjects.get();
|
||
try {
|
||
// 检查对象是否已经被访问过
|
||
if (visited.contains(value)) {
|
||
// 如果对象实现了IdentityEntity,只输出ID
|
||
if (value instanceof IdentityEntity) {
|
||
gen.writeStartObject();
|
||
gen.writeNumberField("id", ((IdentityEntity) value).getId());
|
||
gen.writeStringField("_ref_", "" + ((IdentityEntity) value).getId());
|
||
gen.writeEndObject();
|
||
} else {
|
||
// 对于非IdentityEntity对象,输出对象的toString或hashCode
|
||
gen.writeString(value.toString());
|
||
}
|
||
return;
|
||
}
|
||
|
||
// 标记对象为已访问
|
||
visited.add(value);
|
||
|
||
// 使用委托序列化器进行正常序列化
|
||
((JsonSerializer<Object>) delegate).serialize(value, gen, serializers);
|
||
} finally {
|
||
// 清理访问记录
|
||
visited.remove(value);
|
||
if (visited.isEmpty()) {
|
||
visitedObjects.remove();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} |