忽略本地配置文件
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -60,3 +60,6 @@ nbdist/
|
|||||||
local.sh
|
local.sh
|
||||||
.claude
|
.claude
|
||||||
/test-reports/
|
/test-reports/
|
||||||
|
ruoyi-admin/src/main/resources/application-local.yml
|
||||||
|
ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/impl/ESJobSearchImpl.java
|
||||||
|
ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/impl/JobTitleSuggestServiceImpl.java
|
||||||
@@ -1,158 +0,0 @@
|
|||||||
# 项目相关配置
|
|
||||||
ruoyi:
|
|
||||||
# 名称
|
|
||||||
name: RuoYi
|
|
||||||
# 版本
|
|
||||||
version: 3.8.8
|
|
||||||
# 版权年份
|
|
||||||
copyrightYear: 2024
|
|
||||||
# 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
|
|
||||||
profile: /Users/chenyanchang/logs/ruoyi/uploadPath
|
|
||||||
# 获取ip地址开关
|
|
||||||
addressEnabled: false
|
|
||||||
# 验证码类型 math 数字计算 char 字符验证
|
|
||||||
captchaType: math
|
|
||||||
|
|
||||||
# 数据源配置
|
|
||||||
spring:
|
|
||||||
datasource:
|
|
||||||
type: com.alibaba.druid.pool.DruidDataSource
|
|
||||||
driverClassName: com.highgo.jdbc.Driver
|
|
||||||
druid:
|
|
||||||
# 主库数据源
|
|
||||||
# master:
|
|
||||||
# url: jdbc:highgo://124.243.245.42:5866/shz?useUnicode=true&characterEncoding=utf8¤tSchema=shz&stringtype=unspecified
|
|
||||||
# #username: syssso
|
|
||||||
# username: sysdba
|
|
||||||
# password: ZKR2024@comzkr
|
|
||||||
# 正式环境
|
|
||||||
# master:
|
|
||||||
# url: jdbc:highgo://39.98.44.136:6023/highgo?useUnicode=true&characterEncoding=utf8¤tSchema=shz&stringtype=unspecified
|
|
||||||
# username: sysdba
|
|
||||||
# password: Hello@2026
|
|
||||||
# 测试环境
|
|
||||||
master:
|
|
||||||
url: jdbc:highgo://47.111.103.66:5866/highgo?useUnicode=true&characterEncoding=utf8¤tSchema=shz&stringtype=unspecified
|
|
||||||
username: sysdba
|
|
||||||
password: Hello@2026
|
|
||||||
# 从库数据源
|
|
||||||
slave:
|
|
||||||
# 从数据源开关/默认关闭
|
|
||||||
enabled: false
|
|
||||||
url:
|
|
||||||
username:
|
|
||||||
password:
|
|
||||||
# 初始连接数
|
|
||||||
initialSize: 10
|
|
||||||
# 最小连接池数量
|
|
||||||
minIdle: 30
|
|
||||||
# 最大连接池数量
|
|
||||||
maxActive: 50
|
|
||||||
# 配置获取连接等待超时的时间
|
|
||||||
maxWait: 60000
|
|
||||||
# 配置连接超时时间
|
|
||||||
connectTimeout: 30000
|
|
||||||
# 配置网络超时时间
|
|
||||||
socketTimeout: 60000
|
|
||||||
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
|
|
||||||
timeBetweenEvictionRunsMillis: 60000
|
|
||||||
# 配置一个连接在池中最小生存的时间,单位是毫秒
|
|
||||||
minEvictableIdleTimeMillis: 300000
|
|
||||||
# 配置一个连接在池中最大生存的时间,单位是毫秒
|
|
||||||
maxEvictableIdleTimeMillis: 900000
|
|
||||||
# 配置检测连接是否有效
|
|
||||||
validationQuery: SELECT version()
|
|
||||||
testWhileIdle: true
|
|
||||||
testOnBorrow: false
|
|
||||||
testOnReturn: false
|
|
||||||
webStatFilter:
|
|
||||||
enabled: true
|
|
||||||
statViewServlet:
|
|
||||||
enabled: true
|
|
||||||
# 设置白名单,不填则允许所有访问
|
|
||||||
allow:
|
|
||||||
url-pattern: /druid/*
|
|
||||||
# 控制台管理用户名和密码
|
|
||||||
login-username: ruoyi
|
|
||||||
login-password: 123456
|
|
||||||
filter:
|
|
||||||
stat:
|
|
||||||
enabled: true
|
|
||||||
# 慢SQL记录
|
|
||||||
log-slow-sql: true
|
|
||||||
slow-sql-millis: 1000
|
|
||||||
merge-sql: true
|
|
||||||
wall:
|
|
||||||
config:
|
|
||||||
multi-statement-allow: true
|
|
||||||
redis:
|
|
||||||
# 本地
|
|
||||||
#host: 127.0.0.1
|
|
||||||
#port: 6379
|
|
||||||
host: 124.243.245.42
|
|
||||||
port: 5379
|
|
||||||
# 数据库索引
|
|
||||||
database: 0
|
|
||||||
# 密码(本地通常无密码)
|
|
||||||
password:
|
|
||||||
# 连接超时时间
|
|
||||||
timeout: 100s
|
|
||||||
lettuce:
|
|
||||||
pool:
|
|
||||||
# 连接池中的最小空闲连接
|
|
||||||
min-idle: 0
|
|
||||||
# 连接池中的最大空闲连接
|
|
||||||
max-idle: 8
|
|
||||||
# 连接池的最大数据库连接数
|
|
||||||
max-active: 8
|
|
||||||
# #连接池最大阻塞等待时间(使用负值表示没有限制)
|
|
||||||
max-wait: -1ms
|
|
||||||
|
|
||||||
# easy-es
|
|
||||||
easy-es:
|
|
||||||
enable: true
|
|
||||||
banner: false
|
|
||||||
address: 124.243.245.42:9200
|
|
||||||
global-config:
|
|
||||||
process-index-mode: manual
|
|
||||||
db-config:
|
|
||||||
refresh-policy: immediate
|
|
||||||
username: elastic
|
|
||||||
password: zkr2024@@.com
|
|
||||||
|
|
||||||
#ai
|
|
||||||
chat:
|
|
||||||
baseUrl: http://39.98.44.136:8082
|
|
||||||
chatUrl: /v1/chat/completions
|
|
||||||
chatDetailUrl: /core/chat/getPaginationRecords
|
|
||||||
chatHistoryUrl: /core/chat/getHistories
|
|
||||||
updateNameUrl: /core/chat/updateHistory
|
|
||||||
stickChatUrl: /core/chat/updateHistory
|
|
||||||
delChatUrl: /core/chat/delHistory
|
|
||||||
delAllChatUrl: /core/chat/clearHistories
|
|
||||||
guestUrl: /v1/chat/completions
|
|
||||||
praiseUrl: /core/chat/feedback/updateUserFeedback
|
|
||||||
appId: 67cd49095e947ae0ca7fadd8
|
|
||||||
apiKey: fastgpt-qMl63276wPZvKAxEkW77bur0sSJpmuC6Ngg9lzyEjufLhsBAurjT55j
|
|
||||||
model: qd-job-turbo
|
|
||||||
|
|
||||||
audioText:
|
|
||||||
asr: http://127.0.0.1:8000/asr/file
|
|
||||||
tts: http://127.0.0.1:19527/synthesize
|
|
||||||
|
|
||||||
#浪潮单点登录相关
|
|
||||||
#互联网端:
|
|
||||||
lc_web_auth:
|
|
||||||
appId: cloud-out-2fb6330e9c0843e1a1424efda5d604c0
|
|
||||||
appSecret: x14lueHbtLQL7Pz2G7gE4wcGCV6TDblO5xfeu9V2wGk=
|
|
||||||
getTokenUrl: http://218.31.252.15:9081/prod-psout-api/auth/token
|
|
||||||
getUserInfoUrl: http://218.31.252.15:9081/prod-psout-api/system/app/authorize/user/info
|
|
||||||
editUserInfoUrl: http://218.31.252.15:9081/prod-psout-api/auth/user/edit
|
|
||||||
#监管端:
|
|
||||||
lc_cms_auth:
|
|
||||||
appId: cloud-9793ee8a8c3d47b8871007ffc4128502
|
|
||||||
appSecret: Yi+NACK70UPg8rFvsnnfBUq1wcLD4nm6ilC4II/4C4k=
|
|
||||||
getTokenUrl: http://218.31.252.15:9081/prod-api/auth/token
|
|
||||||
getUserInfoUrl: http://218.31.252.15:9081/prod-api/system/app/authorize/user/info
|
|
||||||
resrtPwdUrl: http://218.31.252.15:9081/prod-api/ps/user/resetPwd/zkr
|
|
||||||
changeStatusUrl: http://218.31.252.15:9081/prod-api/ps/user/change/status/zkr
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,187 +0,0 @@
|
|||||||
package com.ruoyi.cms.service.impl;
|
|
||||||
|
|
||||||
import com.ruoyi.cms.mapper.JobMapper;
|
|
||||||
import com.ruoyi.cms.service.IJobTitleSuggestService;
|
|
||||||
import com.ruoyi.cms.util.JobTitleSuggestTokenizer;
|
|
||||||
import com.ruoyi.common.core.redis.RedisCache;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.TreeMap;
|
|
||||||
import java.util.TreeSet;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 岗位名称 IK 分词联想服务实现。
|
|
||||||
*/
|
|
||||||
@Service
|
|
||||||
public class JobTitleSuggestServiceImpl implements IJobTitleSuggestService {
|
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(JobTitleSuggestServiceImpl.class);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Redis Hash:field 是 IK 分词,value 是包含该分词的完整岗位名称列表。
|
|
||||||
*/
|
|
||||||
private static final String CACHE_KEY = "app:job:title:suggest";
|
|
||||||
private static final String BUILDING_CACHE_KEY = CACHE_KEY + ":building";
|
|
||||||
private static final String LOCK_KEY = CACHE_KEY + ":rebuild:lock";
|
|
||||||
|
|
||||||
private static final int DEFAULT_LIMIT = 10;
|
|
||||||
private static final int MAX_LIMIT = 20;
|
|
||||||
private static final int LOCK_EXPIRE_MINUTES = 30;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private JobMapper jobMapper;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private RedisCache redisCache;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 确保服务启动后 Redis 中已有一份缓存;后续由 Quartz 定时任务周期性重建。
|
|
||||||
*/
|
|
||||||
@PostConstruct
|
|
||||||
public void init() {
|
|
||||||
rebuildCache();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<String> suggest(String keyword, Integer limit) {
|
|
||||||
String normalizedKeyword = JobTitleSuggestTokenizer.normalize(keyword);
|
|
||||||
if (normalizedKeyword.isEmpty()) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
int resultLimit = normalizeLimit(limit);
|
|
||||||
try {
|
|
||||||
Map<String, Object> tokenTitles = redisCache.getCacheMap(CACHE_KEY);
|
|
||||||
if (tokenTitles == null || tokenTitles.isEmpty()) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hash field 只来自 IK 分词;这里仅对已有词项做前缀过滤,不生成新的前缀词。
|
|
||||||
List<Map.Entry<String, Object>> matchedTokens = tokenTitles.entrySet().stream()
|
|
||||||
.filter(entry -> entry.getKey() != null)
|
|
||||||
.filter(entry -> entry.getKey().startsWith(normalizedKeyword))
|
|
||||||
.sorted(Map.Entry.comparingByKey())
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
Set<String> result = new LinkedHashSet<>();
|
|
||||||
for (Map.Entry<String, Object> entry : matchedTokens) {
|
|
||||||
if (result.size() >= resultLimit) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 先返回匹配到的 IK 分词本身。
|
|
||||||
result.add(entry.getKey());
|
|
||||||
|
|
||||||
// 再返回包含该 IK 分词的完整岗位名称。
|
|
||||||
appendTitles(result, entry.getValue(), resultLimit);
|
|
||||||
}
|
|
||||||
return new ArrayList<>(result).subList(0, Math.min(result.size(), resultLimit));
|
|
||||||
} catch (Exception e) {
|
|
||||||
// 联想属于非核心能力,Redis 异常时返回空列表,不影响岗位主搜索。
|
|
||||||
logger.warn("查询岗位名称 IK 分词缓存失败,keyword={}", keyword, e);
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void rebuildCache() {
|
|
||||||
String lockValue = UUID.randomUUID().toString();
|
|
||||||
boolean lockAcquired = false;
|
|
||||||
try {
|
|
||||||
lockAcquired = redisCache.setIfAbsent(
|
|
||||||
LOCK_KEY, lockValue, LOCK_EXPIRE_MINUTES, TimeUnit.MINUTES);
|
|
||||||
if (!lockAcquired) {
|
|
||||||
logger.info("其他节点正在重建岗位名称 IK 分词缓存,本节点跳过");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<String> sourceList = jobMapper.selectValidJobTitles();
|
|
||||||
Map<String, List<String>> cacheData = buildTokenTitles(sourceList);
|
|
||||||
|
|
||||||
// 先写临时 Hash,再原子替换正式 Hash,避免接口读到半成品。
|
|
||||||
redisCache.deleteObject(BUILDING_CACHE_KEY);
|
|
||||||
if (cacheData.isEmpty()) {
|
|
||||||
redisCache.deleteObject(CACHE_KEY);
|
|
||||||
} else {
|
|
||||||
redisCache.setCacheMap(BUILDING_CACHE_KEY, cacheData);
|
|
||||||
redisCache.redisTemplate.rename(BUILDING_CACHE_KEY, CACHE_KEY);
|
|
||||||
}
|
|
||||||
logger.info("岗位名称 IK 分词缓存重建完成,有效岗位名称{}个,IK 词{}个",
|
|
||||||
sourceList == null ? 0 : sourceList.size(), cacheData.size());
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error("重建岗位名称 IK 分词缓存失败", e);
|
|
||||||
} finally {
|
|
||||||
if (lockAcquired) {
|
|
||||||
redisCache.deleteObject(LOCK_KEY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<String, List<String>> buildTokenTitles(List<String> sourceList) {
|
|
||||||
Map<String, Set<String>> tokenTitles = new TreeMap<>();
|
|
||||||
if (sourceList == null) {
|
|
||||||
return Collections.emptyMap();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (String title : sourceList) {
|
|
||||||
String displayTitle = normalizeDisplayTitle(title);
|
|
||||||
if (displayTitle.isEmpty()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Set<String> tokens = JobTitleSuggestTokenizer.tokenize(displayTitle);
|
|
||||||
for (String token : tokens) {
|
|
||||||
tokenTitles.computeIfAbsent(token, key -> new TreeSet<>()).add(displayTitle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, List<String>> result = new LinkedHashMap<>();
|
|
||||||
for (Map.Entry<String, Set<String>> entry : tokenTitles.entrySet()) {
|
|
||||||
result.put(entry.getKey(), new ArrayList<>(entry.getValue()));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void appendTitles(Set<String> result, Object cachedTitles, int resultLimit) {
|
|
||||||
if (!(cachedTitles instanceof Iterable)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (Object cachedTitle : (Iterable<?>) cachedTitles) {
|
|
||||||
if (cachedTitle == null || result.size() >= resultLimit) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
String title = String.valueOf(cachedTitle);
|
|
||||||
if (!title.isEmpty()) {
|
|
||||||
result.add(title);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String normalizeDisplayTitle(String title) {
|
|
||||||
if (title == null) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
return title.trim().replaceAll("\\s+", " ");
|
|
||||||
}
|
|
||||||
|
|
||||||
private int normalizeLimit(Integer limit) {
|
|
||||||
if (limit == null) {
|
|
||||||
return DEFAULT_LIMIT;
|
|
||||||
}
|
|
||||||
return Math.max(1, Math.min(limit, MAX_LIMIT));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user