关于java实现数据过滤

大佬们怎么实现对新增的name、description、title等文本时将敏感词(有表)替换掉,在yml里设置个开关


public static void main(String[] args) {
        List<String> replaceList = Arrays.asList("牛B","牛逼","NB");
        Dto dto = new Dto();
        dto.setName("你真牛逼");
        dto.setDescription("你真牛逼,哈哈NB");
        dto.setTitle("你真厉害");

        dto.doFilter(false,replaceList);
        System.out.println(dto);
        dto.doFilter(true,replaceList);
        System.out.println(dto);
    }

    @Data
    static class Dto{
        private String name;
        private String description;
        private String title;

        public  void doFilter(boolean isFilter,List<String> filterLists){
            if (!isFilter || CollectionUtils.isEmpty(filterLists)){
                return;
            }
            this.name = doFilter(this.name,filterLists);
            this.description = doFilter(this.description,filterLists);
            this.title = doFilter(this.title,filterLists);

        }

        private  String doFilter(String str,List<String> filterLists){
            if (StringUtils.isBlank(str)){
                return str;
            }
            for (String filtetStr : filterLists) {
                if (str.contains(filtetStr)){
                    str = str.replaceAll(filtetStr,"***");
                }
            }
            return str;
        }
    }

执行结果:
Dto(name=你真牛逼, description=你真牛逼,哈哈NB, title=你真厉害)
Dto(name=你真***, description=你真,哈哈, title=你真厉害)

可以使用DFA算法(确定有穷自动机),这样效率比直接判断高很多
下面是之前的一个工具类,你可以参考一下

public class SensitiveWordUtil {

    public static Map<String, Object> dictionaryMap = new HashMap<>();


    /**
     * 生成关键词字典库
     * @param words
     * @return
     */
    public static void initMap(Collection<String> words) {
        if (words == null) {
            System.out.println("敏感词列表不能为空");
            return ;
        }

        // map初始长度words.size(),整个字典库的入口字数(小于words.size(),因为不同的词可能会有相同的首字)
        Map<String, Object> map = new HashMap<>(words.size());
        // 遍历过程中当前层次的数据
        Map<String, Object> curMap = null;
        Iterator<String> iterator = words.iterator();

        while (iterator.hasNext()) {
            String word = iterator.next();
            curMap = map;
            int len = word.length();
            for (int i =0; i < len; i++) {
                // 遍历每个词的字
                String key = String.valueOf(word.charAt(i));
                // 当前字在当前层是否存在, 不存在则新建, 当前层数据指向下一个节点, 继续判断是否存在数据
                Map<String, Object> wordMap = (Map<String, Object>) curMap.get(key);
                if (wordMap == null) {
                    // 每个节点存在两个数据: 下一个节点和isEnd(是否结束标志)
                    wordMap = new HashMap<>(2);
                    wordMap.put("isEnd", "0");
                    curMap.put(key, wordMap);
                }
                curMap = wordMap;
                // 如果当前字是词的最后一个字,则将isEnd标志置1
                if (i == len -1) {
                    curMap.put("isEnd", "1");
                }
            }
        }

        dictionaryMap = map;
    }

    /**
     * 搜索文本中某个文字是否匹配关键词
     * @param text
     * @param beginIndex
     * @return
     */
    private static int checkWord(String text, int beginIndex) {
        if (dictionaryMap == null) {
            throw new RuntimeException("字典不能为空");
        }
        boolean isEnd = false;
        int wordLength = 0;
        Map<String, Object> curMap = dictionaryMap;
        int len = text.length();
        // 从文本的第beginIndex开始匹配
        for (int i = beginIndex; i < len; i++) {
            String key = String.valueOf(text.charAt(i));
            // 获取当前key的下一个节点
            curMap = (Map<String, Object>) curMap.get(key);
            if (curMap == null) {
                break;
            } else {
                wordLength ++;
                if ("1".equals(curMap.get("isEnd"))) {
                    isEnd = true;
                }
            }
        }
        if (!isEnd) {
            wordLength = 0;
        }
        return wordLength;
    }

    /**
     * 获取匹配的关键词和命中次数
     * @param text
     * @return
     */
    public static Map<String, Integer> matchWords(String text) {
        Map<String, Integer> wordMap = new HashMap<>();
        int len = text.length();
        for (int i = 0; i < len; i++) {
            int wordLength = checkWord(text, i);
            if (wordLength > 0) {
                String word = text.substring(i, i + wordLength);
                // 添加关键词匹配次数
                if (wordMap.containsKey(word)) {
                    wordMap.put(word, wordMap.get(word) + 1);
                } else {
                    wordMap.put(word, 1);
                }

                i += wordLength - 1;
            }
        }
        return wordMap;
    }

    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("冰毒");
        initMap(list);
        String content="买卖冰毒是违法的";
        Map<String, Integer> map = matchWords(content);
        System.out.println(map);
    }
}
```java



用contains方法检查,然后用replace方法替换。

这个简单,再yml自定义一个开关,例如 jiance: false,然后再对应的类里面比如controller取出,可以使用@Value注解 赋值给自定义的变量ifGuoLv,每次新增文本时都要判断这个变量的值,如果为true,则执行替换方法,否则不执行

比如 如果yml设置的值是true description属性正则替换

你这是替换所有输入的敏感信息吧,给你个思路:
1、在过滤器参数录入那里进行替换,过滤器中获取request中的参数,对所有参数进行敏感词替换(如果你确定参数名,也可加参数名进行过滤)
2、你的敏感词(有表) 最好放到redis里快速读取,项目启动时加载数据导redis,保存、更新、删除数据时更新redis。

yml只是开关设置,加载到配置类中用作判断即可

只能自己写个工具类,哪些属性需要检查的一个个检查了,可以写个通用的工具类,用反射来获取所有类属性过滤出你要判断的属性,再进行检查替换

String[] tm = {"11", "31", "123"};
String str = "11123131312313";
for (String s : tm) {
str.replaceAll(s, "***");
}

本来看到你的问题是不给钱的想回复你到,然后你删了...我就把我之前的方案写成文章了,自己看吧,也不知道能不能实现你的需求。至于你想要的关键词过滤的写法,如果是我的话就把关键词从库里捞出来,写个for循环一个一个判断直接replaceall,我的文章不适合实时从库里捞,建议你写个定时器每隔一段时间同步到内存里就行了。
https://blog.csdn.net/Tombjp/article/details/122129543

插个眼

自己动手丰衣足食,有问题解决问题,有困难解决困难!有什么疑问可以来交流!