重构模型类包结构,将模型类按功能模块划分到不同的子包中。优化序列化处理,为VO类添加serialVersionUID并实现Serializable接口。移除部分冗余的serialVersionUID字段,简化模型类代码。同时修复UITools中空值处理的问题,并更新pom版本至0.0.100-SNAPSHOT。 - 将模型类按功能模块划分到ds子包中 - 为VO类添加序列化支持 - 移除冗余的serialVersionUID字段 - 修复UITools空值处理问题 - 更新项目版本号
10 KiB
10 KiB
WebSocket服务组件修改方案
1. 概述
基于对WebSocket服务组件的分析,本方案提出对WebSocketServerCallbackManager类进行优化,重点改进泛型类型处理逻辑、增强类型安全检查、实现类型缓存机制,以提高系统的性能、稳定性和可维护性。
2. 修改目标
- 实现类型缓存机制,避免重复解析泛型参数
- 优化类型解析逻辑,提高代码可读性和健壮性
- 增加类型安全检查,防止运行时类型错误
- 完善错误处理机制,提供更详细的异常信息
- 增强对Spring代理类的处理能力
3. 详细修改方案
3.1 优化WebSocketServerCallbackManager类
3.1.1 实现类型缓存机制
在WebSocketServerCallbackManager类中添加一个静态缓存Map,用于存储已解析的实体类型:
// 添加类型缓存,避免重复解析泛型参数
private static final Map<Class<?>, Class<?>> ENTITY_TYPE_CACHE = new ConcurrentHashMap<>();
/**
* 从缓存获取实体类型
*/
@SuppressWarnings("unchecked")
private <T> Class<T> getEntityTypeFromCache(Class<?> serviceClass) {
return (Class<T>) ENTITY_TYPE_CACHE.get(serviceClass);
}
/**
* 缓存实体类型
*/
private <T> void cacheEntityType(Class<?> serviceClass, Class<T> entityClass) {
ENTITY_TYPE_CACHE.put(serviceClass, entityClass);
}
3.1.2 优化createNewEntity方法
修改createNewEntity方法,使用缓存机制并优化类型解析逻辑:
private <T> T createNewEntity(IEntityService<T> entityService) {
try {
// 获取服务类
Class<?> serviceClass = entityService.getClass();
// 1. 尝试从缓存获取实体类型
Class<T> entityClass = getEntityTypeFromCache(serviceClass);
if (entityClass != null) {
return createInstance(entityClass);
}
// 2. 直接检查接口
entityClass = findEntityTypeInInterfaces(serviceClass);
if (entityClass != null) {
cacheEntityType(serviceClass, entityClass);
return createInstance(entityClass);
}
// 3. 处理Spring代理类 - 获取原始类
Class<?> targetClass = getTargetClass(serviceClass);
if (targetClass != serviceClass) {
entityClass = findEntityTypeInInterfaces(targetClass);
if (entityClass != null) {
cacheEntityType(serviceClass, entityClass);
return createInstance(entityClass);
}
}
// 4. 尝试查找父类
entityClass = findEntityTypeInSuperclass(serviceClass);
if (entityClass != null) {
cacheEntityType(serviceClass, entityClass);
return createInstance(entityClass);
}
// 5. 如果上述方法都失败,尝试从参数类型推断
entityClass = findEntityTypeFromMethodParameters(serviceClass);
if (entityClass != null) {
cacheEntityType(serviceClass, entityClass);
return createInstance(entityClass);
}
// 如果所有方法都失败,抛出更具描述性的异常
throw new UnsupportedOperationException(
String.format("无法确定实体类型,请检查服务实现: %s, 实现的接口: %s",
serviceClass.getName(),
Arrays.toString(serviceClass.getInterfaces())));
} catch (Exception e) {
throw new RuntimeException("无法创建Entity实例: " + e.getMessage(), e);
}
}
/**
* 创建实例的辅助方法
*/
private <T> T createInstance(Class<T> entityClass) {
try {
return entityClass.getDeclaredConstructor().newInstance();
} catch (Exception e) {
throw new RuntimeException(
String.format("无法创建%s的实例,请确保该类有公共无参构造函数", entityClass.getName()), e);
}
}
3.1.3 增强类型安全检查
在各个方法中增加类型安全检查,防止类型转换错误:
private Object invokerSaveMethod(Object service, JsonNode argumentsNode) throws JsonMappingException {
JsonNode paramsNode = argumentsNode.get(0);
if (service instanceof IEntityService<?> entityService) {
Object entity = null;
if (paramsNode.has("id") && !paramsNode.get("id").isNull()) {
int id = paramsNode.get("id").asInt();
entity = entityService.getById(id);
if (entity == null) {
throw new NoSuchElementException("未找到实体: #" + id);
}
} else {
entity = createNewEntity(entityService);
}
if (service instanceof VoableService<?, ?>) {
String typeClz = argumentsNode.get(1).asText();
Class<?> type = null;
try {
type = Class.forName(typeClz);
// 增加类型安全检查
if (!VoableService.class.isAssignableFrom(service.getClass())) {
throw new IllegalArgumentException(
String.format("服务%s未实现VoableService接口", service.getClass().getName()));
}
} catch (ClassNotFoundException e) {
throw new RuntimeException("无法加载类型: " + typeClz, e);
}
Object object = objectMapper.convertValue(paramsNode, type);
((VoableService<Object, Object>) service).updateByVo(entity, object);
} else {
objectMapper.updateValue(entity, paramsNode);
}
return ((IEntityService<Object>) entityService).save(entity);
}
throw new IllegalArgumentException(
String.format("服务%s未实现IEntityService接口", service.getClass().getName()));
}
3.1.4 优化findAll方法的类型处理
private Object invokerFindAllMethod(Object service, JsonNode argumentsNode) throws JsonProcessingException {
// 增加类型安全检查
if (!(service instanceof QueryService<?>)) {
throw new IllegalArgumentException(
String.format("服务%s未实现QueryService接口", service.getClass().getName()));
}
JsonNode paramsNode = argumentsNode.get(0);
JsonNode pageableNode = argumentsNode.get(1);
// 增加参数校验
if (pageableNode == null) {
throw new IllegalArgumentException("分页参数不能为空");
}
PageArgument pageArgument = objectMapper.treeToValue(pageableNode, PageArgument.class);
QueryService<?> queryService = (QueryService<?>) service;
try {
Page<?> page = queryService.findAll(paramsNode, pageArgument.toPageable());
return PageContent.of(page.map(entity -> {
if (entity instanceof Voable<?>) {
return ((Voable<?>) entity).toVo();
}
return entity;
}));
} catch (Exception e) {
throw new RuntimeException("查询数据失败: " + e.getMessage(), e);
}
}
3.1.5 增强getTargetClass方法
增强对Spring代理类的处理能力:
/**
* 获取被代理的原始类
*/
private Class<?> getTargetClass(Class<?> proxyClass) {
// 处理CGLIB代理类
if (proxyClass.getName().contains("$$SpringCGLIB$$")) {
Class<?> superClass = proxyClass.getSuperclass();
// 确保返回的不是Object类
return (superClass != null && superClass != Object.class) ? superClass : proxyClass;
}
// 处理JDK动态代理类
if (Proxy.isProxyClass(proxyClass)) {
InvocationHandler handler = Proxy.getInvocationHandler(proxyClass);
// 这里可以根据实际情况进一步处理JDK代理类
}
return proxyClass;
}
3.2 添加日志和监控
在关键方法中添加详细日志,方便问题排查和性能监控:
private Object handleAsMessageCallback(SessionInfo session, String messageId, JsonNode jsonNode) throws Exception {
long startTime = System.currentTimeMillis();
logger.debug("开始处理消息回调: {}, 服务: {}, 方法: {}",
messageId,
jsonNode.get(WebSocketConstant.SERVICE_FIELD_NAME),
jsonNode.get(WebSocketConstant.METHOD_FIELD_NAME));
try {
// 原有逻辑...
Object result = null;
// 处理逻辑...
logger.debug("处理消息回调完成: {}, 耗时: {}ms", messageId, (System.currentTimeMillis() - startTime));
return result;
} catch (Exception e) {
logger.error("处理消息回调失败: {}, 耗时: {}ms", messageId, (System.currentTimeMillis() - startTime), e);
throw e;
}
}
4. 测试用例设计
为了验证修改后的WebSocket服务组件的正确性和性能,建议设计以下测试用例:
4.1 功能测试
- 基本CRUD操作测试:测试通过WebSocket进行实体的创建、查询、更新和删除操作
- 分页查询测试:测试不同分页参数下的查询功能
- 类型安全测试:测试各种边缘情况下的类型处理是否正确
4.2 性能测试
- 并发请求测试:模拟多用户并发访问WebSocket服务
- 缓存效果测试:验证类型缓存机制的性能提升效果
4.3 异常处理测试
- 参数错误测试:测试各种参数错误情况下的异常处理
- 类型转换错误测试:测试类型转换失败情况下的异常处理
5. 实施计划
- 准备阶段:创建分析报告和修改方案文档
- 编码阶段:按照修改方案实现代码优化
- 测试阶段:编写并执行测试用例,验证修改效果
- 验证阶段:生成验证报告,确认修改满足需求
6. 风险评估
-
兼容性风险:修改可能影响现有功能的兼容性
- 应对措施:全面测试,确保与现有系统兼容
-
性能风险:缓存机制可能引入内存占用增加的风险
- 应对措施:监控内存使用情况,必要时调整缓存策略
-
实现风险:优化逻辑可能引入新的bug
- 应对措施:编写详细的测试用例,进行充分测试
7. 总结
本修改方案针对WebSocket服务组件中的泛型类型处理问题提出了全面的优化措施,包括实现类型缓存机制、优化类型解析逻辑、增强类型安全检查、完善错误处理机制等。这些优化将有助于提高系统的性能、稳定性和可维护性,为后续的功能扩展奠定良好基础。