!248 紧急修复 Ip2Region InputStream读取函数导致的OOM问题

Merge pull request !248 from 疯狂的狮子Li/dev
This commit is contained in:
疯狂的狮子Li 2025-12-23 06:45:57 +00:00 committed by Gitee
commit a87450ec2c
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
4 changed files with 54 additions and 5 deletions

View File

@ -1,5 +1,6 @@
package org.dromara.common.core.utils.ip;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.exception.ServiceException;
@ -8,6 +9,7 @@ import org.lionsoul.ip2region.service.Config;
import org.lionsoul.ip2region.service.Ip2Region;
import org.lionsoul.ip2region.xdb.Util;
import java.io.File;
import java.io.InputStream;
import java.time.Duration;
@ -43,11 +45,18 @@ public class RegionUtils {
// 因为加载整个xdb文件会耗费非常大的内存如果你不希望加载整个xdb到内存中更推荐使用 VIndexCache NoCache即实时读取文件策略和 setXdbPath/setXdbFile 加载方法需要注意的一点setXdbPath setXdbFile 不支持读取ClassPath即源码和resource目录中的文件
// 一般而言更建议把xdb数据库放到一个指定的文件目录中即不打包进jar包中然后使用 NoCache + 配合SearcherPool的并发池读取数据更方便随时更新xdb数据库
// TODO 2025年12月23日 Ip2Region封装的 InputStream 读取函数 Searcher.loadContentFromInputStream 在Linux环境下会申请过大的byte[]空间而导致OOM这里先用临时文件的方案解决等后续 Ip2Region 更新解决方案
// 创建临时文件
File v4TempXdb = FileUtil.writeFromStream(ResourceUtil.getStream(DEFAULT_IPV4_XDB_PATH), FileUtil.createTempFile());
// IPv4配置
Config v4Config = Config.custom()
.setCachePolicy(Config.BufferCache)
.setXdbInputStream(ResourceUtil.getStream(DEFAULT_IPV4_XDB_PATH))
.setXdbFile(v4TempXdb)
// .setXdbInputStream(ResourceUtil.getStream(DEFAULT_IPV4_XDB_PATH))
.asV4();
// 删除临时文件
v4TempXdb.delete();
// IPv6配置
Config v6Config = null;
@ -55,10 +64,17 @@ public class RegionUtils {
if (v6XdbInputStream == null) {
log.warn("未加载 IPv6 地址库:未在类路径下找到文件 {}。当前仅启用 IPv4 查询。如需启用 IPv6请将 ip2region_v6.xdb 放置到 resources 目录", DEFAULT_IPV6_XDB_PATH);
} else {
// 创建临时文件
File v6TempXdb = FileUtil.writeFromStream(ResourceUtil.getStream(DEFAULT_IPV4_XDB_PATH), FileUtil.createTempFile());
v6Config = Config.custom()
.setCachePolicy(Config.BufferCache)
.setXdbInputStream(v6XdbInputStream)
.setXdbFile(v6TempXdb)
// .setXdbInputStream(v6XdbInputStream)
.asV6();
// 删除临时文件
v6TempXdb.delete();
}
// 初始化Ip2Region实例

View File

@ -1,7 +1,9 @@
package org.dromara.common.mybatis.service;
import org.apache.dubbo.config.annotation.DubboReference;
import org.dromara.common.core.constant.CacheNames;
import org.dromara.system.api.RemoteDataScopeService;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
/**
@ -24,6 +26,7 @@ public class SysDataScopeService {
* @param roleId 角色ID
* @return 返回角色的自定义权限语句如果没有找到则返回 null
*/
@Cacheable(cacheNames = CacheNames.SYS_ROLE_CUSTOM, key = "#roleId", condition = "#roleId != null")
public String getRoleCustom(Long roleId) {
return remoteDataScopeService.getRoleCustom(roleId);
}
@ -34,6 +37,7 @@ public class SysDataScopeService {
* @param deptId 部门ID
* @return 返回部门及其下级的权限语句如果没有找到则返回 null
*/
@Cacheable(cacheNames = CacheNames.SYS_DEPT_AND_CHILD, key = "#deptId", condition = "#deptId != null")
public String getDeptAndChild(Long deptId) {
return remoteDataScopeService.getDeptAndChild(deptId);
}

View File

@ -1,12 +1,19 @@
package org.dromara.common.translation.core.impl;
import cn.hutool.core.convert.Convert;
import lombok.AllArgsConstructor;
import org.apache.dubbo.config.annotation.DubboReference;
import org.dromara.common.core.constant.CacheNames;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.redis.utils.CacheUtils;
import org.dromara.common.translation.annotation.TranslationType;
import org.dromara.common.translation.constant.TransConstant;
import org.dromara.common.translation.core.TranslationInterface;
import org.dromara.system.api.RemoteUserService;
import java.util.ArrayList;
import java.util.List;
/**
* 用户昵称翻译实现
*
@ -22,9 +29,22 @@ public class NicknameTranslationImpl implements TranslationInterface<String> {
@Override
public String translation(Object key, String other) {
if (key instanceof Long id) {
return remoteUserService.selectNicknameByIds(id.toString());
String nickname = CacheUtils.get(CacheNames.SYS_NICKNAME, key);
if (StringUtils.isNotBlank(nickname)) {
return nickname;
}
return remoteUserService.selectNicknameById(id);
} else if (key instanceof String ids) {
return remoteUserService.selectNicknameByIds(ids);
List<String> list = new ArrayList<>();
for (Long id : StringUtils.splitTo(ids, Convert::toLong)) {
String nickname = CacheUtils.get(CacheNames.SYS_NICKNAME, key);
if (StringUtils.isNotBlank(nickname)) {
list.add(nickname);
} else {
list.add(remoteUserService.selectNicknameById(id));
}
}
return StringUtils.joinComma(list);
}
return null;
}

View File

@ -1,5 +1,9 @@
package org.dromara.common.translation.core.impl;
import cn.hutool.core.convert.Convert;
import org.dromara.common.core.constant.CacheNames;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.redis.utils.CacheUtils;
import org.dromara.common.translation.annotation.TranslationType;
import org.dromara.common.translation.constant.TransConstant;
import org.dromara.common.translation.core.TranslationInterface;
@ -21,6 +25,11 @@ public class UserNameTranslationImpl implements TranslationInterface<String> {
@Override
public String translation(Object key, String other) {
return remoteUserService.selectUserNameById((Long) key);
Long userId = Convert.toLong(key);
String username = CacheUtils.get(CacheNames.SYS_USER_NAME, userId);
if (StringUtils.isNotBlank(username)) {
return username;
}
return remoteUserService.selectUserNameById(userId);
}
}