SpringBoot 框架下高效敏感詞過(guò)濾功能的實(shí)現(xiàn)方案
在實(shí)際項(xiàng)目開(kāi)發(fā)中,內(nèi)容安全審核是一個(gè)非常重要的功能。本文將詳細(xì)介紹如何在SpringBoot項(xiàng)目中實(shí)現(xiàn)一個(gè)功能完善的敏感詞過(guò)濾系統(tǒng)。我們將從項(xiàng)目搭建、核心代碼實(shí)現(xiàn)到實(shí)際應(yīng)用場(chǎng)景逐步展開(kāi)講解。
一、項(xiàng)目準(zhǔn)備
首先,創(chuàng)建一個(gè)SpringBoot項(xiàng)目,在pom.xml中添加必要的依賴:
- Spring Web:用于構(gòu)建 RESTful API。
- Lombok:簡(jiǎn)化 JavaBean 的編寫(xiě),這里主要用于日志記錄注解。
- Apache Commons Lang3:提供了一些常用的工具類,如字符串處理等。
- Spring Data Redis:如果要將敏感詞存儲(chǔ)在 Redis 中,用于操作 Redis 數(shù)據(jù)庫(kù)。
<dependencies>
<!-- SpringBoot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Redis依賴 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- Commons Lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
</dependencies>二、核心代碼實(shí)現(xiàn)
1、敏感詞過(guò)濾器實(shí)現(xiàn)類
@Component
@Slf4j
public class SensitiveWordFilter {
// 敏感詞字典樹(shù),用于存儲(chǔ)敏感詞
private Map<Character, Map> sensitiveWordMap;
// 最小匹配規(guī)則,表示找到第一個(gè)匹配到的敏感詞就返回
public static final int MATCH_TYPE_MIN = 1;
// 最大匹配規(guī)則,表示找到最長(zhǎng)的匹配敏感詞再返回
public static final int MATCH_TYPE_MAX = 2;
// 注入Redis模板,用于從Redis中加載敏感詞
@Resource
private StringRedisTemplate stringRedisTemplate;
/**
* 初始化敏感詞過(guò)濾器,包括從Redis加載敏感詞
*/
@PostConstruct
public void init() {
sensitiveWordMap = new HashMap<>();
// 從Redis加載敏感詞并初始化字典樹(shù)
loadSensitiveWordsFromRedis();
}
/**
* 從Redis加載敏感詞并初始化到字典樹(shù)中
*/
private void loadSensitiveWordsFromRedis() {
try {
// 從Redis的sensitive_words集合中獲取所有敏感詞
Set<String> words = stringRedisTemplate.opsForSet().members("sensitive_words");
if (words != null) {
// 遍歷敏感詞集合,將每個(gè)敏感詞添加到字典樹(shù)中
words.forEach(this::addWordToMap);
}
} catch (Exception e) {
// 記錄加載敏感詞失敗日志
log.error("Failed to load sensitive words from Redis", e);
}
}
/**
* 將敏感詞添加到字典樹(shù)中
* @param word 要添加的敏感詞
*/
public void addWordToMap(String word) {
Map<Character, Map> currentMap = sensitiveWordMap;
for (int i = 0; i < word.length(); i++) {
char c = word.charAt(i);
Map<Character, Map> subMap = currentMap.get(c);
if (subMap == null) {
// 如果當(dāng)前字符不存在于字典樹(shù)中,則創(chuàng)建新的節(jié)點(diǎn)
subMap = new HashMap<>();
currentMap.put(c, subMap);
}
currentMap = subMap;
// 如果是敏感詞的最后一個(gè)字符,則標(biāo)記為敏感詞結(jié)束
if (i == word.length() - 1) {
currentMap.put('$', null);
}
}
}
/**
* 檢查文本中是否包含敏感詞(最小匹配規(guī)則)
* @param text 要檢查的文本
* @return 如果包含敏感詞則返回true,否則返回false
*/
public boolean containsSensitiveWord(String text) {
if (StringUtils.isBlank(text)) {
return false;
}
// 遍歷文本中的每個(gè)字符,檢查是否存在敏感詞
for (int i = 0; i < text.length(); i++) {
int length = checkSensitiveWord(text, i, MATCH_TYPE_MIN);
if (length > 0) {
return true;
}
}
return false;
}
/**
* 在文本中找到所有敏感詞(最大匹配規(guī)則)
* @param text 要查找的文本
* @return 包含所有找到的敏感詞的集合
*/
public Set<String> findSensitiveWords(String text) {
Set<String> sensitiveWords = new HashSet<>();
if (StringUtils.isBlank(text)) {
return sensitiveWords;
}
// 遍歷文本中的每個(gè)字符,查找敏感詞并添加到集合中
for (int i = 0; i < text.length(); i++) {
int length = checkSensitiveWord(text, i, MATCH_TYPE_MAX);
if (length > 0) {
sensitiveWords.add(text.substring(i, i + length));
// 更新索引以跳過(guò)已找到的敏感詞
i = i + length - 1;
}
}
return sensitiveWords;
}
/**
* 過(guò)濾文本中的敏感詞,用'*'替換
* @param text 要過(guò)濾的文本
* @return 過(guò)濾后的文本
*/
public String filter(String text) {
if (StringUtils.isBlank(text)) {
return text;
}
StringBuilder result = new StringBuilder(text);
Set<String> words = findSensitiveWords(text);
// 遍歷找到的敏感詞,用'*'替換
for (String word : words) {
int index = result.indexOf(word);
while (index != -1) {
for (int i = index; i < index + word.length(); i++) {
result.setCharAt(i, '*');
}
index = result.indexOf(word, index + 1);
}
}
return result.toString();
}
/**
* 檢查文本中從指定索引開(kāi)始的子串是否包含敏感詞
* @param text 要檢查的文本
* @param beginIndex 開(kāi)始檢查的索引
* @param matchType 匹配規(guī)則(最小匹配或最大匹配)
* @return 找到的敏感詞長(zhǎng)度,如果沒(méi)有找到則返回0
*/
private int checkSensitiveWord(String text, int beginIndex, int matchType) {
Map<Character, Map> currentMap = sensitiveWordMap;
int wordLength = 0;
int maxLength = 0;
// 從指定索引開(kāi)始遍歷文本字符
for (int i = beginIndex; i < text.length(); i++) {
char c = text.charAt(i);
currentMap = currentMap.get(c);
if (currentMap == null) {
break;
}
wordLength++;
// 如果當(dāng)前節(jié)點(diǎn)標(biāo)記為敏感詞結(jié)束
if (currentMap.containsKey('$')) {
if (matchType == MATCH_TYPE_MIN) {
// 最小匹配規(guī)則,返回當(dāng)前敏感詞長(zhǎng)度
return wordLength;
} else {
// 最大匹配規(guī)則,記錄當(dāng)前敏感詞長(zhǎng)度,繼續(xù)檢查是否還有更長(zhǎng)的敏感詞
maxLength = wordLength;
}
}
}
// 最大匹配規(guī)則下返回最長(zhǎng)敏感詞長(zhǎng)度
return maxLength;
}
}2. 配置類
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.context.annotation.Bean;
@Configuration
public class RedisConfig {
/**
* 創(chuàng)建并配置StringRedisTemplate的Bean實(shí)例
*
* @param connectionFactory Redis連接工廠實(shí)例,用于創(chuàng)建與Redis服務(wù)器的連接
* @return 配置好的StringRedisTemplate實(shí)例,可用于在Spring應(yīng)用中方便地操作Redis中的字符串?dāng)?shù)據(jù)類型
*/
@Bean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory connectionFactory) {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(connectionFactory);
return template;
}
}3. Controller實(shí)現(xiàn)
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.beans.factory.annotation.Resource;
import java.util.Set;
@RestController
@RequestMapping("/api/sensitive")
@Slf4j
public class SensitiveWordController {
@Resource
private SensitiveWordFilter sensitiveWordFilter;
@Resource
private StringRedisTemplate stringRedisTemplate;
/**
* 處理添加敏感詞的請(qǐng)求
*
* @param word 要添加的敏感詞內(nèi)容,通過(guò)請(qǐng)求體傳入
* @return 返回添加結(jié)果的響應(yīng)實(shí)體,添加成功則返回狀態(tài)碼200及"添加成功"消息,添加失敗則返回狀態(tài)碼500及"添加失敗"消息
*/
@PostMapping("/word")
public ResponseEntity<String> addSensitiveWord(@RequestBody String word) {
try {
// 將敏感詞添加到Redis的集合中
stringRedisTemplate.opsForSet().add("sensitive_words", word);
// 將敏感詞添加到敏感詞過(guò)濾器的字典樹(shù)中
sensitiveWordFilter.addWordToMap(word);
return ResponseEntity.ok("添加成功");
} catch (Exception e) {
log.error("添加敏感詞失敗", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("添加失敗");
}
}
/**
* 處理檢查文本是否包含敏感詞的請(qǐng)求
*
* @param text 要檢查的文本內(nèi)容,通過(guò)請(qǐng)求體傳入
* @return 返回檢查結(jié)果的響應(yīng)實(shí)體,包含文本是否包含敏感詞的布爾值,狀態(tài)碼為200
*/
@PostMapping("/check")
public ResponseEntity<Boolean> checkText(@RequestBody String text) {
return ResponseEntity.ok(sensitiveWordFilter.containsSensitiveWord(text));
}
/**
* 處理過(guò)濾文本中敏感詞的請(qǐng)求
*
* @param text 要過(guò)濾的文本內(nèi)容,通過(guò)請(qǐng)求體傳入
* @return 返回過(guò)濾后的文本內(nèi)容的響應(yīng)實(shí)體,狀態(tài)碼為200
*/
@PostMapping("/filter")
public ResponseEntity<String> filterText(@RequestBody String text) {
return ResponseEntity.ok(sensitiveWordFilter.filter(text));
}
/**
* 處理獲取文本中所有敏感詞的請(qǐng)求
*
* @param text 要獲取敏感詞的文本內(nèi)容,通過(guò)請(qǐng)求體傳入
* @return 返回包含文本中所有敏感詞的集合的響應(yīng)實(shí)體,狀態(tài)碼為200
*/
@PostMapping("/find")
public ResponseEntity<Set<String>> findSensitiveWords(@RequestBody String text) {
return ResponseEntity.ok(sensitiveWordFilter.findSensitiveWords(text));
}
}三、配置文件
在application.yml中添加Redis配置:
spring:
redis:
host: localhost
port: 6379
database: 0
timeout: 10000四、使用示例
1. 添加敏感詞
curl -X POST http://localhost:8080/api/sensitive/word -d "敏感詞1"
2. 檢查文本
curl -X POST http://localhost:8080/api/sensitive/check -d "這是一段包含敏感詞1的文本"
3. 過(guò)濾文本
curl -X POST http://localhost:8080/api/sensitive/filter -d "這是一段包含敏感詞1的文本"
五、性能優(yōu)化建議
1、Redis優(yōu)化
使用Redis集群提高可用性
通過(guò)Redis Cluster模式,將數(shù)據(jù)分散存儲(chǔ)在多個(gè)節(jié)點(diǎn)上,實(shí)現(xiàn)水平擴(kuò)展和負(fù)載均衡。這不僅可以提高并發(fā)處理能力,還能在主節(jié)點(diǎn)故障時(shí),通過(guò)自動(dòng)的故障轉(zhuǎn)移機(jī)制保證系統(tǒng)的可用性。
實(shí)現(xiàn)Redis緩存預(yù)熱
在系統(tǒng)上線前或低峰期,提前將熱點(diǎn)數(shù)據(jù)加載到Redis緩存中,以減少用戶請(qǐng)求時(shí)的數(shù)據(jù)庫(kù)查詢壓力,提高響應(yīng)速度??梢酝ㄟ^(guò)分析歷史訪問(wèn)記錄,確定熱點(diǎn)數(shù)據(jù),并使用腳本程序觸發(fā)數(shù)據(jù)預(yù)熱過(guò)程。
添加Redis連接池配置
使用連接池來(lái)管理Redis的連接,可以減少頻繁創(chuàng)建和關(guān)閉連接的開(kāi)銷,提高連接復(fù)用率。配置連接池時(shí),需要根據(jù)實(shí)際業(yè)務(wù)需求和服務(wù)器資源情況,合理設(shè)置最大連接數(shù)、最大空閑連接數(shù)等參數(shù)。
并發(fā)處理
Redis本身支持高并發(fā)處理,但可以通過(guò)進(jìn)一步優(yōu)化配置和使用相關(guān)技術(shù)來(lái)提高并發(fā)性能。例如,使用Redis的Pipeline功能將多個(gè)命令打包并一次性執(zhí)行,減少網(wǎng)絡(luò)通信的開(kāi)銷;使用分布式鎖和樂(lè)觀鎖等技術(shù)來(lái)協(xié)調(diào)多個(gè)客戶端之間的并發(fā)訪問(wèn)。
使用本地緩存減少Redis訪問(wèn)
在應(yīng)用服務(wù)器本地設(shè)置一層緩存(如Guava Cache或Caffeine等),用于存儲(chǔ)一些訪問(wèn)頻率高且變化不頻繁的數(shù)據(jù)。當(dāng)數(shù)據(jù)在本地緩存中命中時(shí),可以直接返回結(jié)果,減少對(duì)Redis的訪問(wèn)壓力。
2、功能擴(kuò)展
支持敏感詞分級(jí)
根據(jù)敏感詞的嚴(yán)重程度或影響范圍,將其分為不同的級(jí)別。在過(guò)濾敏感詞時(shí),可以根據(jù)級(jí)別采取不同的處理措施(如替換、刪除或警告等)。
實(shí)現(xiàn)自定義替換規(guī)則
提供一種機(jī)制,允許用戶根據(jù)自己的需求定義敏感詞的替換規(guī)則。例如,可以將某些敏感詞替換為指定的占位符或符號(hào),以避免直接顯示敏感內(nèi)容。
添加白名單機(jī)制優(yōu)化
對(duì)于一些特定的用戶或內(nèi)容,可以將其添加到白名單中,以允許其包含敏感詞而不被過(guò)濾。這可以用于一些特殊的場(chǎng)景,如內(nèi)部測(cè)試或特定用戶的權(quán)限管理。
實(shí)現(xiàn)敏感詞的定時(shí)更新機(jī)制
通過(guò)設(shè)置定時(shí)任務(wù)或使用Redis的發(fā)布訂閱系統(tǒng),定期從外部數(shù)據(jù)源(如數(shù)據(jù)庫(kù)、文件或遠(yuǎn)程服務(wù)器等)獲取最新的敏感詞列表,并更新到Redis緩存中。這可以確保敏感詞過(guò)濾的準(zhǔn)確性和及時(shí)性。
添加并發(fā)控制
在處理敏感詞過(guò)濾等操作時(shí),需要考慮并發(fā)控制的問(wèn)題??梢允褂肦edis的分布式鎖或其他并發(fā)控制技術(shù)來(lái)確保多個(gè)客戶端之間不會(huì)同時(shí)修改敏感詞列表或緩存數(shù)據(jù),從而避免數(shù)據(jù)不一致的問(wèn)題。
六、總結(jié)
本文介紹了如何在SpringBoot中實(shí)現(xiàn)敏感詞過(guò)濾功能,主要特點(diǎn)包括:
- 使用DFA算法實(shí)現(xiàn)高效的敏感詞匹配
- 結(jié)合Redis實(shí)現(xiàn)敏感詞的持久化存儲(chǔ)
- 提供完整的REST API接口
- 支持敏感詞的動(dòng)態(tài)添加和更新
- 考慮了實(shí)際應(yīng)用場(chǎng)景和性能優(yōu)化
到此這篇關(guān)于SpringBoot 框架下高效敏感詞過(guò)濾功能的實(shí)現(xiàn)方案的文章就介紹到這了,更多相關(guān)SpringBoot高效敏感詞過(guò)濾功能內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot實(shí)現(xiàn)敏感詞過(guò)濾功能示例
- SpringBoot DFA實(shí)現(xiàn)敏感詞過(guò)濾功能
- springboot集成sensitive-word實(shí)現(xiàn)敏感詞過(guò)濾的兩種方案
- SpringBoot過(guò)濾敏感詞的兩種實(shí)現(xiàn)方式
- SpringBoot使用前綴樹(shù)實(shí)現(xiàn)敏感詞過(guò)濾示例
- SpringBoot使用SensitiveWord實(shí)現(xiàn)敏感詞過(guò)濾
- SpringBoot實(shí)現(xiàn)過(guò)濾敏感詞的示例代碼
- SpringBoot使用前綴樹(shù)過(guò)濾敏感詞的方法實(shí)例
相關(guān)文章
Springboot使用redis進(jìn)行api防刷限流過(guò)程詳解
這篇文章主要介紹了Springboot使用redis進(jìn)行api防刷限流過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12
Lombok插件有望被Intellij IDEA收編以改善兼容性問(wèn)題(推薦)
這篇文章主要介紹了Lombok插件有望被Intellij IDEA收編以改善兼容性問(wèn)題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-08-08
簡(jiǎn)單了解java集合框架LinkedList使用方法
這篇文章主要介紹了簡(jiǎn)單了解java集合框架LinkedList使用方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08
java顯示當(dāng)前運(yùn)行時(shí)的參數(shù)(java運(yùn)行參數(shù))
這篇文章主要介紹了java顯示當(dāng)前運(yùn)行時(shí)參數(shù)的示例(java運(yùn)行參數(shù)),需要的朋友可以參考下2014-04-04
SpringIOC?BeanDefinition的加載流程詳解
這篇文章主要為大家介紹了SpringIOC?BeanDefinition的加載流程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10
SpringCloud之微服務(wù)容錯(cuò)的實(shí)現(xiàn)
這篇文章主要介紹了SpringCloud之微服務(wù)容錯(cuò)的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05
spring mvc高級(jí)技術(shù)實(shí)例詳解
前面學(xué)習(xí)了簡(jiǎn)單的Spring Web知識(shí),接著學(xué)習(xí)更高階的Web技術(shù)。下面這篇文章主要給大家介紹了spring mvc高級(jí)技術(shù)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來(lái)一起看看吧2018-09-09

