风也温柔

计算机科学知识库

java关键字过滤算法 Java怎么使用DFA算法实现敏感词过滤

  本篇内容主要讲解“Java怎么使用DFA算法实现敏感词过滤”java关键字过滤算法 Java怎么使用DFA算法实现敏感词过滤,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java怎么使用DFA算法实现敏感词过滤”吧!

  1 前言

  敏感词过滤就是你在项目中输入某些字(比如输入xxoo相关的文字时)时要能检测出来,很多项目中都会有一个敏感词管理模块,在敏感词管理模块中你可以加入敏感词,然后根据加入的敏感词去过滤输入内容中的敏感词并进行相应的处理,要么提示,要么高亮显示,要么直接替换成其它的文字或者符号代替。

  敏感词过滤的做法有很多,其中有比较常用的如下几种:

  1.查询数据库当中的敏感词,循环每一个敏感词,然后去输入的文本中从头到尾搜索一遍,看是否存在此敏感词,有则做相应的处理,这种方式讲白了就是找到一个处理一个。

  优点:so easy。用java代码实现基本没什么难度。

  缺点:这效率是非常低的,如果是英文时你会发现一个很无语的事情,比如英文a是敏感词,那我如果是一篇英文文档,那程序它得处理多少次敏感词?谁能告诉我?

  2.传说中的DFA算法(有限状态机),也正是我要给大家分享的,毕竟感觉比较通用,算法的原理希望大家能够自己去网上查查

  资料,这里就不详细说明了。

  优点:至少比上面那sb效率高点。

  缺点:对于学过算法的应该不难,对于没学过算法的用起来也不难java关键字过滤算法,就是理解起来有点gg疼,匹配效率也不高,比较耗费内存,

  敏感词越多,内存占用的就越大。

  2 代码实现2.1 敏感词库初始化

  在项目启动前读取数据,将敏感词加载到Map中,具体实现如下:

  建表语句:

  <pre class="brush:sql;">CREATE TABLE sensitive_word (
  id int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
  content varchar(50) NOT NULL COMMENT '关键词',
  create_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  update_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;
 
INSERT INTO fuying.sensitive_word (idcontentcreate_timeupdate_time) VALUES (1, '吴名氏', '2023-03-02 14:21:36', '2023-03-02 14:21:36');</pre>

  实体类.java:

  <pre class="brush:java;">package com.wkf.workrecord.tools.dfa.entity;
 
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
 
import java.io.Serializable;
import java.util.Date;
 
/**
 * @author wuKeFan
 * @date 2023-03-02 13:48:58
 */
@Data
@TableName("sensitive_word")
public class SensitiveWord implements Serializable {
 
    private static final long serialVersionUID = 1L;
 
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
 
    private String content;
 
    private Date createTime;
 
    private Date updateTime;
 
}</pre>

  数据库持久类.java:

  <pre class="brush:java;">package com.wkf.workrecord.tools.dfa.mapper;
 
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.wkf.workrecord.tools.dfa.entity.SensitiveWord;
 
/**
 * @author wuKeFan
 * @date 2023-03-02 13:50:16
 */
public interface SensitiveWordMapper extends BaseMapper {
}</pre>

  类.java和Impl.java:

  <pre class="brush:java;">package com.wkf.workrecord.tools.dfa.service;
 
import com.baomidou.mybatisplus.extension.service.IService;
import com.wkf.workrecord.tools.dfa.entity.SensitiveWord;
 
import java.util.Set;
 
/**
 * 敏感词过滤服务类
 * @author wuKeFan
 * @date 2023-03-02 13:47:04
 */
public interface SensitiveWordService extends IService {
 
    Set sensitiveWordFiltering(String text);
 
}</pre>

  <pre class="brush:java;">package com.wkf.workrecord.tools.dfa.service;
 
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wkf.workrecord.tools.dfa.mapper.SensitiveWordMapper;
import com.wkf.workrecord.tools.dfa.SensitiveWordUtils;
import com.wkf.workrecord.tools.dfa.entity.SensitiveWord;
import org.springframework.stereotype.Service;
import java.util.Set;
 
/**
 * @author wuKeFan
 * @date 2023-03-02 13:48:04
 */
@Service
public class SensitiveWordServiceImpl extends ServiceImpl implements SensitiveWordService{
 
    @Override
    public Set sensitiveWordFiltering(String text) {
        // 得到敏感词有哪些,传入2表示获取所有敏感词
        return SensitiveWordUtils.getSensitiveWord(text, 2);
    }
}</pre>

  敏感词过滤工具类:

<p><pre class="brush:java;">package com.wkf.workrecord.tools.dfa;
 
import com.wkf.workrecord.tools.dfa.entity.SensitiveWord;
import lombok.extern.slf4j.Slf4j;
 
import java.util.*;
 
/**
 * 敏感词过滤工具类
 * @author wuKeFan
 * @date 2023-03-02 13:45:19
 */
@Slf4j
@SuppressWarnings("unused")
public class SensitiveWordUtils {
 
    /**
     * 敏感词库
     */
    public static final Map sensitiveWordMap = new HashMap();
 
    /**
     * 只过滤最小敏感词
     */
    public static int minMatchTYpe = 1;
 
    /**
     * 过滤所有敏感词
     */
    public static int maxMatchType = 2;
 
    /**
     * 初始化敏感词
     */
    public static void initKeyWord(List sensitiveWords) {
        try {
            // 从敏感词集合对象中取出敏感词并封装到Set集合中
            Set keyWordSet = new HashSet();
            for (SensitiveWord s : sensitiveWords) {
                keyWordSet.add(s.getContent().trim());
            }
            // 将敏感词库加入到HashMap中
            addSensitiveWordToHashMap(keyWordSet);
        }
        catch (Exception e) {
            log.error("初始化敏感词出错,", e);
        }
    }
 
    /**
     * 封装敏感词库
     *
     * @param keyWordSet 敏感词库列表
     */
    private static void addSensitiveWordToHashMap(Set keyWordSet) {
        // 敏感词
        String key;
        // 用来按照相应的格式保存敏感词库数据
        Map nowMap;
        // 用来辅助构建敏感词库
        Map newWorMap;
        // 使用一个迭代器来循环敏感词集合
        for (String s : keyWordSet) {
            key = s;
            // 等于敏感词库,HashMap对象在内存中占用的是同一个地址,所以此nowMap对象的变化,sensitiveWordMap对象也会跟着改变
            nowMap = sensitiveWordMap;
            for (int i = 0; i