refactor(service): 修改IEntityService泛型为VO类型并优化缓存策略

重构所有注解@CacheConfig的Service类,将IEntityService泛型从实体类改为VO类
实现实体与VO之间的转换逻辑,使用VO替代实体进行缓存以避免序列化问题
更新相关依赖组件和测试用例,确保功能完整性和系统兼容性
优化Redis缓存配置,清理旧缓存数据并验证新缓存策略有效性
This commit is contained in:
2025-09-28 18:19:00 +08:00
parent df6188db40
commit b03b5385a5
75 changed files with 3144 additions and 1377 deletions

View File

@@ -0,0 +1,64 @@
package com.ecep.contract.config;
import java.io.IOException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
/**
* 自定义LocalDateTime反序列化器支持多种格式
*/
class CustomLocalDateTimeDeserializer extends StdDeserializer<LocalDateTime> {
private final List<DateTimeFormatter> formatters;
public CustomLocalDateTimeDeserializer() {
super(LocalDateTime.class);
// 支持多种日期时间格式
this.formatters = new ArrayList<>();
// ISO标准格式
this.formatters.add(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
// 项目默认格式 yyyy-MM-dd HH:mm:ss
this.formatters.add(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
// 其他可能的格式
this.formatters.add(DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"));
this.formatters.add(DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss"));
this.formatters.add(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm"));
this.formatters.add(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
}
@Override
public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
String value = p.getText().trim();
if (value == null || value.isEmpty()) {
return null;
}
// 尝试使用各种格式解析
for (DateTimeFormatter formatter : formatters) {
try {
return LocalDateTime.parse(value, formatter);
} catch (Exception e) {
// 尝试下一种格式
continue;
}
}
// 如果所有格式都失败尝试使用ISO_INSTANT格式可能是时间戳字符串
try {
return LocalDateTime.ofInstant(Instant.parse(value), ZoneId.systemDefault());
} catch (Exception e) {
// 仍然失败,抛出异常
throw new JsonParseException(p, "无法解析为LocalDateTime: " + value);
}
}
}

View File

@@ -0,0 +1,111 @@
package com.ecep.contract.config;
import java.io.IOException;
import org.hibernate.proxy.HibernateProxy;
import com.ecep.contract.model.IdentityEntity;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
/**
* 用于处理Hibernate代理对象的反序列化器
* 专门处理序列化时写入的id和_proxy_字段
*/
class HibernateProxyDeserializer extends StdDeserializer<HibernateProxy> {
protected HibernateProxyDeserializer() {
super(HibernateProxy.class);
}
@Override
public HibernateProxy deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
// 检查是否是对象类型
if (p.currentToken() != JsonToken.START_OBJECT) {
return (HibernateProxy) ctxt.handleUnexpectedToken(HibernateProxy.class, p);
}
// 读取对象字段
JsonToken token;
Object id = null;
String proxyClassName = null;
// 解析JSON对象的所有字段
while ((token = p.nextToken()) != JsonToken.END_OBJECT) {
if (token == JsonToken.FIELD_NAME) {
String fieldName = p.getCurrentName();
p.nextToken(); // 移动到字段值
if ("id".equals(fieldName)) {
id = p.readValueAs(Object.class);
} else if ("_proxy_".equals(fieldName)) {
proxyClassName = p.getText();
}
}
}
// 如果同时存在id和_proxy_字段说明这是一个Hibernate代理对象
if (id != null && proxyClassName != null) {
HibernateProxy proxy = null;
try {
// 尝试获取实体类类型(去掉代理类名中的字节码增强部分)
// 代理类名通常格式为com.ecep.contract.model.Entity$HibernateProxy$XXXX
int proxyIndex = proxyClassName.indexOf("$HibernateProxy$");
String entityClassName = proxyIndex > 0 ? proxyClassName.substring(0, proxyIndex) : proxyClassName;
// 加载实体类
Class<?> entityClass = Class.forName(entityClassName);
// 检查是否是IdentityEntity类型
if (IdentityEntity.class.isAssignableFrom(entityClass)) {
// 创建实体对象并设置ID
IdentityEntity entity = (IdentityEntity) entityClass.getDeclaredConstructor().newInstance();
if (id instanceof Number) {
entity.setId(((Number) id).intValue());
} else {
// 处理非数值类型的ID
try {
entity.setId(Integer.parseInt(id.toString()));
} catch (NumberFormatException e) {
// 如果无法转换为Integer记录警告但继续处理
}
}
return (HibernateProxy) entity;
}
} catch (Exception e) {
// 发生异常时返回一个只包含ID的简单对象
// 这可以避免反序列化失败
return (HibernateProxy) createSimpleIdObject(id);
}
}
// 如果不是代理对象或处理失败,回退到默认的反序列化逻辑
// 使用 skipChildren() 确保解析器在正确的位置开始默认反序列化
if (p.currentToken() != JsonToken.START_OBJECT) {
// 尝试查找对象开始位置
while (p.currentToken() != null && p.currentToken() != JsonToken.START_OBJECT) {
p.nextToken();
}
}
if (p.currentToken() == JsonToken.START_OBJECT) {
return (HibernateProxy) ctxt.readValue(p, Object.class);
}
return null;
}
/**
* 创建一个只包含ID字段的简单对象
*/
private Object createSimpleIdObject(final Object id) {
return new Object() {
@Override
public String toString() {
return "ProxyObject[id=" + id + "]";
}
};
}
}

View File

@@ -0,0 +1,111 @@
package com.ecep.contract.config;
import java.io.IOException;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
import com.ecep.contract.model.IdentityEntity;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
/**
* 专门用于处理HibernateProxy对象的序列化器
*/
class HibernateProxySerializer extends StdSerializer<HibernateProxy> {
protected HibernateProxySerializer() {
super(HibernateProxy.class);
}
@Override
public void serialize(HibernateProxy value, JsonGenerator gen, SerializerProvider serializers)
throws IOException {
// 尝试初始化代理对象如果未初始化则只输出ID
try {
LazyInitializer lazyInitializer = value.getHibernateLazyInitializer();
if (lazyInitializer.isUninitialized()) {
// 如果代理对象未初始化只输出ID
if (lazyInitializer.getIdentifier() != null) {
gen.writeStartObject();
gen.writeFieldName("id");
gen.writeObject(lazyInitializer.getIdentifier());
gen.writeStringField("_proxy_", lazyInitializer.getEntityName());
gen.writeEndObject();
} else {
gen.writeNull();
}
} else {
// 如果代理对象已初始化,获取实际对象并序列化
Object unwrapped = lazyInitializer.getImplementation();
if (unwrapped instanceof IdentityEntity) {
// 对于IdentityEntity类型输出更简洁的格式
gen.writeStartObject();
gen.writeNumberField("id", ((IdentityEntity) unwrapped).getId());
gen.writeEndObject();
} else {
// 对于非IdentityEntity类型使用默认序列化
serializers.defaultSerializeValue(unwrapped, gen);
}
}
} catch (Exception e) {
// 如果发生异常,输出最小化信息
gen.writeStartObject();
gen.writeStringField("error", "Failed to serialize Hibernate proxy: " + e.getMessage());
gen.writeStringField("class", value.getClass().getName());
gen.writeEndObject();
}
}
@Override
public void serializeWithType(HibernateProxy value, JsonGenerator gen, SerializerProvider serializers,
TypeSerializer typeSer) throws IOException {
// 当启用类型信息时Jackson会调用这个方法
try {
LazyInitializer lazyInitializer = value.getHibernateLazyInitializer();
// 获取实际的实体类型名称
String entityTypeName = lazyInitializer.getEntityName();
Class<?> entityClass = Class.forName(entityTypeName);
if (lazyInitializer.isUninitialized()) {
// 确保输出@class: 'org.hibernate.proxy.HibernateProxy'
// 直接使用HibernateProxy.class作为typeId
gen.writeStartObject();
gen.writeStringField("@class", "org.hibernate.proxy.HibernateProxy");
// 对于未初始化的对象,添加代理信息
gen.writeStringField("_proxy_", entityTypeName);
// 写入ID信息
if (lazyInitializer.getIdentifier() != null) {
gen.writeFieldName("id");
gen.writeObject(lazyInitializer.getIdentifier());
}
gen.writeEndObject();
} else {
// 如果代理对象已初始化,获取实际对象
Object unwrapped = lazyInitializer.getImplementation();
// 使用实际对象的类型信息进行序列化
// 查找能够处理类型信息的序列化器
JsonSerializer<Object> serializer = serializers.findTypedValueSerializer(
unwrapped.getClass(), true, null);
// 委托给实际对象的序列化器处理,确保类型信息正确添加
serializer.serializeWithType(unwrapped, gen, serializers, typeSer);
}
} catch (Exception e) {
// 如果发生异常,输出最小化信息并添加类型信息
// 先写入类型前缀
typeSer.writeTypePrefix(gen, typeSer.typeId(value.getClass(), JsonToken.START_OBJECT));
// 输出错误信息
gen.writeStringField("error", "Failed to serialize Hibernate proxy with type: " + e.getMessage());
gen.writeStringField("class", value.getClass().getName());
// 写入类型后缀
typeSer.writeTypeSuffix(gen, typeSer.typeId(value.getClass(), JsonToken.START_OBJECT));
}
}
}

View File

@@ -5,30 +5,32 @@ 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.hibernate.proxy.LazyInitializer;
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.core.JsonToken;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.DeserializationConfig;
import com.fasterxml.jackson.databind.JsonDeserializer;
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.deser.BeanDeserializerModifier;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
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;
@@ -43,7 +45,6 @@ public class JacksonConfig {
@Bean
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
ObjectMapper objectMapper = builder.build();
// 关闭日期时间格式化输出为时间戳而是输出为ISO格式的字符串
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
@@ -52,6 +53,9 @@ public class JacksonConfig {
// 处理循环引用,启用引用处理功能
objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
// 禁用在遇到空Bean时抛出异常
objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
// 配置Java 8时间模块的序列化格式
JavaTimeModule javaTimeModule = new JavaTimeModule();
// LocalDate
@@ -63,154 +67,23 @@ public class JacksonConfig {
// LocalDateTime
javaTimeModule.addSerializer(LocalDateTime.class,
new LocalDateTimeSerializer(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
javaTimeModule.addDeserializer(LocalDateTime.class,
new LocalDateTimeDeserializer(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
// 自定义LocalDateTime反序列化器支持多种格式
javaTimeModule.addDeserializer(LocalDateTime.class, new CustomLocalDateTimeDeserializer());
objectMapper.registerModule(javaTimeModule);
// 添加自定义模块用于处理JPA/Hibernate代理对象
SimpleModule proxyModule = new SimpleModule("HibernateProxyModule");
// 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;
}
});
// // 添加懒加载初始化器序列化器
// proxyModule.addSerializer(LazyInitializer.class, new
// HibernateProxySerializer());
// // 添加Hibernate代理对象反序列化器
// proxyModule.addDeserializer(HibernateProxy.class, new
// HibernateProxyDeserializer());
objectMapper.registerModule(proxyModule);
// 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();
}
}
}
}
/**
* 用于处理IdentityEntity类型的序列化器包装器
*/
private static class IdentityEntitySerializer extends StdSerializer<Object> {
private final JsonSerializer<?> delegate;
protected IdentityEntitySerializer(JsonSerializer<?> delegate) {
super(Object.class);
this.delegate = delegate;
}
@SuppressWarnings("unchecked")
@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();
}
}
}
}
}

View File

@@ -0,0 +1,131 @@
package com.ecep.contract.config;
import java.time.Duration;
import org.hibernate.Hibernate;
import org.hibernate.proxy.HibernateProxy;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import com.ecep.contract.model.IdentityEntity;
import com.ecep.contract.util.HibernateProxyUtils;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.DeserializationConfig;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
/**
* Redis缓存配置类用于配置Redis的缓存管理器和序列化器
*/
@Configuration
@EnableCaching
public class RedisCacheConfig {
/**
* 配置RedisTemplate使用与JacksonConfig相同的ObjectMapper以确保Hibernate代理对象被正确序列化
*/
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory,
ObjectMapper objectMapper) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
// 设置键的序列化器
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
// 使用GenericJackson2JsonRedisSerializer并配置为使用我们自定义的ObjectMapper
// 这个ObjectMapper已经包含了处理Hibernate代理对象的序列化器
GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer(
objectMapper);
template.setValueSerializer(jackson2JsonRedisSerializer);
template.setHashValueSerializer(jackson2JsonRedisSerializer);
return template;
}
/**
* 配置RedisCacheManager使用与JacksonConfig相同的ObjectMapper以确保Hibernate代理对象被正确序列化
* 并启用类型信息存储以解决LinkedHashMap无法转换为具体类型的问题
*/
// @Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory, ObjectMapper objectMapper) {
// 创建ObjectMapper的副本而不是直接修改注入的实例
ObjectMapper cacheObjectMapper = objectMapper.copy();
// 配置ObjectMapper副本以保留类型信息仅用于Redis缓存
// 使用activateDefaultTyping代替已弃用的enableDefaultTyping
cacheObjectMapper.activateDefaultTyping(
cacheObjectMapper.getPolymorphicTypeValidator(),
ObjectMapper.DefaultTyping.NON_FINAL,
JsonTypeInfo.As.PROPERTY);
// 确保我们的HibernateProxyDeserializer被正确注册
// 创建一个新的模块来注册自定义反序列化器
SimpleModule proxyModule = new SimpleModule("CacheHibernateProxyModule");
// 添加代理对象序列化器只输出ID字段
proxyModule.addSerializer(HibernateProxy.class, new HibernateProxySerializer());
proxyModule.addDeserializer(HibernateProxy.class, new HibernateProxyDeserializer());
// 使用BeanSerializerModifier来处理IdentityEntity类型避免递归调用
proxyModule.setSerializerModifier(new BeanSerializerModifier() {
@Override
public JsonSerializer<?> modifySerializer(SerializationConfig config, BeanDescription beanDesc,
JsonSerializer<?> serializer) {
Class<?> beanClass = beanDesc.getBeanClass();
if (beanClass.isPrimitive()) {
return serializer;
}
System.out.println("modifySerializer:" + beanDesc.getBeanClass() + ", serializer:"
+ serializer);
return serializer;
}
});
proxyModule.setDeserializerModifier(new BeanDeserializerModifier() {
@Override
public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config,
BeanDescription beanDesc,
JsonDeserializer<?> deserializer) {
Class<?> beanClass = beanDesc.getBeanClass();
if (beanClass.isPrimitive()) {
return deserializer;
}
System.out.println("modifyDeserializer:" + beanDesc.getBeanClass() + ", deserializer:"
+ deserializer);
return deserializer;
}
});
cacheObjectMapper.registerModule(proxyModule);
// 创建Redis缓存配置使用包含Hibernate代理处理的ObjectMapper副本
RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofHours(6)) // 设置缓存过期时间为6小时
.serializeKeysWith(
RedisSerializationContext.SerializationPair
.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(
new GenericJackson2JsonRedisSerializer(cacheObjectMapper)))
.disableCachingNullValues(); // 不缓存null值
// 创建Redis缓存管理器为所有缓存名称配置相同的序列化策略以确保类型安全反序列化
return RedisCacheManager.builder(redisConnectionFactory)
.cacheDefaults(cacheConfiguration)
.build();
}
}

View File

@@ -130,7 +130,7 @@ public class SecurityConfig {
// 注意根据系统设计Employee实体中没有密码字段系统使用IP/MAC绑定认证
// 这里使用密码编码器加密后的固定密码,确保认证流程能够正常工作
return User.builder()
.username(employee.getName())
.username(employee.getAccount())
.password(passwordEncoder().encode("default123")) // 使用默认密码进行加密
.accountExpired(false) // 账户未过期
.accountLocked(false) // 账户未锁定