前言
敏感詞過濾應(yīng)該是不用給大家過多的解釋吧?講白了就是你在項(xiàng)目中輸入某些字(比如輸入xxoo相關(guān)的文字時(shí))時(shí)要能檢
測(cè)出來,很多項(xiàng)目中都會(huì)有一個(gè)敏感詞管理模塊,在敏感詞管理模塊中你可以加入敏感詞,然后根據(jù)加入的敏感詞去過濾輸
入內(nèi)容中的敏感詞并進(jìn)行相應(yīng)的處理,要么提示,要么高亮顯示,要么直接替換成其它的文字或者符號(hào)代替。
敏感詞過濾的做法有很多,我簡(jiǎn)單描述我現(xiàn)在理解的幾種:
①查詢數(shù)據(jù)庫當(dāng)中的敏感詞,循環(huán)每一個(gè)敏感詞,然后去輸入的文本中從頭到尾搜索一遍,看是否存在此敏感詞,有則做相
應(yīng)的處理,這種方式講白了就是找到一個(gè)處理一個(gè)。
優(yōu)點(diǎn):so easy。用java代碼實(shí)現(xiàn)基本沒什么難度。
缺點(diǎn):這效率讓我心中奔過十萬匹草泥馬,而且匹配的是不是有些蛋疼,如果是英文時(shí)你會(huì)發(fā)現(xiàn)一個(gè)很無語的事情,比如英文
a是敏感詞,那我如果是一篇英文文檔,那程序它妹的得處理多少次敏感詞?誰能告訴我?
②傳說中的DFA算法(有窮自動(dòng)機(jī)),也正是我要給大家分享的,畢竟感覺比較通用,算法的原理希望大家能夠自己去網(wǎng)上查查
資料,這里就不詳細(xì)說明了。
優(yōu)點(diǎn):至少比上面那sb效率高點(diǎn)。
缺點(diǎn):對(duì)于學(xué)過算法的應(yīng)該不難,對(duì)于沒學(xué)過算法的用起來也不難,就是理解起來有點(diǎn)gg疼,匹配效率也不高,比較耗費(fèi)內(nèi)存,
敏感詞越多,內(nèi)存占用的就越大。
③第三種在這里要特別說明一下,那就是你自己去寫一個(gè)算法吧,或者在現(xiàn)有的算法的基礎(chǔ)上去優(yōu)化,這也是追求的至高境界之一。
那么,傳說中的DFA算法是怎么實(shí)現(xiàn)的呢?
第一步:敏感詞庫初始化(將敏感詞用DFA算法的原理封裝到敏感詞庫中,敏感詞庫采用HashMap保存),代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
package com.cfwx.rox.web.sysmgr.util; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import com.cfwx.rox.web.common.model.entity.SensitiveWord; /** * 敏感詞庫初始化 * * @author AlanLee * */ public class SensitiveWordInit { /** * 敏感詞庫 */ public HashMap sensitiveWordMap; /** * 初始化敏感詞 * * @return */ public Map initKeyWord(List<SensitiveWord> sensitiveWords) { try { // 從敏感詞集合對(duì)象中取出敏感詞并封裝到Set集合中 Set<String> keyWordSet = new HashSet<String>(); for (SensitiveWord s : sensitiveWords) { keyWordSet.add(s.getContent().trim()); } // 將敏感詞庫加入到HashMap中 addSensitiveWordToHashMap(keyWordSet); } catch (Exception e) { e.printStackTrace(); } return sensitiveWordMap; } /** * 封裝敏感詞庫 * * @param keyWordSet */ @SuppressWarnings ( "rawtypes" ) private void addSensitiveWordToHashMap(Set<String> keyWordSet) { // 初始化HashMap對(duì)象并控制容器的大小 sensitiveWordMap = new HashMap(keyWordSet.size()); // 敏感詞 String key = null ; // 用來按照相應(yīng)的格式保存敏感詞庫數(shù)據(jù) Map nowMap = null ; // 用來輔助構(gòu)建敏感詞庫 Map<String, String> newWorMap = null ; // 使用一個(gè)迭代器來循環(huán)敏感詞集合 Iterator<String> iterator = keyWordSet.iterator(); while (iterator.hasNext()) { key = iterator.next(); // 等于敏感詞庫,HashMap對(duì)象在內(nèi)存中占用的是同一個(gè)地址,所以此nowMap對(duì)象的變化,sensitiveWordMap對(duì)象也會(huì)跟著改變 nowMap = sensitiveWordMap; for ( int i = 0 ; i < key.length(); i++) { // 截取敏感詞當(dāng)中的字,在敏感詞庫中字為HashMap對(duì)象的Key鍵值 char keyChar = key.charAt(i); // 判斷這個(gè)字是否存在于敏感詞庫中 Object wordMap = nowMap.get(keyChar); if (wordMap != null ) { nowMap = (Map) wordMap; } else { newWorMap = new HashMap<String, String>(); newWorMap.put( "isEnd" , "0" ); nowMap.put(keyChar, newWorMap); nowMap = newWorMap; } // 如果該字是當(dāng)前敏感詞的最后一個(gè)字,則標(biāo)識(shí)為結(jié)尾字 if (i == key.length() - 1 ) { nowMap.put( "isEnd" , "1" ); } System.out.println( "封裝敏感詞庫過程:" +sensitiveWordMap); } System.out.println( "查看敏感詞庫數(shù)據(jù):" + sensitiveWordMap); } } } |
第二步:寫一個(gè)敏感詞過濾工具類,里面可以寫上自己需要的方法,代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
|
package com.cfwx.rox.web.sysmgr.util; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; /** * 敏感詞過濾工具類 * * @author AlanLee * */ public class SensitivewordEngine { /** * 敏感詞庫 */ public static Map sensitiveWordMap = null ; /** * 只過濾最小敏感詞 */ public static int minMatchTYpe = 1 ; /** * 過濾所有敏感詞 */ public static int maxMatchType = 2 ; /** * 敏感詞庫敏感詞數(shù)量 * * @return */ public static int getWordSize() { if (SensitivewordEngine.sensitiveWordMap == null ) { return 0 ; } return SensitivewordEngine.sensitiveWordMap.size(); } /** * 是否包含敏感詞 * * @param txt * @param matchType * @return */ public static boolean isContaintSensitiveWord(String txt, int matchType) { boolean flag = false ; for ( int i = 0 ; i < txt.length(); i++) { int matchFlag = checkSensitiveWord(txt, i, matchType); if (matchFlag > 0 ) { flag = true ; } } return flag; } /** * 獲取敏感詞內(nèi)容 * * @param txt * @param matchType * @return 敏感詞內(nèi)容 */ public static Set<String> getSensitiveWord(String txt, int matchType) { Set<String> sensitiveWordList = new HashSet<String>(); for ( int i = 0 ; i < txt.length(); i++) { int length = checkSensitiveWord(txt, i, matchType); if (length > 0 ) { // 將檢測(cè)出的敏感詞保存到集合中 sensitiveWordList.add(txt.substring(i, i + length)); i = i + length - 1 ; } } return sensitiveWordList; } /** * 替換敏感詞 * * @param txt * @param matchType * @param replaceChar * @return */ public static String replaceSensitiveWord(String txt, int matchType, String replaceChar) { String resultTxt = txt; Set<String> set = getSensitiveWord(txt, matchType); Iterator<String> iterator = set.iterator(); String word = null ; String replaceString = null ; while (iterator.hasNext()) { word = iterator.next(); replaceString = getReplaceChars(replaceChar, word.length()); resultTxt = resultTxt.replaceAll(word, replaceString); } return resultTxt; } /** * 替換敏感詞內(nèi)容 * * @param replaceChar * @param length * @return */ private static String getReplaceChars(String replaceChar, int length) { String resultReplace = replaceChar; for ( int i = 1 ; i < length; i++) { resultReplace += replaceChar; } return resultReplace; } /** * 檢查敏感詞數(shù)量 * * @param txt * @param beginIndex * @param matchType * @return */ public static int checkSensitiveWord(String txt, int beginIndex, int matchType) { boolean flag = false ; // 記錄敏感詞數(shù)量 int matchFlag = 0 ; char word = 0 ; Map nowMap = SensitivewordEngine.sensitiveWordMap; for ( int i = beginIndex; i < txt.length(); i++) { word = txt.charAt(i); // 判斷該字是否存在于敏感詞庫中 nowMap = (Map) nowMap.get(word); if (nowMap != null ) { matchFlag++; // 判斷是否是敏感詞的結(jié)尾字,如果是結(jié)尾字則判斷是否繼續(xù)檢測(cè) if ( "1" .equals(nowMap.get( "isEnd" ))) { flag = true ; // 判斷過濾類型,如果是小過濾則跳出循環(huán),否則繼續(xù)循環(huán) if (SensitivewordEngine.minMatchTYpe == matchType) { break ; } } } else { break ; } } if (!flag) { matchFlag = 0 ; } return matchFlag; } } |
第三步:一切都準(zhǔn)備就緒,當(dāng)然是查詢好數(shù)據(jù)庫當(dāng)中的敏感詞,并且開始過濾咯,代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
@SuppressWarnings ( "rawtypes" ) @Override public Set<String> sensitiveWordFiltering(String text) { // 初始化敏感詞庫對(duì)象 SensitiveWordInit sensitiveWordInit = new SensitiveWordInit(); // 從數(shù)據(jù)庫中獲取敏感詞對(duì)象集合(調(diào)用的方法來自Dao層,此方法是service層的實(shí)現(xiàn)類) List<SensitiveWord> sensitiveWords = sensitiveWordDao.getSensitiveWordListAll(); // 構(gòu)建敏感詞庫 Map sensitiveWordMap = sensitiveWordInit.initKeyWord(sensitiveWords); // 傳入SensitivewordEngine類中的敏感詞庫 SensitivewordEngine.sensitiveWordMap = sensitiveWordMap; // 得到敏感詞有哪些,傳入2表示獲取所有敏感詞 Set<String> set = SensitivewordEngine.getSensitiveWord(text, 2 ); return set; } |
最后一步:在Controller層寫一個(gè)方法給前端請(qǐng)求,前端獲取到需要的數(shù)據(jù)并進(jìn)行相應(yīng)的處理,代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
/** * 敏感詞過濾 * * @param text * @return */ @RequestMapping (value = "/word/filter" ) @ResponseBody public RespVo sensitiveWordFiltering(String text) { RespVo respVo = new RespVo(); try { Set<String> set = sensitiveWordService.sensitiveWordFiltering(text); respVo.setResult(set); } catch (Exception e) { throw new RoxException( "過濾敏感詞出錯(cuò),請(qǐng)聯(lián)系維護(hù)人員" ); } return respVo; } |
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,代碼中寫了不少的注釋,大家可以動(dòng)動(dòng)自己的腦筋好好的理解一下。希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對(duì)服務(wù)器之家的支持。
原文鏈接:http://www.cnblogs.com/AlanLee/p/5329555.html