使用hutool的dfa
工具类可以很好的帮助我们来实现敏感词过滤的功能,下面从用例入手来逐步地去j简单了解一下dfa工具类。
字典树
DFA算法的核心是建立了以敏感词为基础的许多敏感词树(字典树)。 它的基本思想是基于状态转移来检索敏感词。
字典树,是一种树形结构树形结构,主要用于统计,排序和保存大量的字符串。
主要思想:利用字符串的公共前缀来节约存储空间,很好地利用了串的公共前缀,节约了存储空间,字典树主要包含插入和查找两种操作。
初始化敏感词库
在文本中查找敏感词之前,首先需要一个存放敏感词的词库作为查找标准。
public void initKeyWord() throws IOException {List<String> strings = new ArrayList<>();URL path = ResourceUtil.getResource("txtTemplate/words.txt");File file = FileUtil.file(path);FileReader reader = new FileReader(file);BufferedReader bufferedReader = new BufferedReader(reader);String line = bufferedReader.readLine();while (line != null) {strings.add(line);line = bufferedReader.readLine();}SensitiveUtil.init(strings);}
此段代码通过读取文件中的敏感词来初始化词库,主角自然是SensitiveUtil
工具类。此工具类中,有一个棵重要的树:dfa字典树。
private static final WordTree sensitiveTree = new WordTree();public static void init(Collection<String> sensitiveWords) {sensitiveTree.clear();sensitiveTree.addWords(sensitiveWords);}
可以看到是通过WordTree
的addWords
中的添加方法来构建敏感词的字典树的。
ublic WordTree addWord(String word) {final Filter<Character> charFilter = this.charFilter;WordTree parent = null;WordTree current = this;WordTree child;char currentChar = 0;final int length = word.length();for (int i = 0; i < length; i++) {currentChar = word.charAt(i);if (charFilter.accept(currentChar)) {child = current.get(currentChar);if (child == null) {child = new WordTree();current.put(currentChar, child);}parent = current;current = child;}}if (null != parent) {parent.setEnd(currentChar);}return this;}
查找敏感词并替换
对传入的文本进行敏感词查找,并将敏感词替换为相应数量的*
。
public String replaceKeyWords(String text){List<FoundWord> matchAll = SensitiveUtil.getFoundAllSensitive(text, false, true);if (matchAll.size() > 0) {for (FoundWord match : matchAll) {String str = match.getFoundWord();StringBuilder replace = new StringBuilder();for (int i = 0; i < StrUtil.length(str); i++) {replace.append("*");}text = StrUtil.replace(text, str, replace.toString());}}return text;
}
FoundWord
是在工具类中自定义的类,通过getFoundWord()
方法可以拿到查找到的单词,详细信息请查阅源码。getFoundAllSensitive
方法对敏感词进行查找,返回一个FoundWord
集合
public static List<FoundWord> getFoundAllSensitive(String text) {return sensitiveTree.matchAllWords(text);
}