java利用DFA算法实现敏感词过滤功能
前言
敏感词过滤应该是不用给大家过多的解释吧?讲白了就是你在项目中输入某些字(比如输入xxoo相关的文字时)时要能检
测出来,很多项目中都会有一个敏感词管理模块,在敏感词管理模块中你可以加入敏感词,然后根据加入的敏感词去过滤输
入内容中的敏感词并进行相应的处理,要么提示,要么高亮显示,要么直接替换成其它的文字或者符号代替。
敏感词过滤的做法有很多,我简单描述我现在理解的几种:
①查询数据库当中的敏感词,循环每一个敏感词,然后去输入的文本中从头到尾搜索一遍,看是否存在此敏感词,有则做相
应的处理,这种方式讲白了就是找到一个处理一个。
优点:soeasy。用java代码实现基本没什么难度。
缺点:这效率让我心中奔过十万匹草泥马,而且匹配的是不是有些蛋疼,如果是英文时你会发现一个很无语的事情,比如英文
a是敏感词,那我如果是一篇英文文档,那程序它妹的得处理多少次敏感词?谁能告诉我?
②传说中的DFA算法(有穷自动机),也正是我要给大家分享的,毕竟感觉比较通用,算法的原理希望大家能够自己去网上查查
资料,这里就不详细说明了。
优点:至少比上面那sb效率高点。
缺点:对于学过算法的应该不难,对于没学过算法的用起来也不难,就是理解起来有点gg疼,匹配效率也不高,比较耗费内存,
敏感词越多,内存占用的就越大。
③第三种在这里要特别说明一下,那就是你自己去写一个算法吧,或者在现有的算法的基础上去优化,这也是追求的至高境界之一。
那么,传说中的DFA算法是怎么实现的呢?
第一步:敏感词库初始化(将敏感词用DFA算法的原理封装到敏感词库中,敏感词库采用HashMap保存),代码如下:
packagecom.cfwx.rox.web.sysmgr.util;
importjava.util.HashMap;
importjava.util.HashSet;
importjava.util.Iterator;
importjava.util.List;
importjava.util.Map;
importjava.util.Set;
importcom.cfwx.rox.web.common.model.entity.SensitiveWord;
/**
*敏感词库初始化
*
*@authorAlanLee
*
*/
publicclassSensitiveWordInit
{
/**
*敏感词库
*/
publicHashMapsensitiveWordMap;
/**
*初始化敏感词
*
*@return
*/
publicMapinitKeyWord(ListsensitiveWords)
{
try
{
//从敏感词集合对象中取出敏感词并封装到Set集合中
SetkeyWordSet=newHashSet();
for(SensitiveWords:sensitiveWords)
{
keyWordSet.add(s.getContent().trim());
}
//将敏感词库加入到HashMap中
addSensitiveWordToHashMap(keyWordSet);
}
catch(Exceptione)
{
e.printStackTrace();
}
returnsensitiveWordMap;
}
/**
*封装敏感词库
*
*@paramkeyWordSet
*/
@SuppressWarnings("rawtypes")
privatevoidaddSensitiveWordToHashMap(SetkeyWordSet)
{
//初始化HashMap对象并控制容器的大小
sensitiveWordMap=newHashMap(keyWordSet.size());
//敏感词
Stringkey=null;
//用来按照相应的格式保存敏感词库数据
MapnowMap=null;
//用来辅助构建敏感词库
MapnewWorMap=null;
//使用一个迭代器来循环敏感词集合
Iteratoriterator=keyWordSet.iterator();
while(iterator.hasNext())
{
key=iterator.next();
//等于敏感词库,HashMap对象在内存中占用的是同一个地址,所以此nowMap对象的变化,sensitiveWordMap对象也会跟着改变
nowMap=sensitiveWordMap;
for(inti=0;i();
newWorMap.put("isEnd","0");
nowMap.put(keyChar,newWorMap);
nowMap=newWorMap;
}
//如果该字是当前敏感词的最后一个字,则标识为结尾字
if(i==key.length()-1)
{
nowMap.put("isEnd","1");
}
System.out.println("封装敏感词库过程:"+sensitiveWordMap);
}
System.out.println("查看敏感词库数据:"+sensitiveWordMap);
}
}
}
第二步:写一个敏感词过滤工具类,里面可以写上自己需要的方法,代码如下:
packagecom.cfwx.rox.web.sysmgr.util;
importjava.util.HashSet;
importjava.util.Iterator;
importjava.util.Map;
importjava.util.Set;
/**
*敏感词过滤工具类
*
*@authorAlanLee
*
*/
publicclassSensitivewordEngine
{
/**
*敏感词库
*/
publicstaticMapsensitiveWordMap=null;
/**
*只过滤最小敏感词
*/
publicstaticintminMatchTYpe=1;
/**
*过滤所有敏感词
*/
publicstaticintmaxMatchType=2;
/**
*敏感词库敏感词数量
*
*@return
*/
publicstaticintgetWordSize()
{
if(SensitivewordEngine.sensitiveWordMap==null)
{
return0;
}
returnSensitivewordEngine.sensitiveWordMap.size();
}
/**
*是否包含敏感词
*
*@paramtxt
*@parammatchType
*@return
*/
publicstaticbooleanisContaintSensitiveWord(Stringtxt,intmatchType)
{
booleanflag=false;
for(inti=0;i0)
{
flag=true;
}
}
returnflag;
}
/**
*获取敏感词内容
*
*@paramtxt
*@parammatchType
*@return敏感词内容
*/
publicstaticSetgetSensitiveWord(Stringtxt,intmatchType)
{
SetsensitiveWordList=newHashSet();
for(inti=0;i0)
{
//将检测出的敏感词保存到集合中
sensitiveWordList.add(txt.substring(i,i+length));
i=i+length-1;
}
}
returnsensitiveWordList;
}
/**
*替换敏感词
*
*@paramtxt
*@parammatchType
*@paramreplaceChar
*@return
*/
publicstaticStringreplaceSensitiveWord(Stringtxt,intmatchType,StringreplaceChar)
{
StringresultTxt=txt;
Setset=getSensitiveWord(txt,matchType);
Iteratoriterator=set.iterator();
Stringword=null;
StringreplaceString=null;
while(iterator.hasNext())
{
word=iterator.next();
replaceString=getReplaceChars(replaceChar,word.length());
resultTxt=resultTxt.replaceAll(word,replaceString);
}
returnresultTxt;
}
/**
*替换敏感词内容
*
*@paramreplaceChar
*@paramlength
*@return
*/
privatestaticStringgetReplaceChars(StringreplaceChar,intlength)
{
StringresultReplace=replaceChar;
for(inti=1;i
第三步:一切都准备就绪,当然是查询好数据库当中的敏感词,并且开始过滤咯,代码如下:
@SuppressWarnings("rawtypes")
@Override
publicSetsensitiveWordFiltering(Stringtext)
{
//初始化敏感词库对象
SensitiveWordInitsensitiveWordInit=newSensitiveWordInit();
//从数据库中获取敏感词对象集合(调用的方法来自Dao层,此方法是service层的实现类)
ListsensitiveWords=sensitiveWordDao.getSensitiveWordListAll();
//构建敏感词库
MapsensitiveWordMap=sensitiveWordInit.initKeyWord(sensitiveWords);
//传入SensitivewordEngine类中的敏感词库
SensitivewordEngine.sensitiveWordMap=sensitiveWordMap;
//得到敏感词有哪些,传入2表示获取所有敏感词
Setset=SensitivewordEngine.getSensitiveWord(text,2);
returnset;
}
最后一步:在Controller层写一个方法给前端请求,前端获取到需要的数据并进行相应的处理,代码如下:
/**
*敏感词过滤
*
*@paramtext
*@return
*/
@RequestMapping(value="/word/filter")
@ResponseBody
publicRespVosensitiveWordFiltering(Stringtext)
{
RespVorespVo=newRespVo();
try
{
Setset=sensitiveWordService.sensitiveWordFiltering(text);
respVo.setResult(set);
}
catch(Exceptione)
{
thrownewRoxException("过滤敏感词出错,请联系维护人员");
}
returnrespVo;
}
总结
以上就是这篇文章的全部内容了,代码中写了不少的注释,大家可以动动自己的脑筋好好的理解一下。希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对毛票票的支持。