一、导包

本文的敏感词过滤器用在springboot项目中,因此,首先需要在pom.xml文件中导入如下依赖

<dependency>
		<groupid>org.springframework.boot</groupid>
		<artifactid>spring-boot-starter-aop</artifactid>
</dependency>

<dependency>
		<groupid>org.springframework.boot</groupid>
		<artifactid>spring-boot-starter-thymeleaf</artifactid>
</dependency>

<dependency>
		<groupid>org.springframework.boot</groupid>
		<artifactid>spring-boot-starter-web</artifactid>
</dependency>

<dependency>
		<groupid>org.springframework.boot</groupid>
		<artifactid>spring-boot-devtools</artifactid>
		<scope>runtime</scope>
</dependency>

<dependency>
		<groupid>org.springframework.boot</groupid>
		<artifactid>spring-boot-starter-test</artifactid>
		<scope>test</scope>
</dependency>

<dependency>
		<groupid>org.apache.commons</groupid>
		<artifactid>commons-lang3</artifactid>
		<version>3.9</version>
</dependency>

二、敏感词文件

在resources目录下,创建sensitive-word.txt,里面填入需要过滤的敏感词信息。

三、前缀树的实现

前缀树trienode以一个空节点为头结点,每个节点下包含若干子节点,不同节点代表不同字符。trienode 由两部分组成,首先是一个boolean变量,表示该结点是否为一个关键词的终结点。其次是该结点的子节点集合,在本文中,用hashmap存储子节点,key存储结点代表的字符,类型为character,value为trienode,表示子节点。实现的代码如下。

 //前缀树
    private class trienode{
        //关键词结束标识
        private boolean iskeywordend = false;

        //子节点
        private map<character,trienode> subnodes = new hashmap<>();
		
		//iskeywordend的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);
        }
    }

四、敏感词过滤器的实现

@component
public class sensitivefilter {
    // 替换符
    private static final string replacement = "***";

    //根节点
    private trienode rootnode = new trienode();

    //bean的初始化方法,服务一启动,容器自动给bean执行此方法完成初始化
    //此方法的目的是读取敏感词文件,构建敏感词前缀树
    @postconstruct
    public void init(){
        try(
                inputstream is = this.getclass().getclassloader().getresourceasstream("sensitive-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;
        }
        //指针1
        trienode tempnode = rootnode;
        //指针2
        int begin = 0;
        //指针3
        int position = 0;
        //结果
        stringbuilder sb = new stringbuilder();
        while(position<text.length()){
            char c = text.charat(position);
            /*
            	跳过符号
            	情况一:符号在敏感词前面,将符号写入结果,如 敏感词
            	情况二:符号在敏感词中间,则将符号与敏感词一起替换,如敏感词
            */
            if(issymbol(c)){
                //若指针1处于根节点,对应情况一,将符号计入结果,让指针2向下走一步
                if(tempnode==rootnode){
                    sb.append(c);
                    begin++;
                }
                //无论符号在开头还是敏感词中间,指针3都向下走一步
                position++;
                continue;
            }
            //检查下级节点
            tempnode = tempnode.getsubnode(c);
            if(tempnode==null){
                //以begin开头的的字符串不是敏感词
                sb.append(text.charat(begin));
                //指针2和指针3共同指向指针2的下一个位置
                position = ++begin;
                //指针1重新指向根节点
                tempnode = rootnode;
            }else if(tempnode.iskeywordend()){
                //发现敏感词,将begin~position字符串替换
                sb.append(replacement);
                //进入下一个位置
                begin = ++position;
                //指针1重新指向根节点
                tempnode = rootnode;
            }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);
    }
}

到此这篇关于java实战之敏感词过滤器的文章就介绍到这了,更多相关java敏感词过滤器内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!