整理架构,初次提交
This commit is contained in:
@@ -1,241 +0,0 @@
|
||||
package com.ruoyi.cms.util;
|
||||
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.ruoyi.cms.domain.BussinessDictData;
|
||||
import com.ruoyi.common.constant.CacheConstants;
|
||||
import com.ruoyi.common.core.redis.RedisCache;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.utils.spring.SpringUtils;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 字典工具类
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class DictUtils
|
||||
{
|
||||
/**
|
||||
* 分隔符
|
||||
*/
|
||||
public static final String SEPARATOR = ",";
|
||||
|
||||
/**
|
||||
* 设置字典缓存
|
||||
*
|
||||
* @param key 参数键
|
||||
* @param dictDatas 字典数据列表
|
||||
*/
|
||||
public static void setDictCache(String key, List<BussinessDictData> dictDatas)
|
||||
{
|
||||
SpringUtils.getBean(RedisCache.class).setCacheObject(getCacheKey(key), dictDatas);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取字典缓存
|
||||
*
|
||||
* @param key 参数键
|
||||
* @return dictDatas 字典数据列表
|
||||
*/
|
||||
public static List<BussinessDictData> getDictCache(String key)
|
||||
{
|
||||
JSONArray arrayCache = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key));
|
||||
if (StringUtils.isNotNull(arrayCache))
|
||||
{
|
||||
return arrayCache.toList(BussinessDictData.class);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据字典类型和字典值获取字典标签
|
||||
*
|
||||
* @param dictType 字典类型
|
||||
* @param dictValue 字典值
|
||||
* @return 字典标签
|
||||
*/
|
||||
public static String getDictLabel(String dictType, String dictValue)
|
||||
{
|
||||
if (StringUtils.isEmpty(dictValue))
|
||||
{
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
return getDictLabel(dictType, dictValue, SEPARATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据字典类型和字典标签获取字典值
|
||||
*
|
||||
* @param dictType 字典类型
|
||||
* @param dictLabel 字典标签
|
||||
* @return 字典值
|
||||
*/
|
||||
public static String getDictValue(String dictType, String dictLabel)
|
||||
{
|
||||
if (StringUtils.isEmpty(dictLabel))
|
||||
{
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
return getDictValue(dictType, dictLabel, SEPARATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据字典类型和字典值获取字典标签
|
||||
*
|
||||
* @param dictType 字典类型
|
||||
* @param dictValue 字典值
|
||||
* @param separator 分隔符
|
||||
* @return 字典标签
|
||||
*/
|
||||
public static String getDictLabel(String dictType, String dictValue, String separator)
|
||||
{
|
||||
StringBuilder propertyString = new StringBuilder();
|
||||
List<BussinessDictData> datas = getDictCache(dictType);
|
||||
if (StringUtils.isNull(datas))
|
||||
{
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
if (StringUtils.containsAny(separator, dictValue))
|
||||
{
|
||||
for (BussinessDictData dict : datas)
|
||||
{
|
||||
for (String value : dictValue.split(separator))
|
||||
{
|
||||
if (value.equals(dict.getDictValue()))
|
||||
{
|
||||
propertyString.append(dict.getDictLabel()).append(separator);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (BussinessDictData dict : datas)
|
||||
{
|
||||
if (dictValue.equals(dict.getDictValue()))
|
||||
{
|
||||
return dict.getDictLabel();
|
||||
}
|
||||
}
|
||||
}
|
||||
return StringUtils.stripEnd(propertyString.toString(), separator);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据字典类型和字典标签获取字典值
|
||||
*
|
||||
* @param dictType 字典类型
|
||||
* @param dictLabel 字典标签
|
||||
* @param separator 分隔符
|
||||
* @return 字典值
|
||||
*/
|
||||
public static String getDictValue(String dictType, String dictLabel, String separator)
|
||||
{
|
||||
StringBuilder propertyString = new StringBuilder();
|
||||
List<BussinessDictData> datas = getDictCache(dictType);
|
||||
if (StringUtils.isNull(datas))
|
||||
{
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
if (StringUtils.containsAny(separator, dictLabel))
|
||||
{
|
||||
for (BussinessDictData dict : datas)
|
||||
{
|
||||
for (String label : dictLabel.split(separator))
|
||||
{
|
||||
if (label.equals(dict.getDictLabel()))
|
||||
{
|
||||
propertyString.append(dict.getDictValue()).append(separator);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (BussinessDictData dict : datas)
|
||||
{
|
||||
if (dictLabel.equals(dict.getDictLabel()))
|
||||
{
|
||||
return dict.getDictValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
return StringUtils.stripEnd(propertyString.toString(), separator);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据字典类型获取字典所有值
|
||||
*
|
||||
* @param dictType 字典类型
|
||||
* @return 字典值
|
||||
*/
|
||||
public static String getDictValues(String dictType)
|
||||
{
|
||||
StringBuilder propertyString = new StringBuilder();
|
||||
List<BussinessDictData> datas = getDictCache(dictType);
|
||||
if (StringUtils.isNull(datas))
|
||||
{
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
for (BussinessDictData dict : datas)
|
||||
{
|
||||
propertyString.append(dict.getDictValue()).append(SEPARATOR);
|
||||
}
|
||||
return StringUtils.stripEnd(propertyString.toString(), SEPARATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据字典类型获取字典所有标签
|
||||
*
|
||||
* @param dictType 字典类型
|
||||
* @return 字典值
|
||||
*/
|
||||
public static String getDictLabels(String dictType)
|
||||
{
|
||||
StringBuilder propertyString = new StringBuilder();
|
||||
List<BussinessDictData> datas = getDictCache(dictType);
|
||||
if (StringUtils.isNull(datas))
|
||||
{
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
for (BussinessDictData dict : datas)
|
||||
{
|
||||
propertyString.append(dict.getDictLabel()).append(SEPARATOR);
|
||||
}
|
||||
return StringUtils.stripEnd(propertyString.toString(), SEPARATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除指定字典缓存
|
||||
*
|
||||
* @param key 字典键
|
||||
*/
|
||||
public static void removeDictCache(String key)
|
||||
{
|
||||
SpringUtils.getBean(RedisCache.class).deleteObject(getCacheKey(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空字典缓存
|
||||
*/
|
||||
public static void clearDictCache()
|
||||
{
|
||||
Collection<String> keys = SpringUtils.getBean(RedisCache.class).keys(CacheConstants.BUSSINESS_DICT_KEY + "*");
|
||||
SpringUtils.getBean(RedisCache.class).deleteObject(keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置cache key
|
||||
*
|
||||
* @param configKey 参数键
|
||||
* @return 缓存键key
|
||||
*/
|
||||
public static String getCacheKey(String configKey)
|
||||
{
|
||||
return CacheConstants.BUSSINESS_DICT_KEY + configKey;
|
||||
}
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
package com.ruoyi.cms.util.notice;
|
||||
|
||||
import com.ruoyi.cms.domain.EmployeeConfirm;
|
||||
import com.ruoyi.cms.domain.Job;
|
||||
import com.ruoyi.cms.domain.Notice;
|
||||
import com.ruoyi.common.core.domain.entity.AppUser;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class NoticeUtils {
|
||||
/**
|
||||
* 消息已读
|
||||
*/
|
||||
public static final String NOTICE_YD="1";
|
||||
/**
|
||||
* 消息未读
|
||||
*/
|
||||
public static final String NOTICE_WD="0";
|
||||
|
||||
public static final String NOTICE_REMARK="notice_bar";
|
||||
|
||||
public static final String NOTICE_COMENT_ZH="衷心祝贺您通过";
|
||||
|
||||
public static final String NOTICE_COMENT_LY="全流程招聘考核,正式被录用,岗位为【";
|
||||
|
||||
public static final String NOTICE_COMENT_FF="】";
|
||||
|
||||
public static final String NOTICE_TYPE_LY="录用通知";
|
||||
|
||||
public static final String NOTICE_TYPE_GWSX="您收藏的公司有新的职位发布";
|
||||
|
||||
public static final String NOTICE_TYPE_XTLX="1";
|
||||
|
||||
public static final String NOTICE_TYPE_SXLX="2";
|
||||
|
||||
public static final String NOTICE_TYPE_MSLX="4";
|
||||
|
||||
/**
|
||||
* 拼装岗位
|
||||
*/
|
||||
public static final String JOB_NEW="刚刚发布职位";
|
||||
public static final String JOB_XZ="薪资";
|
||||
public static final String JOB_KKB="快去看看吧";
|
||||
public static final String JOB_QFH="“";
|
||||
public static final String JOB_HFH="”";
|
||||
public static final String JOB_ZJG="-";
|
||||
public static final String JOB_DH=",";
|
||||
|
||||
|
||||
/**
|
||||
* 录用通知
|
||||
* @param companyName
|
||||
* @param jobName
|
||||
* @return
|
||||
*/
|
||||
public static String appUserLytz(String companyName,String jobName){
|
||||
return NoticeUtils.NOTICE_COMENT_ZH+companyName+NoticeUtils.NOTICE_COMENT_LY+jobName+NoticeUtils.NOTICE_COMENT_FF;
|
||||
}
|
||||
|
||||
/**
|
||||
* “海尔集团”刚刚发布职位“产品性能分析工程师”薪资“1.5-2.5k,快去看看吧
|
||||
* @param job
|
||||
* @return
|
||||
*/
|
||||
public static String appUserGwsx(Job job){
|
||||
return JOB_QFH+job.getCompanyName()+JOB_HFH+JOB_NEW+JOB_QFH+job.getJobTitle()+JOB_HFH+JOB_XZ+job.getMinSalary()+JOB_ZJG+job.getMaxSalary()+JOB_DH+JOB_KKB;
|
||||
}
|
||||
|
||||
/**
|
||||
* 审核确认界面拼装消息
|
||||
*/
|
||||
public static Notice createLytzNotice(EmployeeConfirm employeeConfirm, Job job) {
|
||||
Notice notice = new Notice();
|
||||
notice.setUserId(employeeConfirm.getUserId());
|
||||
notice.setBussinessId(job.getJobId());
|
||||
notice.setIsRead(NoticeUtils.NOTICE_WD);
|
||||
notice.setTitle(NoticeUtils.NOTICE_TYPE_LY);
|
||||
notice.setSubTitle(NoticeUtils.NOTICE_TYPE_LY);
|
||||
notice.setNoticeType(NoticeUtils.NOTICE_TYPE_XTLX);
|
||||
notice.setRemark(NoticeUtils.NOTICE_REMARK);
|
||||
String content = appUserLytz(job.getCompanyName(), job.getJobTitle());
|
||||
notice.setNoticeContent(content);
|
||||
return notice;
|
||||
}
|
||||
|
||||
/**
|
||||
* 岗位上新
|
||||
*/
|
||||
public static List<Notice> createGwsxNotice(List<AppUser> appUserList, Job job) {
|
||||
List<Notice> add=new ArrayList<>();
|
||||
appUserList.forEach(appUser -> {
|
||||
String content = appUserGwsx(job);
|
||||
Notice notice = new Notice();
|
||||
notice.setUserId(appUser.getUserId());
|
||||
notice.setBussinessId(job.getJobId());
|
||||
notice.setIsRead(NoticeUtils.NOTICE_WD);
|
||||
notice.setTitle(NoticeUtils.NOTICE_TYPE_GWSX);
|
||||
notice.setSubTitle(content);
|
||||
notice.setNoticeType(NoticeUtils.NOTICE_TYPE_SXLX);
|
||||
notice.setRemark(NoticeUtils.NOTICE_REMARK);
|
||||
notice.setNoticeContent(content);
|
||||
add.add(notice);
|
||||
});
|
||||
return add;
|
||||
}
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
package com.ruoyi.cms.util.sensitiveWord;
|
||||
|
||||
import com.ruoyi.cms.domain.SensitiveWordData;
|
||||
import com.ruoyi.cms.mapper.SensitiveWordDataMapper;
|
||||
import com.ruoyi.common.core.redis.RedisCache;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.stereotype.Component;
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
public class SensitiveWordChecker {
|
||||
|
||||
@Autowired
|
||||
private SensitiveWordDataMapper sensitiveWordDataMapper;
|
||||
|
||||
@Autowired
|
||||
private SensitiveWordTrie trie; // 注入前缀树
|
||||
// 缓存键常量
|
||||
private static final String SENSITIVE_WORD_CACHE_KEY = "sensitive:words";
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
|
||||
/**
|
||||
* 项目启动时初始化敏感词库到前缀树
|
||||
*/
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
List<String> sensitiveWords = getSensitiveWordsFromCache();
|
||||
if (sensitiveWords.isEmpty()) {
|
||||
// 缓存未命中,从数据库加载
|
||||
sensitiveWords = loadSensitiveWordsFromDbAndCache();
|
||||
}
|
||||
// 初始化前缀树
|
||||
trie.batchAddWords(sensitiveWords);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测文本中的敏感词
|
||||
* @param text 待检测文本(如job.getDescription())
|
||||
* @return 敏感词列表(空列表表示无敏感词)
|
||||
*/
|
||||
public List<String> checkSensitiveWords(String text) {
|
||||
return trie.findAllSensitiveWords(text);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从缓存获取敏感词列表
|
||||
*/
|
||||
@Cacheable(value = SENSITIVE_WORD_CACHE_KEY)
|
||||
public List<String> getSensitiveWordsFromCache() {
|
||||
// 从Redis获取
|
||||
Object cachedWords = redisCache.getCacheObject(SENSITIVE_WORD_CACHE_KEY);
|
||||
if (cachedWords instanceof List<?>) {
|
||||
return ((List<?>) cachedWords).stream()
|
||||
.filter(obj -> obj instanceof String)
|
||||
.map(obj -> (String) obj)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 从数据库加载敏感词并更新缓存
|
||||
*/
|
||||
public List<String> loadSensitiveWordsFromDbAndCache() {
|
||||
List<SensitiveWordData> wordList = sensitiveWordDataMapper.selectSensitiveworddataList(new SensitiveWordData());
|
||||
List<String> sensitiveWords = wordList.stream()
|
||||
.map(SensitiveWordData::getSensitiveWord)
|
||||
.collect(Collectors.toList());
|
||||
// 缓存有效期设置为24小时,可根据实际需求调整
|
||||
redisCache.setCacheObject(SENSITIVE_WORD_CACHE_KEY, sensitiveWords, 24, TimeUnit.HOURS);
|
||||
return sensitiveWords;
|
||||
}
|
||||
|
||||
/**
|
||||
* 敏感词更新时清除缓存(需在敏感词管理服务中调用)
|
||||
*/
|
||||
@CacheEvict(value = SENSITIVE_WORD_CACHE_KEY, allEntries = true)
|
||||
public void clearSensitiveWordCache() {
|
||||
// 清除缓存后可重新加载
|
||||
loadSensitiveWordsFromDbAndCache();
|
||||
// 重新初始化前缀树
|
||||
trie.clear();
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增/修改敏感词后更新缓存和前缀树
|
||||
*/
|
||||
public void updateCacheAfterModify() {
|
||||
// 1. 清除旧缓存
|
||||
redisCache.deleteObject(SENSITIVE_WORD_CACHE_KEY);
|
||||
// 2. 从数据库重新加载最新数据并更新缓存
|
||||
List<String> latestWords = loadSensitiveWordsFromDbAndCache();
|
||||
// 3. 重建前缀树
|
||||
trie.clear();
|
||||
trie.batchAddWords(latestWords);
|
||||
}
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
package com.ruoyi.cms.util.sensitiveWord;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 前缀树(Trie树)节点
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* 前缀树(Trie树)工具类
|
||||
*/
|
||||
@Component
|
||||
public class SensitiveWordTrie {
|
||||
// 根节点(无实际字符)
|
||||
private final TrieNode root = new TrieNode();
|
||||
|
||||
/**
|
||||
* 向前缀树中添加敏感词
|
||||
*/
|
||||
public void addWord(String word) {
|
||||
if (word == null || word.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
TrieNode current = root;
|
||||
for (char c : word.toCharArray()) {
|
||||
// 若子节点中不存在该字符,则创建新节点
|
||||
current.getChildren().putIfAbsent(c, new TrieNode());
|
||||
// 移动到子节点
|
||||
current = current.getChildren().get(c);
|
||||
}
|
||||
// 标记当前节点为敏感词结尾
|
||||
current.setEnd(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测文本中所有敏感词(去重)
|
||||
* @param text 待检测文本
|
||||
* @return 敏感词列表
|
||||
*/
|
||||
public List<String> findAllSensitiveWords(String text) {
|
||||
if (text == null || text.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
Set<String> sensitiveWords = new HashSet<>();
|
||||
TrieNode current = root;
|
||||
StringBuilder currentWord = new StringBuilder(); // 记录当前匹配的字符
|
||||
|
||||
for (int i = 0; i < text.length(); i++) {
|
||||
char c = text.charAt(i);
|
||||
|
||||
// 若当前字符不在子节点中,重置匹配状态
|
||||
if (!current.getChildren().containsKey(c)) {
|
||||
current = root; // 回到根节点
|
||||
currentWord.setLength(0); // 清空当前匹配的字符
|
||||
continue;
|
||||
}
|
||||
|
||||
// 匹配到字符,移动到子节点
|
||||
current = current.getChildren().get(c);
|
||||
currentWord.append(c);
|
||||
|
||||
// 若当前节点是敏感词结尾,记录该敏感词
|
||||
if (current.isEnd()) {
|
||||
sensitiveWords.add(currentWord.toString());
|
||||
}
|
||||
}
|
||||
|
||||
return new ArrayList<>(sensitiveWords);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量添加敏感词到前缀树
|
||||
* @param words 敏感词列表
|
||||
*/
|
||||
public void batchAddWords(List<String> words) {
|
||||
if (words == null || words.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
// 批量处理比循环单次添加更高效,减少重复判断
|
||||
for (String word : words) {
|
||||
addWord(word);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空前缀树所有节点
|
||||
*/
|
||||
public void clear() {
|
||||
// 清空根节点的子节点映射,达到清空整个前缀树的效果
|
||||
root.getChildren().clear();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package com.ruoyi.cms.util.sensitiveWord;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
class TrieNode {
|
||||
// 子节点:key=字符,value=子节点
|
||||
private final Map<Character, TrieNode> children = new HashMap<>();
|
||||
// 标记当前节点是否为敏感词的结尾
|
||||
private boolean isEnd = false;
|
||||
|
||||
public Map<Character, TrieNode> getChildren() {
|
||||
return children;
|
||||
}
|
||||
|
||||
public boolean isEnd() {
|
||||
return isEnd;
|
||||
}
|
||||
|
||||
public void setEnd(boolean end) {
|
||||
isEnd = end;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user