Java Springbool敏感词过工具类滤

1. 功能描述
利用前缀树这种数据结构,设计并开发出敏感词过滤工具。

2. 构建敏感词表
resource/sensitive-words.txt

3. 敏感词过滤器
util/SensitiveUtil.java

构建前缀树
定义过滤方法

package com.wlnl.lanaer.service.api.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.CharUtils;
import org.apache.commons.lang.StringUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class SensitiveUtil {

private static final String FILE_NAME = "sensitive-words.txt";

// 默认替换符
private static final String REPLACEMENT = "***";

// 根节点
private static TrieNode rootNode = new TrieNode();

static {
try (
InputStream is = SensitiveUtil.class.getClassLoader().getResourceAsStream(FILE_NAME);
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
) {
String keyword;
while ((keyword = reader.readLine()) != null) {
// 添加到前缀树
addKeyword(keyword);
}
} catch (IOException e) {
log.error("加载敏感词文件失败: " + e.getMessage());
}
}

// 将一个敏感词添加到前缀树中
private static 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 static boolean hasKeyword(String text) {
if (StringUtils.isBlank(text)) {
return false;
}

// 指针1
TrieNode tempNode = rootNode;
// 指针2
int begin = 0;
// 指针3
int position = 0;

while (position < text.length()) {
char c = text.charAt(position);

// 跳过符号
if (isSymbol(c)) {
// 若指针1处于根节点,将此符号计入结果,让指针2向下走一步
if (tempNode == rootNode) {
begin++;
}
// 无论符号在开头或中间,指针3都向下走一步
position++;
continue;
}

// 检查下级节点
tempNode = tempNode.getSubNode(c);
if (tempNode == null) {
// 进入下一个位置
position = ++begin;
// 重新指向根节点
tempNode = rootNode;
} else if (tempNode.isKeywordEnd()) {
// 发现敏感词
return true;
} else {
// 检查下一个字符
position++;
}
}
return false;
}

/**
* 过滤敏感词
*
* @param text 待过滤的文本
* @return 过滤后的文本
*/
public static String filter(String text) {
return filter(text, REPLACEMENT);
}

/**
* 过滤敏感词
*
* @param text 待过滤的文本
* @param substitute 敏感词替换字符串
* @return 过滤后的文本
*/
public static String filter(String text, String substitute) {
if (StringUtils.isBlank(text)) {
return null;
}
if (null == substitute) {
substitute = REPLACEMENT;
}

// 指针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));
// 进入下一个位置
position = ++begin;
// 重新指向根节点
tempNode = rootNode;
} else if (tempNode.isKeywordEnd()) {
// 发现敏感词,将begin~position字符串替换掉
sb.append(substitute);
// 进入下一个位置
begin = ++position;
// 重新指向根节点
tempNode = rootNode;
} else {
// 检查下一个字符
position++;
}
}

// 将最后一批字符计入结果
sb.append(text.substring(begin));

return sb.toString();
}

// 判断是否为符号
private static boolean isSymbol(Character c) {
// 0x2E80~0x9FFF 是东亚文字范围
return !CharUtils.isAsciiAlphanumeric(c) && (c < 0x2E80 || c > 0x9FFF);
}

// 前缀树
private static class TrieNode {

// 关键词结束标识
private boolean isKeywordEnd = false;

// 子节点(key是下级字符,value是下级节点)
private Map<Character, TrieNode> subNodes = new HashMap<>();

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);
}

}

}

4. 测试过滤敏感词功能

package com.wlnl.lanaer.service.api.mq;

import com.wlnl.lanaer.service.api.KxkdApiServiceApplication;
import com.wlnl.lanaer.service.api.util.BlogKeywordUtil;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit.jupiter.SpringExtension;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {KxkdApiServiceApplication.class})
@AutoConfigureMockMvc
@ExtendWith(SpringExtension.class)
@ActiveProfiles(profiles = "dev")
public class TestSensitiveWords {

public static void main(String[] args) {
String text = "这里可以赌博,可以嫖娼,可以吸毒,哈哈哈!";
String text1 = "这里可以-赌-博-,可以,嫖,娼,,可以=吸=毒=,哈哈哈!";
String text2 = "正规正规";
boolean bool = BlogKeywordUtil.hasKeyword(text);
System.out.println("是否有关键词:" + bool);
System.out.println("过滤后的文本:" + BlogKeywordUtil.filter(text));

System.out.println("是否有关键词:" + BlogKeywordUtil.hasKeyword(text1));
System.out.println("过滤后的文本:" + BlogKeywordUtil.filter(text1));

System.out.println("是否有关键词:" + BlogKeywordUtil.hasKeyword(text2));
System.out.println("过滤后的文本:" + BlogKeywordUtil.filter(text2));
}

}

执行结果

Java Springbool敏感词过工具类滤的更多相关文章

  1. C++ 简单中文敏感词检测工具类

    具体思路: 1->敏感词库,可从数据库读取,也可以从文件加载. 2->将敏感词转化为gbk编码,因为gbk严格按照字符一个字节,汉字两个字节的格式编码,便于容易切分文字段. 3->将 ...

  2. Java实现敏感词过滤 - IKAnalyzer中文分词工具

    IKAnalyzer 是一个开源的,基于java语言开发的轻量级的中文分词工具包. 官网: https://code.google.com/archive/p/ik-analyzer/ 本用例借助 I ...

  3. java实现敏感词过滤(DFA算法)

    小Alan在最近的开发中遇到了敏感词过滤,便去网上查阅了很多敏感词过滤的资料,在这里也和大家分享一下自己的理解. 敏感词过滤应该是不用给大家过多的解释吧?讲白了就是你在项目中输入某些字(比如输入xxo ...

  4. Java实现敏感词过滤 - DFA算法

    Java实现DFA算法进行敏感词过滤 封装工具类如下: 使用前需对敏感词库进行初始化: SensitiveWordUtil.init(sensitiveWordSet); package cn.swf ...

  5. java 实现敏感词(sensitive word)工具详解使用说明

    sensitive-word 平时工作中,只要涉及到用户可以自由发言(博客.文档.论坛),就要考虑内容的敏感性处理. sensitive-word 基于 DFA 算法实现的高性能敏感词工具.工具使用 ...

  6. Java实现敏感词过滤

    敏感词.文字过滤是一个网站必不可少的功能,如何设计一个好的.高效的过滤算法是非常有必要的.前段时间我一个朋友(马上毕业,接触编程不久)要我帮他看一个文字过滤的东西,它说检索效率非常慢.我把它程序拿过来 ...

  7. Java实现敏感词过滤(转)

    敏感词.文字过滤是一个网站必不可少的功能,如何设计一个好的.高效的过滤算法是非常有必要的.前段时间我一个朋友(马上毕业,接触编程不久)要我帮他看一个文字过滤的东西,它说检索效率非常慢.我把它程序拿过来 ...

  8. 转:Java实现敏感词过滤

    敏感词.文字过滤是一个网站必不可少的功能,如何设计一个好的.高效的过滤算法是非常有必要的.前段时间我一个朋友(马上毕业,接触编程不久)要我帮他看一个文字过滤的东西,它说检索效率非常慢.我把它程序拿过来 ...

  9. Java操作文件夹的工具类

    Java操作文件夹的工具类 import java.io.File; public class DeleteDirectory { /** * 删除单个文件 * @param fileName 要删除 ...

  10. Java汉字转成汉语拼音工具类

    Java汉字转成汉语拼音工具类,需要用到pinyin4j.jar包. import net.sourceforge.pinyin4j.PinyinHelper; import net.sourcefo ...

随机推荐

  1. mysql基础_约束

    介绍 约束对应的英语单词:constraint,在创建表的时候,我们可以给表中的字段加上一些约束,来保证这个表中数据的完整性.有效性. 约束的作用就是为了保证:表中的数据有效. 类型 非空约束:not ...

  2. Word书签替换,加盖电子印章及转换PDF(Java实用版)

    一.前言 在项目中有需要对word进行操作的,可以看看哈,本次使用比较强大的spire组件来对word进行操作,免费版支持三页哦,对于不止三页的word文件,可以购买收费版,官网:https://ww ...

  3. Git 环境配置(详解版)

    前言 Git下载官网:https://git-scm.com/downloads 本次使用Github为配置前提(Gitee步骤类似) 环境搭建 1.git安装好去GitHub上注册一个账号,注册好后 ...

  4. <学习笔记> 关于二项式反演

    1 容斥原理的式子: \[|A1∪A2∪...∪An|=\sum_{1≤i≤n}|Ai|−\sum_{1≤i<j≤n}|Ai∩Aj|+...+(−1)^{n−1}×|A1∩A2∩...∩An| ...

  5. Rollup 编译资源离不开 plugin

    rollup 也是一个 JavaScript 的模块化编译工具,可以帮助我们处理资源. 与webpack比较 rollup相比 webpack 理念更为简单,能处理的场景也更有限. 资源类型 处理方式 ...

  6. 让nodejs开启服务更简单--koa篇

    在nodejs原始的http模块中,开启一个服务编码相对麻烦,需要对请求方式及上传的数据进行各种判断,而koa给我们提供了比较便捷的编码方式,同时它还有很多中间件可以直接拿来使用.   首先来看,如何 ...

  7. Health Kit基于数据提供专业方案,改善用户睡眠质量

    什么是CBT-I? 中国社科院等机构今年发布的<中国睡眠研究报告2023>内容显示,2022年,受访者的每晚平均睡眠时长为7.40小时,近半数受访者的每晚平均睡眠时长不足8小时(47.55 ...

  8. 【译】Silverlight 不会消亡 XAML for Blazor 到来

    Userware 正在使用早已消失的.令人怀念的微软 Silverlight Web 开发平台的遗留来支持其新的"XAML for Blazor"产品,该产品允许 .NET 开发人 ...

  9. Hadoop NameNode启动后自动关闭解决方法

    Hadoop NameNode启动后过一会自动关闭了,查看日志文件报内存溢出异常: tail -100 /bigdata/logs/hadoop/hadoop-root-namenode-node1. ...

  10. 大企业才用的分布式唯一Id,它比GUID好

    支持.Net Core(2.0及以上)与.Net Framework(4.5及以上) 可以部署在Docker, Windows, Linux, Mac. 分布式唯一Id,顾名思义,是指在全世界任何一台 ...