Compare commits
2 Commits
ed74d6073f
...
d0f3648087
Author | SHA1 | Date | |
---|---|---|---|
d0f3648087 | |||
4d31f4d12c |
@ -2,6 +2,7 @@ package com.coscoshipping.ebtp.system.dict.service.impl;
|
||||
|
||||
|
||||
import cn.hutool.core.collection.ListUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.chinaunicom.mall.ebtp.common.base.service.impl.BaseServiceImpl;
|
||||
@ -76,13 +77,9 @@ public class DictProjectServiceImpl extends BaseServiceImpl<DictProjectMapper, D
|
||||
@Override
|
||||
public List<DictProject> selectDictList(DictProject dictProject) {
|
||||
|
||||
if (dictProject != null && dictProject.getCode() != null && dictProject.getParentType() != null) {
|
||||
return this.list(Wrappers.<DictProject>lambdaQuery()
|
||||
.eq(DictProject::getCode, dictProject.getCode())
|
||||
.eq(DictProject::getParentType, dictProject.getParentType())
|
||||
.last("limit 1"));
|
||||
}
|
||||
return ListUtil.empty();
|
||||
return this.list(Wrappers.<DictProject>lambdaQuery()
|
||||
.eq(StrUtil.isNotBlank(dictProject.getCode()), DictProject::getCode, dictProject.getCode())
|
||||
.eq(StrUtil.isNotBlank(dictProject.getParentType()), DictProject::getParentType, dictProject.getParentType()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,48 @@
|
||||
package com.coscoshipping.ebtp.system.org.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.serializer.GenericToStringSerializer;
|
||||
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 组织机构缓存配置类
|
||||
* 配置专门的RedisTemplate用于组织机构缓存,使用Java原生序列化提高性能
|
||||
*
|
||||
* @author system
|
||||
*/
|
||||
@Configuration
|
||||
public class OrgCacheConfig {
|
||||
|
||||
/**
|
||||
* 组织机构专用RedisTemplate配置
|
||||
* 使用Java原生序列化,避免JSON转换开销
|
||||
*
|
||||
* @param redisConnectionFactory Redis连接工厂
|
||||
* @return 配置好的RedisTemplate
|
||||
*/
|
||||
@Bean(name = "orgCacheRedisTemplate")
|
||||
public RedisTemplate<String, List> orgCacheRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
|
||||
RedisTemplate<String, List> redisTemplate = new RedisTemplate<>();
|
||||
redisTemplate.setConnectionFactory(redisConnectionFactory);
|
||||
|
||||
// 使用String序列化器处理key
|
||||
redisTemplate.setKeySerializer(new GenericToStringSerializer<>(String.class));
|
||||
redisTemplate.setHashKeySerializer(new GenericToStringSerializer<>(String.class));
|
||||
|
||||
// 使用Java原生序列化器处理value,避免JSON转换
|
||||
JdkSerializationRedisSerializer jdkSerializer = new JdkSerializationRedisSerializer();
|
||||
redisTemplate.setValueSerializer(jdkSerializer);
|
||||
redisTemplate.setHashValueSerializer(jdkSerializer);
|
||||
|
||||
// 启用事务支持
|
||||
redisTemplate.setEnableTransactionSupport(true);
|
||||
|
||||
redisTemplate.afterPropertiesSet();
|
||||
return redisTemplate;
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package com.coscoshipping.ebtp.system.org.config;
|
||||
|
||||
import com.coscoshipping.ebtp.system.org.manager.OrgCacheManager;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.ApplicationArguments;
|
||||
import org.springframework.boot.ApplicationRunner;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 组织机构缓存初始化器
|
||||
* 在系统启动时自动初始化组织机构数据到Redis缓存
|
||||
*
|
||||
* @author system
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@Order(1) // 设置执行顺序,确保在其他组件之前执行
|
||||
public class OrgCacheInitializer implements ApplicationRunner {
|
||||
|
||||
@Autowired
|
||||
private OrgCacheManager orgCacheManager;
|
||||
|
||||
@Override
|
||||
public void run(ApplicationArguments args) throws Exception {
|
||||
log.info("系统启动 - 开始初始化组织机构缓存");
|
||||
|
||||
try {
|
||||
// 初始化组织机构缓存
|
||||
orgCacheManager.initCache();
|
||||
log.info("系统启动 - 组织机构缓存初始化完成");
|
||||
|
||||
// 可选:执行性能测试(仅在需要时启用)
|
||||
// orgCacheManager.performanceTest(100);
|
||||
} catch (Exception e) {
|
||||
log.error("系统启动 - 组织机构缓存初始化失败", e);
|
||||
// 不抛出异常,避免影响系统启动
|
||||
}
|
||||
}
|
||||
}
|
@ -98,12 +98,17 @@ public class SysOrgController{
|
||||
*/
|
||||
@ApiOperation("查询列表数据")
|
||||
@GetMapping("/list")
|
||||
public BaseResponse<List<SysOrg>> list(@ApiParam(value = "查询对象数据", required = false) SysOrg param) {
|
||||
public BaseResponse<List<SysOrg>> list(@ApiParam(value = "查询对象数据", required = false) SysOrgVO param) {
|
||||
//查询
|
||||
LambdaQueryWrapper<SysOrg> query = Wrappers.lambdaQuery(param);
|
||||
|
||||
// 处理多orgId查询条件
|
||||
if (param.getAllDepartmentId() != null && !param.getAllDepartmentId().trim().isEmpty()) {
|
||||
String[] orgIds = param.getAllDepartmentId().split(",");
|
||||
query.in(SysOrg::getOrgId, orgIds);
|
||||
}
|
||||
|
||||
List<SysOrg> list = iSysOrgService.list(query);
|
||||
//异常处理
|
||||
//RespsExceptionEnum.FRAME_EXCEPTION_DEMO_NOT_FIND.customValid(list.isEmpty());
|
||||
return BaseResponse.success(list);
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,163 @@
|
||||
package com.coscoshipping.ebtp.system.org.manager;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.coscoshipping.ebtp.system.org.entity.SysOrg;
|
||||
import com.coscoshipping.ebtp.system.org.service.SysOrgService;
|
||||
import com.coscoshipping.ebtp.system.org.util.CachePerformanceTest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 组织机构缓存管理器
|
||||
* 负责组织机构数据的Redis缓存操作
|
||||
*
|
||||
* @author system
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class OrgCacheManager {
|
||||
|
||||
private static final String ORG_CACHE_KEY = "sys:org:all";
|
||||
private static final long CACHE_EXPIRE_TIME = 24; // 24小时过期
|
||||
|
||||
@Autowired
|
||||
@Qualifier("cacheRedisTemplate")
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
@Autowired
|
||||
private SysOrgService sysOrgService;
|
||||
|
||||
/**
|
||||
* 初始化缓存 - 系统启动时调用
|
||||
*/
|
||||
public void initCache() {
|
||||
log.info("开始初始化组织机构缓存...");
|
||||
try {
|
||||
// 从数据库查询所有组织机构数据
|
||||
List<SysOrg> allOrgs = sysOrgService.list(new LambdaQueryWrapper<SysOrg>()
|
||||
.eq(SysOrg::getDeleteFlag, "normal")
|
||||
.orderByAsc(SysOrg::getSort));
|
||||
|
||||
if (!CollectionUtils.isEmpty(allOrgs)) {
|
||||
// 直接将List<SysOrg>存入Redis缓存,无需JSON转换
|
||||
redisTemplate.opsForValue().set(ORG_CACHE_KEY, allOrgs, CACHE_EXPIRE_TIME, TimeUnit.HOURS);
|
||||
log.info("组织机构缓存初始化完成,共缓存{}条记录", allOrgs.size());
|
||||
|
||||
// 可选:执行性能测试(仅在开发环境建议启用)
|
||||
// CachePerformanceTest.comparePerformance(allOrgs, 100);
|
||||
} else {
|
||||
log.warn("数据库中没有找到组织机构数据");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("初始化组织机构缓存失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从缓存中获取所有组织机构数据
|
||||
*
|
||||
* @return 组织机构列表,如果缓存中没有数据则返回null
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<SysOrg> getAllOrgsFromCache() {
|
||||
try {
|
||||
Object cacheData = redisTemplate.opsForValue().get(ORG_CACHE_KEY);
|
||||
if (cacheData != null) {
|
||||
log.debug("从缓存中获取组织机构数据");
|
||||
return (List<SysOrg>) cacheData;
|
||||
} else {
|
||||
log.debug("缓存中没有组织机构数据");
|
||||
return null;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("从缓存获取组织机构数据失败", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新缓存 - 增删改操作后调用
|
||||
*/
|
||||
public void refreshCache() {
|
||||
log.info("开始刷新组织机构缓存...");
|
||||
try {
|
||||
// 先删除旧缓存
|
||||
redisTemplate.delete(ORG_CACHE_KEY);
|
||||
|
||||
// 重新初始化缓存
|
||||
initCache();
|
||||
|
||||
log.info("组织机构缓存刷新完成");
|
||||
} catch (Exception e) {
|
||||
log.error("刷新组织机构缓存失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除缓存
|
||||
*/
|
||||
public void clearCache() {
|
||||
try {
|
||||
redisTemplate.delete(ORG_CACHE_KEY);
|
||||
log.info("组织机构缓存已清除");
|
||||
} catch (Exception e) {
|
||||
log.error("清除组织机构缓存失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查缓存是否存在
|
||||
*
|
||||
* @return true 如果缓存存在,false 如果缓存不存在
|
||||
*/
|
||||
public boolean isCacheExists() {
|
||||
try {
|
||||
return Boolean.TRUE.equals(redisTemplate.hasKey(ORG_CACHE_KEY));
|
||||
} catch (Exception e) {
|
||||
log.error("检查缓存是否存在时出错", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 延长缓存过期时间
|
||||
*/
|
||||
public void extendCacheExpire() {
|
||||
try {
|
||||
redisTemplate.expire(ORG_CACHE_KEY, CACHE_EXPIRE_TIME, TimeUnit.HOURS);
|
||||
log.debug("组织机构缓存过期时间已延长");
|
||||
} catch (Exception e) {
|
||||
log.error("延长缓存过期时间失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行缓存性能测试
|
||||
* 比较JSON序列化与Java原生序列化的性能差异
|
||||
*
|
||||
* @param testCount 测试次数,建议100-1000次
|
||||
*/
|
||||
public void performanceTest(int testCount) {
|
||||
try {
|
||||
List<SysOrg> allOrgs = sysOrgService.list(new LambdaQueryWrapper<SysOrg>()
|
||||
.eq(SysOrg::getDeleteFlag, "normal"));
|
||||
|
||||
if (!CollectionUtils.isEmpty(allOrgs)) {
|
||||
log.info("开始执行组织机构缓存性能测试...");
|
||||
CachePerformanceTest.comparePerformance(allOrgs, testCount);
|
||||
log.info("组织机构缓存性能测试完成");
|
||||
} else {
|
||||
log.warn("没有组织机构数据,无法进行性能测试");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("执行缓存性能测试失败", e);
|
||||
}
|
||||
}
|
||||
}
|
@ -10,6 +10,7 @@ import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
@ -26,6 +27,7 @@ import com.coscoshipping.ebtp.system.org.entity.SysOrg;
|
||||
import com.coscoshipping.ebtp.system.org.entity.vo.SysOrgVO;
|
||||
import com.coscoshipping.ebtp.system.org.service.SysOrgService;
|
||||
import com.coscoshipping.ebtp.system.org.util.CommonUtil;
|
||||
import com.coscoshipping.ebtp.system.org.manager.OrgCacheManager;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
|
||||
@ -37,6 +39,9 @@ import cn.hutool.core.bean.BeanUtil;
|
||||
@Service
|
||||
public class SysOrgServiceImpl extends BaseServiceImpl<SysOrgMapper, SysOrg> implements SysOrgService {
|
||||
|
||||
@Autowired
|
||||
private OrgCacheManager orgCacheManager;
|
||||
|
||||
@Override
|
||||
public IPage<SysOrg> getPage(SysOrgVO SysOrgVO) {
|
||||
LambdaQueryWrapper<SysOrg> query = buildQueryWrapper(SysOrgVO);
|
||||
@ -79,9 +84,15 @@ public class SysOrgServiceImpl extends BaseServiceImpl<SysOrgMapper, SysOrg> imp
|
||||
return buildOrgTree(orgList, org);
|
||||
}
|
||||
|
||||
// 3. 没有条件,才全查
|
||||
List<SysOrg> allOrgList = this.list();
|
||||
if (CollectionUtils.isEmpty(allOrgList)) return new ArrayList<>();
|
||||
// 3. 没有条件,才全查 - 优先从缓存获取
|
||||
List<SysOrg> allOrgList = orgCacheManager.getAllOrgsFromCache();
|
||||
if (CollectionUtils.isEmpty(allOrgList)) {
|
||||
// 缓存中没有数据,从数据库查询
|
||||
allOrgList = this.list();
|
||||
if (CollectionUtils.isEmpty(allOrgList)) return new ArrayList<>();
|
||||
// 如果数据库有数据但缓存没有,刷新缓存
|
||||
orgCacheManager.refreshCache();
|
||||
}
|
||||
return buildOrgTree(allOrgList, org);
|
||||
}
|
||||
|
||||
@ -165,7 +176,14 @@ public class SysOrgServiceImpl extends BaseServiceImpl<SysOrgMapper, SysOrg> imp
|
||||
SysOrg full = this.buildOrgFullPath(vo);
|
||||
vo.setOrgFullId(full.getOrgFullId()).setOrgFullName(full.getOrgFullName());
|
||||
validEntityBeforeSave(vo, false);
|
||||
return baseMapper.insert(vo) > 0;
|
||||
boolean result = baseMapper.insert(vo) > 0;
|
||||
|
||||
// 新增成功后刷新缓存
|
||||
if (result) {
|
||||
orgCacheManager.refreshCache();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -175,7 +193,14 @@ public class SysOrgServiceImpl extends BaseServiceImpl<SysOrgMapper, SysOrg> imp
|
||||
vo.setOrgFullId(full.getOrgFullId()).setOrgFullName(full.getOrgFullName());
|
||||
// 删除机构与人员关联
|
||||
// roleMenuService.remove(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, vo.getRoleId()));
|
||||
return baseMapper.updateById(vo) > 0;
|
||||
boolean result = baseMapper.updateById(vo) > 0;
|
||||
|
||||
// 更新成功后刷新缓存
|
||||
if (result) {
|
||||
orgCacheManager.refreshCache();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@ -186,7 +211,14 @@ public class SysOrgServiceImpl extends BaseServiceImpl<SysOrgMapper, SysOrg> imp
|
||||
CommonExceptionEnum.FRAME_EXCEPTION_COMMON_DATA_OTHER_ERROR.customValidName("存在下级组织,不可删除", !orgList.isEmpty());
|
||||
// 删除机构与人员关联
|
||||
// roleMenuService.remove(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, roleId));
|
||||
return this.removeById(orgId);
|
||||
boolean result = this.removeById(orgId);
|
||||
|
||||
// 删除成功后刷新缓存
|
||||
if (result) {
|
||||
orgCacheManager.refreshCache();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,113 @@
|
||||
package com.coscoshipping.ebtp.system.org.util;
|
||||
|
||||
import com.chinaunicom.mall.ebtp.common.util.JsonUtils;
|
||||
import com.coscoshipping.ebtp.system.org.entity.SysOrg;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 缓存性能测试工具类
|
||||
* 用于比较JSON序列化与Java原生序列化的性能差异
|
||||
*
|
||||
* @author system
|
||||
*/
|
||||
@Slf4j
|
||||
public class CachePerformanceTest {
|
||||
|
||||
/**
|
||||
* 测试JSON序列化性能
|
||||
*
|
||||
* @param orgList 组织机构列表
|
||||
* @param testCount 测试次数
|
||||
* @return 平均耗时(纳秒)
|
||||
*/
|
||||
public static long testJsonSerialization(List<SysOrg> orgList, int testCount) {
|
||||
long startTime = System.nanoTime();
|
||||
|
||||
for (int i = 0; i < testCount; i++) {
|
||||
// 序列化
|
||||
String json = JsonUtils.objectToJson(orgList);
|
||||
// 反序列化
|
||||
List<SysOrg> result = JsonUtils.jsonToList(json, SysOrg.class);
|
||||
}
|
||||
|
||||
long endTime = System.nanoTime();
|
||||
long avgTime = (endTime - startTime) / testCount;
|
||||
|
||||
log.info("JSON序列化测试完成,测试次数: {}, 平均耗时: {} 纳秒", testCount, avgTime);
|
||||
return avgTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试Java原生序列化性能
|
||||
*
|
||||
* @param orgList 组织机构列表
|
||||
* @param testCount 测试次数
|
||||
* @return 平均耗时(纳秒)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static long testJavaSerial(List<SysOrg> orgList, int testCount) {
|
||||
long startTime = System.nanoTime();
|
||||
|
||||
for (int i = 0; i < testCount; i++) {
|
||||
try {
|
||||
// 序列化
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
ObjectOutputStream oos = new ObjectOutputStream(bos);
|
||||
oos.writeObject(orgList);
|
||||
byte[] bytes = bos.toByteArray();
|
||||
oos.close();
|
||||
bos.close();
|
||||
|
||||
// 反序列化
|
||||
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
|
||||
ObjectInputStream ois = new ObjectInputStream(bis);
|
||||
List<SysOrg> result = (List<SysOrg>) ois.readObject();
|
||||
ois.close();
|
||||
bis.close();
|
||||
} catch (Exception e) {
|
||||
log.error("Java序列化测试失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
long endTime = System.nanoTime();
|
||||
long avgTime = (endTime - startTime) / testCount;
|
||||
|
||||
log.info("Java原生序列化测试完成,测试次数: {}, 平均耗时: {} 纳秒", testCount, avgTime);
|
||||
return avgTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* 比较两种序列化方式的性能
|
||||
*
|
||||
* @param orgList 组织机构列表
|
||||
* @param testCount 测试次数
|
||||
*/
|
||||
public static void comparePerformance(List<SysOrg> orgList, int testCount) {
|
||||
log.info("开始缓存性能测试,数据量: {} 条记录", orgList.size());
|
||||
|
||||
// 预热JVM
|
||||
testJsonSerialization(orgList, 10);
|
||||
testJavaSerial(orgList, 10);
|
||||
|
||||
// 正式测试
|
||||
long jsonTime = testJsonSerialization(orgList, testCount);
|
||||
long javaTime = testJavaSerial(orgList, testCount);
|
||||
|
||||
// 计算性能提升
|
||||
double improvement = ((double) (jsonTime - javaTime) / jsonTime) * 100;
|
||||
|
||||
log.info("=== 缓存性能测试结果 ===");
|
||||
log.info("JSON序列化平均耗时: {} 纳秒", jsonTime);
|
||||
log.info("Java原生序列化平均耗时: {} 纳秒", javaTime);
|
||||
log.info("性能提升: {:.2f}%", improvement);
|
||||
|
||||
if (improvement > 0) {
|
||||
log.info("Java原生序列化比JSON序列化快 {:.2f}%", improvement);
|
||||
} else {
|
||||
log.info("JSON序列化比Java原生序列化快 {:.2f}%", Math.abs(improvement));
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user