Commit 3499093c authored by 万成波's avatar 万成波

敏感词过滤

parent 0ea260dc
package com.tangguo; package com.tangguo;
import com.tangguo.common.constant.ActiveMQConstant; import com.tangguo.common.constant.ActiveMQConstant;
import com.tangguo.common.domain.PointsDetailInfo; import com.tangguo.common.domain.PointsDetail;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.jms.core.JmsTemplate; import org.springframework.jms.core.JmsTemplate;
...@@ -23,7 +23,7 @@ public class ApplicationTest { ...@@ -23,7 +23,7 @@ public class ApplicationTest {
@Test @Test
public void test() { public void test() {
PointsDetailInfo detail = new PointsDetailInfo(); PointsDetail detail = new PointsDetail();
detail.setUserName("TanXiaoIng"); detail.setUserName("TanXiaoIng");
detail.setDetailPoints(10); detail.setDetailPoints(10);
detail.setDetailName("外部系统"); detail.setDetailName("外部系统");
......
...@@ -19,12 +19,22 @@ public interface ActiveMQConstant{ ...@@ -19,12 +19,22 @@ public interface ActiveMQConstant{
/** /**
* 增加用户积分队列名 * 增加用户积分队列名
*/ */
String INCR_USER_POINTS_QUEUE = "points.user.incr"; String INCR_USER_POINTS_QUEUE = "user.points.incr";
/** /**
* 扣减用户积分队列名 * 扣减用户积分队列名
*/ */
String DECR_USER_POINTS_QUEUE = "points.user.decr"; String DECR_USER_POINTS_QUEUE = "user.points.decr";
}
interface Operate {
/**
* 增加用户积分队列名
*/
String USER_OPERATE = "user.operate";
} }
......
...@@ -5,13 +5,13 @@ import lombok.Data; ...@@ -5,13 +5,13 @@ import lombok.Data;
import java.io.Serializable; import java.io.Serializable;
/** /**
* 积分明细DTO * 积分明细
* *
* @author 谈笑 * @author 谈笑
* @createTime 2025-08-29 17:23:29 星期五 * @createTime 2025-08-29 17:23:29 星期五
*/ */
@Data @Data
public class PointsDetailInfo implements Serializable { public class PointsDetail implements Serializable {
private static final long serialVersionUID = 8057307839793769207L; private static final long serialVersionUID = 8057307839793769207L;
......
package com.tangguo.common.utils;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.util.StrUtil;
import cn.hutool.dfa.FoundWord;
import cn.hutool.dfa.WordTree;
import lombok.extern.slf4j.Slf4j;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Slf4j
public class SensitiveWordUtils {
private static final WordTree SENSITIVE_TREE = new WordTree();
/**
* 添加敏感词
*
* @param word 敏感词
*/
public static void addWords(String word) {
if (StrUtil.isNotBlank(word)) {
SENSITIVE_TREE.addWords(word);
log.info("=> 敏感词工具添加敏感:{}", word);
}
}
/**
* 添加敏感词
*
* @param words 敏感词
*/
public static void addWords(Collection<String> words) {
if (CollUtil.isNotEmpty(words)) {
List<String> filterWords = words.stream().filter(StrUtil::isNotBlank).collect(Collectors.toList());
SENSITIVE_TREE.addWords(filterWords);
log.info("=> 敏感词工具添加敏感数量:{}", words.size());
}
}
/**
* 清空敏感词
*/
public static void clearWords() {
SENSITIVE_TREE.clear();
log.info("=> 敏感词工具清空敏感词");
}
/**
* 重新加载敏感词
*
* @param words 敏感词
*/
public static void reloadWords(Collection<String> words) {
SENSITIVE_TREE.clear();
if (CollUtil.isNotEmpty(words)) {
List<String> filterWords = words.stream().filter(StrUtil::isNotBlank).collect(Collectors.toList());
SENSITIVE_TREE.addWords(filterWords);
log.info("=> 敏感词工具重新加载敏感数量:{}", words.size());
}
}
/**
* 查找敏感词,返回找到的第一个敏感词
*
* @param text 文本
* @return 敏感词
* @since 5.5.3
*/
public static FoundWord getFoundFirstSensitive(String text) {
return SENSITIVE_TREE.matchWord(text);
}
/**
* 查找敏感词,返回找到的所有敏感词
*
* @param text 文本
* @return 敏感词
*/
public static List<FoundWord> getFoundAllSensitive(String text) {
return SENSITIVE_TREE.matchAllWords(text);
}
/**
* 查找敏感词,返回找到的所有敏感词
*
* @param text 文本
* @param isDensityMatch 是否使用密集匹配原则
* @param isGreedMatch 是否使用贪婪匹配(最长匹配)原则
* @return 敏感词
*/
public static List<FoundWord> getFoundAllSensitive(String text, boolean isDensityMatch, boolean isGreedMatch) {
return SENSITIVE_TREE.matchAllWords(text, -1, isDensityMatch, isGreedMatch);
}
/**
* 处理过滤文本中的敏感词,默认替换成*
*
* @param text 文本
* @param isGreedMatch 贪婪匹配(最长匹配)原则:假如关键字a,ab,最长匹配将匹配[a, ab]
* @return 敏感词过滤处理后的文本
*/
public static String sensitiveFilter(String text, boolean isGreedMatch) {
if (StrUtil.isEmpty(text)) {
return text;
}
TimeInterval timer = DateUtil.timer();
//敏感词过滤场景下,不需要密集匹配
List<FoundWord> foundWordList = getFoundAllSensitive(text, false, isGreedMatch);
if (CollUtil.isEmpty(foundWordList)) {
return text;
}
Map<Integer, FoundWord> foundWordMap = new HashMap<>(foundWordList.size());
foundWordList.forEach(foundWord -> foundWordMap.put(foundWord.getStartIndex(), foundWord));
int length = text.length();
StringBuilder textStringBuilder = new StringBuilder();
for (int i = 0; i < length; i++) {
FoundWord fw = foundWordMap.get(i);
if (fw != null) {
int fwl = fw.getFoundWord().length();
StringBuilder sb = new StringBuilder(fwl);
for (int m = 0; m < fwl; m++) {
sb.append("*");
}
textStringBuilder.append(sb);
i = fw.getEndIndex();
} else {
textStringBuilder.append(text.charAt(i));
}
}
log.info("过滤敏感词, 耗时: {} ms", timer.intervalMs());
return textStringBuilder.toString();
}
}
package com.tangguo.enums; package com.tangguo.common.enums;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
......
package com.tangguo.enums; package com.tangguo.common.enums;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
......
package com.tangguo.enums; package com.tangguo.common.enums;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
......
package com.tangguo.enums; package com.tangguo.common.enums;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
......
package com.tangguo.enums; package com.tangguo.common.enums;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
......
package com.tangguo.enums; package com.tangguo.common.enums;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
......
package com.tangguo.jobs; package com.tangguo.common.jobs;
import com.tangguo.service.IBbsTopicService; import com.tangguo.service.IBbsTopicService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
......
package com.tangguo.common.listener;
import com.tangguo.common.constant.ActiveMQConstant;
import com.tangguo.domain.OperateDetail;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;
import javax.jms.Message;
/**
* 用户操作事件监听器
*
* @author 谈笑
* @createTime 2025-09-01 16:03:08 星期一
*/
@Slf4j
@Component
public class UserOperateListener {
/**
* 增加用户积分消息
*
* @param detail 积分明细
*/
@JmsListener(destination = ActiveMQConstant.Operate.USER_OPERATE, containerFactory = ActiveMQConstant.QUEUE_CONTAINER_BEAN)
public void operateListener(OperateDetail detail, Message message) {
}
}
...@@ -3,6 +3,7 @@ package com.tangguo.controller.mobile; ...@@ -3,6 +3,7 @@ package com.tangguo.controller.mobile;
import com.tangguo.common.core.domain.AjaxResult; import com.tangguo.common.core.domain.AjaxResult;
import com.tangguo.common.mauth.MobileAuth; import com.tangguo.common.mauth.MobileAuth;
import com.tangguo.common.utils.PageUtils; import com.tangguo.common.utils.PageUtils;
import com.tangguo.common.utils.ValidateOperations;
import com.tangguo.domain.bo.CreateTopicBO; import com.tangguo.domain.bo.CreateTopicBO;
import com.tangguo.domain.vo.BbsMomentListVO; import com.tangguo.domain.vo.BbsMomentListVO;
import com.tangguo.domain.vo.BbsTopicListVO; import com.tangguo.domain.vo.BbsTopicListVO;
...@@ -50,6 +51,7 @@ public class MBbsTopicController { ...@@ -50,6 +51,7 @@ public class MBbsTopicController {
@MobileAuth @MobileAuth
@PostMapping("/create") @PostMapping("/create")
public AjaxResult createTopic(@RequestBody CreateTopicBO bo) { public AjaxResult createTopic(@RequestBody CreateTopicBO bo) {
ValidateOperations.generalValidate(bo);
BbsTopicListVO topic = this.topicService.createTopic(bo); BbsTopicListVO topic = this.topicService.createTopic(bo);
return AjaxResult.success(topic); return AjaxResult.success(topic);
} }
......
...@@ -6,7 +6,7 @@ import com.tangguo.common.core.domain.AjaxResult; ...@@ -6,7 +6,7 @@ import com.tangguo.common.core.domain.AjaxResult;
import com.tangguo.common.core.page.TableDataInfo; import com.tangguo.common.core.page.TableDataInfo;
import com.tangguo.common.enums.BusinessType; import com.tangguo.common.enums.BusinessType;
import com.tangguo.domain.BbsSensitiveWord; import com.tangguo.domain.BbsSensitiveWord;
import com.tangguo.domain.result.DataImportResult; import com.tangguo.domain.DataImportResult;
import com.tangguo.service.IBbsSensitiveWordService; import com.tangguo.service.IBbsSensitiveWordService;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
...@@ -116,7 +116,7 @@ public class BbsSensitiveWordController extends BaseController { ...@@ -116,7 +116,7 @@ public class BbsSensitiveWordController extends BaseController {
@Log(title = "敏感词库", businessType = BusinessType.UPDATE) @Log(title = "敏感词库", businessType = BusinessType.UPDATE)
@PutMapping("/refresh") @PutMapping("/refresh")
public AjaxResult refresh() { public AjaxResult refresh() {
this.bbsSensitiveWordService.refreshCacheWords(); this.bbsSensitiveWordService.reloadCacheWords();
return AjaxResult.success(); return AjaxResult.success();
} }
......
package com.tangguo.domain;
import lombok.Data;
/**
* 操作明细
*
* @author 谈笑
* @createTime 2025-09-04 22:33:53 星期四
*/
@Data
public class OperateDetail {
}
package com.tangguo.domain.bo; package com.tangguo.domain.bo;
import lombok.Data; import lombok.Data;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotBlank;
/** /**
* *
...@@ -14,6 +17,8 @@ public class CreateTopicBO { ...@@ -14,6 +17,8 @@ public class CreateTopicBO {
/** /**
* 话题名称 * 话题名称
*/ */
@NotBlank(message = "话题名称不能为空")
@Length(min = 1, max = 50, message = "话题长度字符错误")
private String name; private String name;
} }
...@@ -2,7 +2,6 @@ package com.tangguo.service; ...@@ -2,7 +2,6 @@ package com.tangguo.service;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import com.tangguo.domain.BbsMomentVote; import com.tangguo.domain.BbsMomentVote;
import com.tangguo.domain.vo.BbsVoteOptionVO;
import com.tangguo.domain.vo.BbsVoteVO; import com.tangguo.domain.vo.BbsVoteVO;
import java.util.List; import java.util.List;
......
...@@ -2,7 +2,7 @@ package com.tangguo.service; ...@@ -2,7 +2,7 @@ package com.tangguo.service;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import com.tangguo.domain.BbsSensitiveWord; import com.tangguo.domain.BbsSensitiveWord;
import com.tangguo.domain.result.DataImportResult; import com.tangguo.domain.DataImportResult;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import java.util.List; import java.util.List;
...@@ -25,9 +25,9 @@ public interface IBbsSensitiveWordService extends IService<BbsSensitiveWord> { ...@@ -25,9 +25,9 @@ public interface IBbsSensitiveWordService extends IService<BbsSensitiveWord> {
/** /**
* 刷新缓存敏感词 * 重新加载缓存敏感词
*/ */
void refreshCacheWords(); void reloadCacheWords();
/** /**
......
...@@ -2,10 +2,10 @@ package com.tangguo.service.impl; ...@@ -2,10 +2,10 @@ package com.tangguo.service.impl;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tangguo.common.enums.CommentStatus;
import com.tangguo.common.exception.ServiceException; import com.tangguo.common.exception.ServiceException;
import com.tangguo.domain.BbsMomentComment; import com.tangguo.domain.BbsMomentComment;
import com.tangguo.domain.vo.BbsCommentDetailVO; import com.tangguo.domain.vo.BbsCommentDetailVO;
import com.tangguo.enums.CommentStatus;
import com.tangguo.mapper.BbsMomentCommentMapper; import com.tangguo.mapper.BbsMomentCommentMapper;
import com.tangguo.service.IBbsMomentCommentService; import com.tangguo.service.IBbsMomentCommentService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
......
...@@ -2,10 +2,13 @@ package com.tangguo.service.impl; ...@@ -2,10 +2,13 @@ package com.tangguo.service.impl;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.dfa.FoundWord;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tangguo.common.enums.*;
import com.tangguo.common.exception.ServiceException; import com.tangguo.common.exception.ServiceException;
import com.tangguo.common.mauth.MobileTokenHelper; import com.tangguo.common.mauth.MobileTokenHelper;
import com.tangguo.common.utils.SensitiveWordUtils;
import com.tangguo.domain.BbsMoment; import com.tangguo.domain.BbsMoment;
import com.tangguo.domain.BbsMomentAttachment; import com.tangguo.domain.BbsMomentAttachment;
import com.tangguo.domain.BbsMomentComment; import com.tangguo.domain.BbsMomentComment;
...@@ -15,10 +18,10 @@ import com.tangguo.domain.bo.CreateMomentBO; ...@@ -15,10 +18,10 @@ import com.tangguo.domain.bo.CreateMomentBO;
import com.tangguo.domain.bo.LikeMomentBO; import com.tangguo.domain.bo.LikeMomentBO;
import com.tangguo.domain.bo.VoteMomentBO; import com.tangguo.domain.bo.VoteMomentBO;
import com.tangguo.domain.vo.*; import com.tangguo.domain.vo.*;
import com.tangguo.enums.*;
import com.tangguo.mapper.BbsMomentMapper; import com.tangguo.mapper.BbsMomentMapper;
import com.tangguo.service.*; import com.tangguo.service.*;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.C;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StopWatch; import org.springframework.util.StopWatch;
...@@ -182,7 +185,6 @@ public class BbsMomentServiceImpl extends ServiceImpl<BbsMomentMapper, BbsMoment ...@@ -182,7 +185,6 @@ public class BbsMomentServiceImpl extends ServiceImpl<BbsMomentMapper, BbsMoment
if (Objects.isNull(dbMoment)) { if (Objects.isNull(dbMoment)) {
throw new ServiceException("删除失败,未查询到当前动态数据。"); throw new ServiceException("删除失败,未查询到当前动态数据。");
} }
this.removeById(dbMoment.getId()); this.removeById(dbMoment.getId());
} }
...@@ -343,26 +345,40 @@ public class BbsMomentServiceImpl extends ServiceImpl<BbsMomentMapper, BbsMoment ...@@ -343,26 +345,40 @@ public class BbsMomentServiceImpl extends ServiceImpl<BbsMomentMapper, BbsMoment
// 动态附件 // 动态附件
BbsMoment newMoment = new BbsMoment(); BbsMoment newMoment = new BbsMoment();
List<CreateMomentBO.Attachment> attachments = bo.getAttachments(); List<CreateMomentBO.Attachment> attachments = bo.getAttachments();
String linkUrl = bo.getLinkUrl(); String content = bo.getContent();
if (MomentType.TEXT == momentType) {
if (StrUtil.isBlank(bo.getContent())) { // 动态类型
throw new ServiceException("发布失败,动态内容不能为空。"); if (MomentType.TEXT == momentType || MomentType.IMAGE == momentType || MomentType.VIDEO == momentType) {
if (MomentType.TEXT == momentType) {
if (StrUtil.isBlank(content)) {
throw new ServiceException("发布失败,动态内容不能为空。");
}
} }
} if (MomentType.IMAGE == momentType || MomentType.VIDEO == momentType) {
else if (MomentType.IMAGE == momentType || MomentType.VIDEO == momentType) { if (CollUtil.isEmpty(attachments)) {
if (CollUtil.isEmpty(attachments)) { throw new ServiceException("发布失败,动态附件不能为空。");
throw new ServiceException("发布失败,动态附件不能为空。"); }
}
if (StrUtil.isNotBlank(content)) {
FoundWord fw = SensitiveWordUtils.getFoundFirstSensitive(content);
if (Objects.nonNull(fw)) {
String msg = String.format("发布失败,当前动态内容存在敏感词【%s】。", fw.getFoundWord());
throw new ServiceException(msg);
} else {
newMoment.setContent(content);
}
} }
} }
else if (MomentType.URL == momentType) { else if (MomentType.URL == momentType) {
String linkUrl = bo.getLinkUrl();
if (StrUtil.isBlank(linkUrl)) { if (StrUtil.isBlank(linkUrl)) {
throw new ServiceException("发布失败,动态链接不能为空。"); throw new ServiceException("发布失败,动态链接不能为空。");
} else {
newMoment.setLinkUrl(linkUrl);
} }
} }
newMoment.setType(momentType.name()); newMoment.setType(momentType.name());
newMoment.setContent(bo.getContent());
newMoment.setLinkUrl(linkUrl);
newMoment.setIsEnableComment(bo.getIsEnableComment()); newMoment.setIsEnableComment(bo.getIsEnableComment());
newMoment.setIsEnableFeaturedComment(bo.getIsEnableFeaturedComment()); newMoment.setIsEnableFeaturedComment(bo.getIsEnableFeaturedComment());
......
...@@ -3,11 +3,11 @@ package com.tangguo.service.impl; ...@@ -3,11 +3,11 @@ package com.tangguo.service.impl;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tangguo.common.enums.VoteOptionType;
import com.tangguo.domain.BbsMoment; import com.tangguo.domain.BbsMoment;
import com.tangguo.domain.BbsMomentVoteOption; import com.tangguo.domain.BbsMomentVoteOption;
import com.tangguo.domain.bo.CreateMomentBO; import com.tangguo.domain.bo.CreateMomentBO;
import com.tangguo.domain.vo.BbsVoteOptionVO; import com.tangguo.domain.vo.BbsVoteOptionVO;
import com.tangguo.enums.VoteOptionType;
import com.tangguo.mapper.BbsMomentVoteOptionMapper; import com.tangguo.mapper.BbsMomentVoteOptionMapper;
import com.tangguo.service.IBbsMomentVoteOptionService; import com.tangguo.service.IBbsMomentVoteOptionService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
...@@ -15,7 +15,6 @@ import org.springframework.transaction.annotation.Transactional; ...@@ -15,7 +15,6 @@ import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
/** /**
......
...@@ -7,9 +7,10 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers; ...@@ -7,9 +7,10 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tangguo.common.core.redis.RedisCache; import com.tangguo.common.core.redis.RedisCache;
import com.tangguo.common.exception.ServiceException; import com.tangguo.common.exception.ServiceException;
import com.tangguo.common.utils.SensitiveWordUtils;
import com.tangguo.common.utils.StringUtils; import com.tangguo.common.utils.StringUtils;
import com.tangguo.domain.BbsSensitiveWord; import com.tangguo.domain.BbsSensitiveWord;
import com.tangguo.domain.result.DataImportResult; import com.tangguo.domain.DataImportResult;
import com.tangguo.mapper.BbsSensitiveWordMapper; import com.tangguo.mapper.BbsSensitiveWordMapper;
import com.tangguo.service.IBbsSensitiveWordService; import com.tangguo.service.IBbsSensitiveWordService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
...@@ -44,7 +45,7 @@ public class BbsSensitiveWordServiceImpl extends ServiceImpl<BbsSensitiveWordMap ...@@ -44,7 +45,7 @@ public class BbsSensitiveWordServiceImpl extends ServiceImpl<BbsSensitiveWordMap
@PostConstruct @PostConstruct
private void initCacheWords() { private void initCacheWords() {
Set<String> dbWords = this.getDbWords(); Set<String> dbWords = this.getDbWords();
this.redisCache.setCacheSet(WORD_CACHE_KEY, new HashSet<>(dbWords)); SensitiveWordUtils.addWords(dbWords);
log.info("=> 数据库敏感词已缓存,敏感词数量:{}", dbWords.size()); log.info("=> 数据库敏感词已缓存,敏感词数量:{}", dbWords.size());
} }
...@@ -64,15 +65,12 @@ public class BbsSensitiveWordServiceImpl extends ServiceImpl<BbsSensitiveWordMap ...@@ -64,15 +65,12 @@ public class BbsSensitiveWordServiceImpl extends ServiceImpl<BbsSensitiveWordMap
/** /**
* 刷新缓存敏感词 * 重新加载缓存敏感词
*/ */
@Override @Override
public void refreshCacheWords() { public void reloadCacheWords() {
this.redisCache.deleteObject(WORD_CACHE_KEY);
log.info("=> 缓存敏感词已清空");
Set<String> dbWords = this.getDbWords(); Set<String> dbWords = this.getDbWords();
this.redisCache.setCacheSet(WORD_CACHE_KEY, new HashSet<>(dbWords)); SensitiveWordUtils.reloadWords(dbWords);
log.info("=> 缓存敏感词已刷新,敏感词数量:{}", dbWords.size());
} }
...@@ -110,7 +108,7 @@ public class BbsSensitiveWordServiceImpl extends ServiceImpl<BbsSensitiveWordMap ...@@ -110,7 +108,7 @@ public class BbsSensitiveWordServiceImpl extends ServiceImpl<BbsSensitiveWordMap
addWord.setSort(word.getSort()); addWord.setSort(word.getSort());
addWord.setEnableStatus(1); addWord.setEnableStatus(1);
this.save(addWord); this.save(addWord);
this.redisCache.setAddValues(WORD_CACHE_KEY, word.getName()); SensitiveWordUtils.addWords(addWord.getName());
} }
...@@ -140,9 +138,7 @@ public class BbsSensitiveWordServiceImpl extends ServiceImpl<BbsSensitiveWordMap ...@@ -140,9 +138,7 @@ public class BbsSensitiveWordServiceImpl extends ServiceImpl<BbsSensitiveWordMap
updWord.setName(word.getName()); updWord.setName(word.getName());
updWord.setSort(word.getSort()); updWord.setSort(word.getSort());
this.updateById(updWord); this.updateById(updWord);
this.reloadCacheWords();
this.redisCache.setDeleteValues(WORD_CACHE_KEY, dbWord.getName());
this.redisCache.setAddValues(WORD_CACHE_KEY, word.getName());
} }
...@@ -156,7 +152,7 @@ public class BbsSensitiveWordServiceImpl extends ServiceImpl<BbsSensitiveWordMap ...@@ -156,7 +152,7 @@ public class BbsSensitiveWordServiceImpl extends ServiceImpl<BbsSensitiveWordMap
BbsSensitiveWord dbWord = this.getById(wordId); BbsSensitiveWord dbWord = this.getById(wordId);
if (Objects.nonNull(dbWord)) { if (Objects.nonNull(dbWord)) {
this.removeById(wordId); this.removeById(wordId);
this.redisCache.setDeleteValues(WORD_CACHE_KEY, dbWord.getName()); this.reloadCacheWords();
} }
} }
......
package com.tangguo.service.impl; package com.tangguo.service.impl;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.dfa.FoundWord;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tangguo.common.constant.TopicConstant;
import com.tangguo.common.core.redis.RedisCache; import com.tangguo.common.core.redis.RedisCache;
import com.tangguo.common.enums.TopicTopStatus;
import com.tangguo.common.exception.ServiceException; import com.tangguo.common.exception.ServiceException;
import com.tangguo.common.mauth.MobileTokenHelper; import com.tangguo.common.mauth.MobileTokenHelper;
import com.tangguo.common.utils.SensitiveWordUtils;
import com.tangguo.common.utils.StringUtils; import com.tangguo.common.utils.StringUtils;
import com.tangguo.constant.TopicConstant;
import com.tangguo.domain.BbsTopic; import com.tangguo.domain.BbsTopic;
import com.tangguo.domain.bo.CreateTopicBO; import com.tangguo.domain.bo.CreateTopicBO;
import com.tangguo.domain.vo.BbsMomentListVO; import com.tangguo.domain.vo.BbsMomentListVO;
import com.tangguo.domain.vo.BbsTopicListVO; import com.tangguo.domain.vo.BbsTopicListVO;
import com.tangguo.enums.TopicTopStatus;
import com.tangguo.mapper.BbsTopicMapper; import com.tangguo.mapper.BbsTopicMapper;
import com.tangguo.service.IBbsTopicService; import com.tangguo.service.IBbsTopicService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
...@@ -207,18 +209,25 @@ public class BbsTopicServiceImpl extends ServiceImpl<BbsTopicMapper, BbsTopic> i ...@@ -207,18 +209,25 @@ public class BbsTopicServiceImpl extends ServiceImpl<BbsTopicMapper, BbsTopic> i
*/ */
@Override @Override
public BbsTopicListVO createTopic(CreateTopicBO bo) { public BbsTopicListVO createTopic(CreateTopicBO bo) {
synchronized (bo.getName().intern()) { String topicName = bo.getName();
synchronized (topicName.intern()) {
long nameCount = this.count( long nameCount = this.count(
Wrappers.lambdaQuery(BbsTopic.class).eq(BbsTopic::getName, bo.getName()) Wrappers.lambdaQuery(BbsTopic.class).eq(BbsTopic::getName, topicName)
); );
if (nameCount > 0) { if (nameCount > 0) {
throw new ServiceException("创建失败,当前话题名称已存在。"); throw new ServiceException("创建失败,当前话题名称已存在。");
} }
FoundWord fw = SensitiveWordUtils.getFoundFirstSensitive(topicName);
if (Objects.nonNull(fw)) {
String msg = String.format("创建失败,当前话题名称存在敏感词【%s】。", fw.getFoundWord());
throw new ServiceException(msg);
}
BbsTopic newTopic = new BbsTopic(); BbsTopic newTopic = new BbsTopic();
newTopic.setCreateBy(MobileTokenHelper.getUserName()); newTopic.setCreateBy(MobileTokenHelper.getUserName());
newTopic.setSource("移动端用户"); newTopic.setSource("移动端用户");
newTopic.setName(bo.getName()); newTopic.setName(topicName);
this.save(newTopic); this.save(newTopic);
BbsTopicListVO topicVO = new BbsTopicListVO(); BbsTopicListVO topicVO = new BbsTopicListVO();
......
package com.tangguo.listener; package com.tangguo.listener;
import com.tangguo.common.constant.ActiveMQConstant; import com.tangguo.common.constant.ActiveMQConstant;
import com.tangguo.common.domain.PointsDetailInfo; import com.tangguo.common.domain.PointsDetail;
import com.tangguo.service.IBbsUserPointsService; import com.tangguo.service.IBbsUserPointsService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.jms.annotation.JmsListener; import org.springframework.jms.annotation.JmsListener;
...@@ -11,14 +11,14 @@ import javax.annotation.Resource; ...@@ -11,14 +11,14 @@ import javax.annotation.Resource;
import javax.jms.Message; import javax.jms.Message;
/** /**
* 用户积分增加扣减消息时间监听器 * 用户积分事件监听器
* *
* @author 谈笑 * @author 谈笑
* @createTime 2025-09-01 16:03:08 星期一 * @createTime 2025-09-01 16:03:08 星期一
*/ */
@Slf4j @Slf4j
@Component @Component
public class UserPointsListener { public class PointsListener {
@Resource @Resource
private IBbsUserPointsService userPointsService; private IBbsUserPointsService userPointsService;
...@@ -30,7 +30,7 @@ public class UserPointsListener { ...@@ -30,7 +30,7 @@ public class UserPointsListener {
* @param detail 积分明细 * @param detail 积分明细
*/ */
@JmsListener(destination = ActiveMQConstant.Points.INCR_USER_POINTS_QUEUE, containerFactory = ActiveMQConstant.QUEUE_CONTAINER_BEAN) @JmsListener(destination = ActiveMQConstant.Points.INCR_USER_POINTS_QUEUE, containerFactory = ActiveMQConstant.QUEUE_CONTAINER_BEAN)
public void incrUserPointsListener(PointsDetailInfo detail, Message message) { public void incrUserPointsListener(PointsDetail detail, Message message) {
try { try {
log.info("=> 开始处理增加用户积分消息:{}", detail); log.info("=> 开始处理增加用户积分消息:{}", detail);
this.userPointsService.incrUserPoints(detail); this.userPointsService.incrUserPoints(detail);
...@@ -47,7 +47,7 @@ public class UserPointsListener { ...@@ -47,7 +47,7 @@ public class UserPointsListener {
* @param detail 积分明细 * @param detail 积分明细
*/ */
@JmsListener(destination = ActiveMQConstant.Points.DECR_USER_POINTS_QUEUE, containerFactory = ActiveMQConstant.QUEUE_CONTAINER_BEAN) @JmsListener(destination = ActiveMQConstant.Points.DECR_USER_POINTS_QUEUE, containerFactory = ActiveMQConstant.QUEUE_CONTAINER_BEAN)
public void decrUserPointsListener(PointsDetailInfo detail, Message message) { public void decrUserPointsListener(PointsDetail detail, Message message) {
try { try {
log.info("=> 扣减用户积分消息:{}", detail); log.info("=> 扣减用户积分消息:{}", detail);
this.userPointsService.decrUserPoints(detail); this.userPointsService.decrUserPoints(detail);
......
package com.tangguo.service; package com.tangguo.service;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import com.tangguo.common.domain.PointsDetailInfo; import com.tangguo.common.domain.PointsDetail;
import com.tangguo.domain.BbsUserPoints; import com.tangguo.domain.BbsUserPoints;
import java.util.List; import java.util.List;
...@@ -53,7 +53,7 @@ public interface IBbsUserPointsService extends IService<BbsUserPoints> { ...@@ -53,7 +53,7 @@ public interface IBbsUserPointsService extends IService<BbsUserPoints> {
* *
* @param detail 积分明细 * @param detail 积分明细
*/ */
void incrUserPoints(PointsDetailInfo detail); void incrUserPoints(PointsDetail detail);
/** /**
...@@ -61,6 +61,6 @@ public interface IBbsUserPointsService extends IService<BbsUserPoints> { ...@@ -61,6 +61,6 @@ public interface IBbsUserPointsService extends IService<BbsUserPoints> {
* *
* @param detail 积分明细 * @param detail 积分明细
*/ */
void decrUserPoints(PointsDetailInfo detail); void decrUserPoints(PointsDetail detail);
} }
package com.tangguo.service.impl; package com.tangguo.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tangguo.common.domain.PointsDetailInfo; import com.tangguo.common.domain.PointsDetail;
import com.tangguo.common.exception.ServiceException; import com.tangguo.common.exception.ServiceException;
import com.tangguo.domain.BbsPointsGoods; import com.tangguo.domain.BbsPointsGoods;
import com.tangguo.domain.BbsUserPoints; import com.tangguo.domain.BbsUserPoints;
...@@ -85,7 +85,7 @@ public class BbsUserPointsExchangeServiceImpl extends ServiceImpl<BbsUserPointsE ...@@ -85,7 +85,7 @@ public class BbsUserPointsExchangeServiceImpl extends ServiceImpl<BbsUserPointsE
this.pointsGoodsService.incrGoodsSales(goodsId, 1); this.pointsGoodsService.incrGoodsSales(goodsId, 1);
// 扣减用户积分 // 扣减用户积分
PointsDetailInfo detail = new PointsDetailInfo(); PointsDetail detail = new PointsDetail();
detail.setUserName(userName); detail.setUserName(userName);
detail.setDetailPoints(exchangePoints); detail.setDetailPoints(exchangePoints);
detail.setDetailName(dbGoods.getName()); detail.setDetailName(dbGoods.getName());
......
package com.tangguo.service.impl; package com.tangguo.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tangguo.common.domain.PointsDetailInfo; import com.tangguo.common.domain.PointsDetail;
import com.tangguo.common.domain.QwmhUserInfo; import com.tangguo.common.domain.QwmhUserInfo;
import com.tangguo.common.exception.ServiceException; import com.tangguo.common.exception.ServiceException;
import com.tangguo.common.utils.SecurityUtils; import com.tangguo.common.utils.SecurityUtils;
...@@ -96,7 +96,7 @@ public class BbsUserPointsServiceImpl extends ServiceImpl<BbsUserPointsMapper, B ...@@ -96,7 +96,7 @@ public class BbsUserPointsServiceImpl extends ServiceImpl<BbsUserPointsMapper, B
@Override @Override
public void addUserPoints(BbsUserPoints points) { public void addUserPoints(BbsUserPoints points) {
String userName = points.getUserName(); String userName = points.getUserName();
PointsDetailInfo detail = new PointsDetailInfo(); PointsDetail detail = new PointsDetail();
detail.setUserName(userName); detail.setUserName(userName);
detail.setDetailPoints(points.getIncrOrDecrPoints()); detail.setDetailPoints(points.getIncrOrDecrPoints());
detail.setDetailName("后台手动增加"); detail.setDetailName("后台手动增加");
...@@ -114,7 +114,7 @@ public class BbsUserPointsServiceImpl extends ServiceImpl<BbsUserPointsMapper, B ...@@ -114,7 +114,7 @@ public class BbsUserPointsServiceImpl extends ServiceImpl<BbsUserPointsMapper, B
@Override @Override
public void deleteUserPoints(BbsUserPoints points) { public void deleteUserPoints(BbsUserPoints points) {
String userName = points.getUserName(); String userName = points.getUserName();
PointsDetailInfo detail = new PointsDetailInfo(); PointsDetail detail = new PointsDetail();
detail.setUserName(userName); detail.setUserName(userName);
detail.setDetailPoints(points.getIncrOrDecrPoints()); detail.setDetailPoints(points.getIncrOrDecrPoints());
detail.setDetailName("后台手动扣减"); detail.setDetailName("后台手动扣减");
...@@ -129,7 +129,7 @@ public class BbsUserPointsServiceImpl extends ServiceImpl<BbsUserPointsMapper, B ...@@ -129,7 +129,7 @@ public class BbsUserPointsServiceImpl extends ServiceImpl<BbsUserPointsMapper, B
* @param detail 积分明细 * @param detail 积分明细
*/ */
@Override @Override
public void incrUserPoints(PointsDetailInfo detail) { public void incrUserPoints(PointsDetail detail) {
synchronized (detail.getUserName().intern()) { synchronized (detail.getUserName().intern()) {
this.pointsServiceImpl.privIncrUserPoints(detail); this.pointsServiceImpl.privIncrUserPoints(detail);
} }
...@@ -142,7 +142,7 @@ public class BbsUserPointsServiceImpl extends ServiceImpl<BbsUserPointsMapper, B ...@@ -142,7 +142,7 @@ public class BbsUserPointsServiceImpl extends ServiceImpl<BbsUserPointsMapper, B
* @param detail 积分明细 * @param detail 积分明细
*/ */
@Override @Override
public void decrUserPoints(PointsDetailInfo detail) { public void decrUserPoints(PointsDetail detail) {
synchronized (detail.getUserName().intern()) { synchronized (detail.getUserName().intern()) {
this.pointsServiceImpl.privDecrUserPoints(detail); this.pointsServiceImpl.privDecrUserPoints(detail);
} }
...@@ -155,7 +155,7 @@ public class BbsUserPointsServiceImpl extends ServiceImpl<BbsUserPointsMapper, B ...@@ -155,7 +155,7 @@ public class BbsUserPointsServiceImpl extends ServiceImpl<BbsUserPointsMapper, B
* @param detail 积分明细 * @param detail 积分明细
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void privIncrUserPoints(PointsDetailInfo detail) { public void privIncrUserPoints(PointsDetail detail) {
int points = detail.getDetailPoints(); int points = detail.getDetailPoints();
if (points < 1) { if (points < 1) {
throw new ServiceException("增加用户积分失败,增加的积分分值不能小于0。"); throw new ServiceException("增加用户积分失败,增加的积分分值不能小于0。");
...@@ -198,7 +198,7 @@ public class BbsUserPointsServiceImpl extends ServiceImpl<BbsUserPointsMapper, B ...@@ -198,7 +198,7 @@ public class BbsUserPointsServiceImpl extends ServiceImpl<BbsUserPointsMapper, B
* @param detail 积分明细 * @param detail 积分明细
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void privDecrUserPoints(PointsDetailInfo detail) { public void privDecrUserPoints(PointsDetail detail) {
int points = detail.getDetailPoints(); int points = detail.getDetailPoints();
if (points < 1) { if (points < 1) {
throw new ServiceException("扣减用户积分失败,扣减的积分分值不能小于0。"); throw new ServiceException("扣减用户积分失败,扣减的积分分值不能小于0。");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment