bugfix: 修复删除敏感词中可能出现的并发问题

This commit is contained in:
yudasen
2025-02-01 11:34:13 +08:00
parent a6ece9c222
commit dc70bcd684
5 changed files with 70 additions and 58 deletions

View File

@@ -22,10 +22,10 @@ public interface IWordData extends ISensitiveWordDestroy {
/**
* 删除敏感词
* @param word 单词
* @param collection 单词
* @since 0.19.0
*/
void removeWord(String word);
void removeWord(Collection<String> collection);
/**
* 新增敏感词

View File

@@ -639,9 +639,7 @@ public class SensitiveWordBs implements ISensitiveWordDestroy {
// 主要原因是二者没有保持一致,初始化的数据和插入的数据没有做相同的格式化
List<String> formatList = InnerWordFormatUtils.formatWordList(collection, context);
for(String word : formatList) {
this.wordData.removeWord(word);
}
this.wordData.removeWord(formatList);
}
/**
@@ -698,9 +696,8 @@ public class SensitiveWordBs implements ISensitiveWordDestroy {
// 主要原因是二者没有保持一致,初始化的数据和插入的数据没有做相同的格式化
List<String> formatList = InnerWordFormatUtils.formatWordList(collection, context);
for(String word : formatList) {
this.wordDataAllow.removeWord(word);
}
this.wordDataAllow.removeWord(formatList);
}
/**
* 新增敏感词白名单

View File

@@ -1,6 +1,5 @@
package com.github.houbb.sensitive.word.support.data;
import com.github.houbb.heaven.util.lang.StringUtil;
import com.github.houbb.heaven.util.util.CollectionUtil;
import com.github.houbb.sensitive.word.api.IWordData;
import com.github.houbb.sensitive.word.api.context.InnerSensitiveWordContext;
@@ -31,9 +30,9 @@ public abstract class AbstractWordData implements IWordData {
/**
* 删除敏感词
* @param word 敏感词
* @param collection
*/
protected abstract void doRemoveWord(String word);
protected abstract void doRemoveWord(Collection<String> collection);
/**
* 新增敏感词
@@ -49,12 +48,12 @@ public abstract class AbstractWordData implements IWordData {
}
@Override
public void removeWord(String word) {
if(StringUtil.isEmpty(word)) {
public void removeWord(Collection<String> collection) {
if(CollectionUtil.isEmpty(collection)) {
return;
}
doRemoveWord(word);
doRemoveWord(collection);
}
@Override

View File

@@ -89,7 +89,7 @@ public class WordDataHashMap extends AbstractWordData {
}
@Override
protected void doRemoveWord(String word) {
protected void doRemoveWord(Collection<String> collection) {
}

View File

@@ -4,7 +4,6 @@ import com.github.houbb.heaven.annotation.ThreadSafe;
import com.github.houbb.heaven.util.lang.ObjectUtil;
import com.github.houbb.heaven.util.lang.StringUtil;
import com.github.houbb.sensitive.word.api.IWordContext;
import com.github.houbb.sensitive.word.api.IWordData;
import com.github.houbb.sensitive.word.api.context.InnerSensitiveWordContext;
import com.github.houbb.sensitive.word.constant.enums.WordContainsTypeEnum;
@@ -84,49 +83,7 @@ public class WordDataTree extends AbstractWordData {
this.root = newRoot;
}
@Override
protected void doRemoveWord(String word) {
WordDataTreeNode tempNode = root;
//需要删除的
Map<Character, WordDataTreeNode> map = new HashMap<>();
char[] chars = word.toCharArray();
int length = chars.length;
for (int i = 0; i < length; i++) {
//不存在第一个词
WordDataTreeNode subNode = tempNode.getSubNode(chars[i]);
if (subNode == null) {
return;
}
if (i == (length - 1)) {
//尾字符判断是否结束
if (!subNode.end()) {
return;
}
if (subNode.getNodeSize() > 0) {
//尾字符下还存在字符,即标识即可
subNode.end(false);
return;
}
}
if (subNode.end()) {
map.clear();
}
map.put(chars[i], tempNode);
tempNode = subNode;
}
for (Map.Entry<Character, WordDataTreeNode> entry : map.entrySet()) {
WordDataTreeNode value = entry.getValue();
//节点只有一个就置空
if (value.getNodeSize() == 1) {
value.clearNode();
return;
}
//多个就删除
value.removeNode(entry.getKey());
}
}
/**
* 新增敏感词
@@ -143,6 +100,21 @@ public class WordDataTree extends AbstractWordData {
}
}
@Override
protected synchronized void doRemoveWord(Collection<String> collection) {
for (String word : collection) {
if (StringUtil.isEmpty(word)) {
continue;
}
removeWord(this.root, word);
}
}
/**
* 获取当前的 Map
* @param nowNode 当前节点
@@ -211,4 +183,48 @@ public class WordDataTree extends AbstractWordData {
tempNode.end(true);
}
private void removeWord(WordDataTreeNode root, String word){
WordDataTreeNode tempNode = root;
//需要删除的
Map<Character, WordDataTreeNode> map = new HashMap<>();
char[] chars = word.toCharArray();
int length = chars.length;
for (int i = 0; i < length; i++) {
//不存在第一个词
WordDataTreeNode subNode = tempNode.getSubNode(chars[i]);
if (subNode == null) {
return;
}
if (i == (length - 1)) {
//尾字符判断是否结束
if (!subNode.end()) {
return;
}
if (subNode.getNodeSize() > 0) {
//尾字符下还存在字符,即标识即可
subNode.end(false);
return;
}
}
if (subNode.end()) {
map.clear();
}
map.put(chars[i], tempNode);
tempNode = subNode;
}
for (Map.Entry<Character, WordDataTreeNode> entry : map.entrySet()) {
WordDataTreeNode value = entry.getValue();
//节点只有一个就置空
if (value.getNodeSize() == 1) {
value.clearNode();
return;
}
//多个就删除
value.removeNode(entry.getKey());
}
}
}