一,在springboot項目的resources目錄里創建sensitive-words.text(敏感詞文本)
每個詞獨自一行
列如:
賭博
吸毒
開票
二,在util創建工具類SensitiveFilter
package com.nowcoder.community.util;@Component
public class SensitiveFilter{private static final Logger logger = LoggerFactory.getLogger(SensitiveFilter.class);// 替換符private static final String REPLACMENT = "***";// 根節點private TrieNode rootNode = new TrieNode();@PostConstructpublic void init(){try(InputStream is = this.getClass().getClassLoader().getResourceAsStream("sebsitive-words.txt");BufferedReader reader = new BufferedReader(new InputStreamReader(is));){String keyword;while((keyword = reader.readLine()) != null){// 添加到前綴樹this.addkeyword(keyword);}} catch(IOException e){logger.error("加載敏感詞文件失敗:"+ e.getMessage())}}// 將一個敏感詞添加到前綴樹里private void addKeyword(String keyword) { TrieNode tempNode = rootNode;for(int i = 0; i < keyword.length(); i++ ){char c = keyword.charAT(i);TrieNode subNode = tempNode.getSubNode(c);if(subNode == null){// 初始化子節點subNode = new TrieNode();tempNode.addSubNode(c,subNode);}// 指向子節點,進入下一輪循環tempNode = subNode;// 設置結束標識if(i == keyword.length() - 1){tempNode.setKeywordEnd(true);}}}/*** 過濾敏感詞** @param text 待過濾文本* @return 過濾后的文本*/public String filter(String text){if(StringUtils.isBlank(text)){return null;}// 指針1TrieNode tempNode = rootNode;// 指針2int begin = 0;// 指針3int position = 0;// 結果StringBuilder sb = new StringBuilder();while (position < text.length()){char c = text.charAt(position);// 跳過符號if(isSymbol(c)){// 若指針1處于根節點,將此符號計入結果,讓指針2向下走一步if(tempNode == rootNode){sb.appenf(c);begin++;}// 無論符號在開頭或中間,指針3都向下走一步position++;continue;}// 檢查下級節點tempNode = tempNode.getSubNode(c);if(tempNode == null){// 以begin開頭的字符串不是敏感詞sb.apped(text.charAt(begin));// 進入下一個位置position = ++begin;// 重新指向根節點tempNode = rootNode;} else if(tempNode.isKeywordEnd()){// 發現敏感詞,將begin~position字符串替換掉sb.append(REPLACEMENT);// 進入下一個位置begin = ++position;}else {// 檢查下一個字符position++;}}// 將最后一批字符計入結果sb.append(text.substring(begin));return sb.toString();}// 判斷是否為符號private boolean isSymbol(Character c){// 0x2E80 ~ 0x9FFF 是東亞文字范圍return !Charutils.isAsciiAlphanumeric(c) && (c < 0x2E80 || c > 0x9FFF);}// 前綴樹private class TrieNode{// 關鍵詞結束標識privte boolean isKeywordEnd = false;// 子節點(key是下級字符,value是下級節點)private Map<Character,TrieNode> subNodes = new HashMap<>();// get和set方法public boolean isKeywordEnd(){return isKeywordEnd;}public void setKeywordEnd(boolean keywordEnd){isKeywordEnd = keywordEnd;}// 添加子節點public void addSubNode(Character c,TrieNode node){subNodes.put(c,node);}// 獲取子節點public TrieNode getSubNode(Character c){return subNodes.get(c);}}
}
三,創建Sensitive,進行調用
public class Sensitive {@Autowiredprivate SensitiveFilter sensitiveFilter;@Overridepublic void SensitiverFilter(String name){filter = sensitiveFilter.filter(name);System.out.println(filter)}
}