最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot實(shí)現(xiàn)過濾敏感詞的示例代碼

 更新時(shí)間:2022年08月05日 10:55:19   作者:嘿_魚骨頭  
這篇文章主要為大家詳細(xì)介紹了如何利用SpringBoot實(shí)現(xiàn)過濾敏感詞功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以動(dòng)手嘗試一下

過濾敏感詞

1. 創(chuàng)建一個(gè)儲存要過濾的敏感詞的文本文件

首先創(chuàng)建一個(gè)文本文件儲存要過濾的敏感詞

在下面的工具類中我們會讀取這個(gè)文本文件,這里提前給出

@PostConstruct   // 這個(gè)注解表示當(dāng)容器實(shí)例化這個(gè)bean(服務(wù)啟動(dòng)的時(shí)候)之后在調(diào)用構(gòu)造器之后這個(gè)方法會自動(dòng)的調(diào)用
public void init(){
    try(
            // 讀取寫有“敏感詞”的文件,getClass表示從程序編譯之后的target/classes讀配置文件,讀之后是字節(jié)流
            // java7語法,在這里的句子最后會自動(dòng)執(zhí)行close語句
            InputStream is = this.getClass().getClassLoader().getResourceAsStream("sensitive-words.txt");
            // 字節(jié)流  ->   字符流  ->  緩沖流
            BufferedReader reader = new BufferedReader(new InputStreamReader(is));

    ) {
        String keyword;
        // 從文件中一行一行讀
        while ((keyword = reader.readLine()) != null){
            // 添加到前綴樹
            this.addKeyword(keyword);
        }
    } catch (IOException e) {
        logger.error("加載敏感詞文件失敗: " + e.getMessage());
    }
}

2. 開發(fā)過濾敏感詞的工具類

開發(fā)過濾敏感詞組件

為了方便以后復(fù)用,我們把過濾敏感詞寫成一個(gè)工具類SensitiveFilter。

@Component
public class SensitiveFilter {

    private static final Logger logger = LoggerFactory.getLogger(SensitiveFilter.class);

    // 當(dāng)檢測到敏感詞后我們要把敏感詞替換成什么符號
    private static final String REPLACEMENT = "***";

    // 根節(jié)點(diǎn)
    private TrieNode rootNode = new TrieNode();

    @PostConstruct   // 這個(gè)注解表示當(dāng)容器實(shí)例化這個(gè)bean(服務(wù)啟動(dòng)的時(shí)候)之后在調(diào)用構(gòu)造器之后這個(gè)方法會自動(dòng)的調(diào)用
    public void init(){
        try(
                // 讀取寫有“敏感詞”的文件,getClass表示從程序編譯之后的target/classes讀配置文件,讀之后是字節(jié)流
                // java7語法,在這里的句子最后會自動(dòng)執(zhí)行close語句
                InputStream is = this.getClass().getClassLoader().getResourceAsStream("sensitive-words.txt");
                // 字節(jié)流  ->   字符流  ->  緩沖流
                BufferedReader reader = new BufferedReader(new InputStreamReader(is));

        ) {
            String keyword;
            // 從文件中一行一行讀
            while ((keyword = reader.readLine()) != null){
                // 添加到前綴樹
                this.addKeyword(keyword);
            }
        } catch (IOException e) {
            logger.error("加載敏感詞文件失敗: " + e.getMessage());
        }
    }

    // 將一個(gè)敏感詞添加到前綴樹中
    private void addKeyword(String keyword){
        // 首先默認(rèn)指向根
        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為空,初始化子節(jié)點(diǎn);subNode不為空,直接用就可以了
                subNode = new TrieNode();
                tempNode.addSubNode(c, subNode);
            }
            // 指針指向子節(jié)點(diǎn),進(jìn)入下一輪循環(huán)
            tempNode = subNode;
        }
        // 最后要設(shè)置結(jié)束標(biāo)識
        tempNode.setKeywordEnd(true);
    }

    /**
     * 過濾敏感詞
     * @param text 待過濾的文本
     * @return  過濾后的文本
     */
    public String filter(String text){
        if(StringUtils.isBlank(text)){
            // 待過濾的文本為空,直接返回null
            return null;
        }
        // 指針1,指向樹
        TrieNode tempNode = rootNode;
        // 指針2,指向正在檢測的字符串段的首
        int begin = 0;
        // 指針3,指向正在檢測的字符串段的尾
        int position = 0;
        // 儲存過濾后的文本
        StringBuilder sb = new StringBuilder();
        while (begin < text.length()){
            char c = text.charAt(position);

            // 跳過符號,比如 “開票”是敏感詞 #開#票# 這個(gè)字符串中間的 '#' 應(yīng)該跳過
            if(isSymbol(c)){
                // 是特殊字符
                // 若指針1處于根節(jié)點(diǎn),將此符號計(jì)入結(jié)果,指針2、3向右走一步
                if(tempNode == rootNode){
                    sb.append(c);
                    begin++;
                }
                // 無論符號在開頭或中間,指針3都向下走一步
                position++;
                // 符號處理完,進(jìn)入下一輪循環(huán)
                continue;
            }
            // 執(zhí)行到這里說明字符不是特殊符號
            // 檢查下級節(jié)點(diǎn)
            tempNode = tempNode.getSubNode(c);
            if(tempNode == null){
                // 以begin開頭的字符串不是敏感詞
                sb.append(text.charAt(begin));
                // 進(jìn)入下一個(gè)位置
                position = ++begin;
                // 重新指向根節(jié)點(diǎn)
                tempNode = rootNode;
            } else if(tempNode.isKeywordEnd()){
                // 發(fā)現(xiàn)敏感詞,將begin~position字符串替換掉,存 REPLACEMENT (里面是***)
                sb.append(REPLACEMENT);
                // 進(jìn)入下一個(gè)位置
                begin = ++position;
                // 重新指向根節(jié)點(diǎn)
                tempNode = rootNode;
            } else {
                // 檢查下一個(gè)字符
                position++;
            }
        }
        return sb.toString();
    }

    // 判斷是否為特殊符號,是則返回true,不是則返回false
    private boolean isSymbol(Character c){
        // CharUtils.isAsciiAlphanumeric(c)方法:a、b、1、2···返回true,特殊字符返回false
        // 0x2E80  ~  0x9FFF 是東亞的文字范圍,東亞文字范圍我們不認(rèn)為是符號
        return  !CharUtils.isAsciiAlphanumeric(c) && (c < 0x2E80 || c > 0x9FFF);
    }

    // 前綴樹
    private class TrieNode{

        // 關(guān)鍵詞結(jié)束標(biāo)識
        private boolean isKeywordEnd = false;

        // 當(dāng)前節(jié)點(diǎn)的子節(jié)點(diǎn)(key是下級字符、value是下級節(jié)點(diǎn))
        private Map<Character, TrieNode> subNodes = new HashMap<>();

        public boolean isKeywordEnd() {
            return isKeywordEnd;
        }

        public void setKeywordEnd(boolean keywordEnd) {
            isKeywordEnd = keywordEnd;
        }

        // 添加子節(jié)點(diǎn)
        public void addSubNode(Character c, TrieNode node){
            subNodes.put(c, node);
        }

        // 獲取子節(jié)點(diǎn)
        public TrieNode getSubNode(Character c){
            return subNodes.get(c);
        }
    }
}

上面就是過濾敏感詞工具類的全部代碼,接下來我們來解釋一下開發(fā)步驟

開發(fā)過濾敏感詞組件分為三步:

1.定義前綴樹(Tree)

我們將定義前綴樹寫為SensitiveFilter工具類的內(nèi)部類

// 前綴樹
private class TrieNode{

    // 關(guān)鍵詞結(jié)束標(biāo)識
    private boolean isKeywordEnd = false;

    // 當(dāng)前節(jié)點(diǎn)的子節(jié)點(diǎn)(key是下級字符、value是下級節(jié)點(diǎn))
    private Map<Character, TrieNode> subNodes = new HashMap<>();

    public boolean isKeywordEnd() {
        return isKeywordEnd;
    }

    public void setKeywordEnd(boolean keywordEnd) {
        isKeywordEnd = keywordEnd;
    }

    // 添加子節(jié)點(diǎn)
    public void addSubNode(Character c, TrieNode node){
        subNodes.put(c, node);
    }

    // 獲取子節(jié)點(diǎn)
    public TrieNode getSubNode(Character c){
        return subNodes.get(c);
    }
}

2.根據(jù)敏感詞,初始化前綴樹

將敏感詞添加到前綴樹中

// 將一個(gè)敏感詞添加到前綴樹中
private void addKeyword(String keyword){
    // 首先默認(rèn)指向根
    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為空,初始化子節(jié)點(diǎn);subNode不為空,直接用就可以了
            subNode = new TrieNode();
            tempNode.addSubNode(c, subNode);
        }
        // 指針指向子節(jié)點(diǎn),進(jìn)入下一輪循環(huán)
        tempNode = subNode;
    }
    // 最后要設(shè)置結(jié)束標(biāo)識
    tempNode.setKeywordEnd(true);
}

3.編寫過濾敏感詞的方法

如何過濾文本中的敏感詞:

特殊符號怎么處理:

敏感詞前綴樹初始化完畢之后,過濾文本中的敏感詞的算法應(yīng)該如下:

定義三個(gè)指針:

  • 指針1指向Tree樹
  • 指針2指向待過濾字符串段
  • 指針3指向待過濾字符串段
/**
 * 過濾敏感詞
 * @param text 待過濾的文本
 * @return  過濾后的文本
 */
public String filter(String text){
    if(StringUtils.isBlank(text)){
        // 待過濾的文本為空,直接返回null
        return null;
    }
    // 指針1,指向樹
    TrieNode tempNode = rootNode;
    // 指針2,指向正在檢測的字符串段的首
    int begin = 0;
    // 指針3,指向正在檢測的字符串段的尾
    int position = 0;
    // 儲存過濾后的文本
    StringBuilder sb = new StringBuilder();
    while (begin < text.length()){
        char c = text.charAt(position);

        // 跳過符號,比如 “開票”是敏感詞 #開#票# 這個(gè)字符串中間的 '#' 應(yīng)該跳過
        if(isSymbol(c)){
            // 是特殊字符
            // 若指針1處于根節(jié)點(diǎn),將此符號計(jì)入結(jié)果,指針2、3向右走一步
            if(tempNode == rootNode){
                sb.append(c);
                begin++;
            }
            // 無論符號在開頭或中間,指針3都向下走一步
            position++;
            // 符號處理完,進(jìn)入下一輪循環(huán)
            continue;
        }
        // 執(zhí)行到這里說明字符不是特殊符號
        // 檢查下級節(jié)點(diǎn)
        tempNode = tempNode.getSubNode(c);
        if(tempNode == null){
            // 以begin開頭的字符串不是敏感詞
            sb.append(text.charAt(begin));
            // 進(jìn)入下一個(gè)位置
            position = ++begin;
            // 重新指向根節(jié)點(diǎn)
            tempNode = rootNode;
        } else if(tempNode.isKeywordEnd()){
            // 發(fā)現(xiàn)敏感詞,將begin~position字符串替換掉,存 REPLACEMENT (里面是***)
            sb.append(REPLACEMENT);
            // 進(jìn)入下一個(gè)位置
            begin = ++position;
            // 重新指向根節(jié)點(diǎn)
            tempNode = rootNode;
        } else {
            // 檢查下一個(gè)字符
            position++;
        }
    }
    return sb.toString();
}

// 判斷是否為特殊符號,是則返回true,不是則返回false
private boolean isSymbol(Character c){
    // CharUtils.isAsciiAlphanumeric(c)方法:a、b、1、2···返回true,特殊字符返回false
    // 0x2E80  ~  0x9FFF 是東亞的文字范圍,東亞文字范圍我們不認(rèn)為是符號
    return  !CharUtils.isAsciiAlphanumeric(c) && (c < 0x2E80 || c > 0x9FFF);
}

最后:建議在測試類中測試一下

經(jīng)測試,過濾敏感詞的工具類開發(fā)完成,這個(gè)工具會在接下來的發(fā)布帖子的功能中用到。

以上就是SpringBoot實(shí)現(xiàn)過濾敏感詞的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot過濾敏感詞的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 使用Java連接WMI獲取系統(tǒng)信息的方法

    使用Java連接WMI獲取系統(tǒng)信息的方法

    在 Windows 系統(tǒng)上,WMI是一套管理數(shù)據(jù)和操作系統(tǒng)組件的基礎(chǔ)設(shè)施,能讓應(yīng)用程序查詢系統(tǒng)信息、監(jiān)控硬件狀態(tài)以及管理系統(tǒng)配置,本項(xiàng)目旨在講解如何通過 Java 連接 WMI 獲取系統(tǒng)信息,需要的朋友可以參考下
    2025-03-03
  • java實(shí)現(xiàn)靜默加載Class示例代碼

    java實(shí)現(xiàn)靜默加載Class示例代碼

    這篇文章主要給大家介紹了關(guān)于java實(shí)現(xiàn)靜默加載Class的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-10-10
  • java實(shí)現(xiàn)遞歸菜單樹

    java實(shí)現(xiàn)遞歸菜單樹

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)遞歸菜單樹,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-08-08
  • SpringBoot數(shù)據(jù)壓縮實(shí)踐方案

    SpringBoot數(shù)據(jù)壓縮實(shí)踐方案

    文章探討了Redis中處理大key的壓縮方案,包括拆分JSON結(jié)構(gòu)、使用GZIP/Deflater壓縮、優(yōu)化體積(如移除空格、縮短鍵名)、流式處理及分段存儲,旨在降低內(nèi)存負(fù)擔(dān)并提升性能,感興趣的朋友跟隨小編一起看看吧
    2025-10-10
  • SpringBoot整合spring-retry實(shí)現(xiàn)接口請求重試機(jī)制及注意事項(xiàng)

    SpringBoot整合spring-retry實(shí)現(xiàn)接口請求重試機(jī)制及注意事項(xiàng)

    今天通過本文給大家介紹我們應(yīng)該如何使用SpringBoot來整合spring-retry組件實(shí)現(xiàn)重試機(jī)制及注意事項(xiàng),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧
    2021-08-08
  • Java中Stream流的使用示例詳解

    Java中Stream流的使用示例詳解

    Stream流提供了一種高效且易于使用的方式來對數(shù)據(jù)進(jìn)行過濾、映射、排序、聚合等操作,使代碼更加簡潔和可讀,接下來通過本文給大家介紹Java中Stream流的使用,感興趣的朋友跟隨小編一起看看吧
    2025-08-08
  • 詳解Java中Quartz的簡單使用

    詳解Java中Quartz的簡單使用

    Quartz?是一個(gè)開源的作業(yè)調(diào)度框架,它完全由?Java?寫成,并設(shè)計(jì)用于?J2SE?和?J2EE?應(yīng)用中。這篇文章主要通過示例和大家講講Quartz的簡單使用,需要的可以參考一下
    2023-04-04
  • Java中super與this關(guān)鍵字的用途及區(qū)別詳解

    Java中super與this關(guān)鍵字的用途及區(qū)別詳解

    這篇文章主要介紹了Java中super與this關(guān)鍵字的用途及區(qū)別的相關(guān)資料,super和this是Java中用于引用父類和當(dāng)前對象的特殊關(guān)鍵字,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-04-04
  • SpringBoot實(shí)現(xiàn)全局異常處理方法總結(jié)

    SpringBoot實(shí)現(xiàn)全局異常處理方法總結(jié)

    在項(xiàng)目開發(fā)中出現(xiàn)異常時(shí)很平常不過的事情,我們處理異常也有很多種方式。本文將詳細(xì)為大家講解SpringBoot實(shí)現(xiàn)全局異常處理幾種方法,感興趣的可以學(xué)習(xí)一下
    2022-03-03
  • 高內(nèi)聚低耦合原則_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    高內(nèi)聚低耦合原則_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    耦合度就是某模塊(類)與其它模塊(類)之間的關(guān)聯(lián)、感知和依賴的程度,是衡量代碼獨(dú)立性的一個(gè)指標(biāo),也是軟件工程設(shè)計(jì)及編碼質(zhì)量評價(jià)的一個(gè)標(biāo)準(zhǔn)
    2017-08-08

最新評論

上杭县| 通榆县| 华蓥市| 连城县| 包头市| 江津市| 靖西县| 项城市| 萨嘎县| 麻阳| 都匀市| 四川省| 崇阳县| 三明市| 来凤县| 长治县| 伊宁县| 双江| 滨州市| 呼伦贝尔市| 寿光市| 时尚| 冀州市| 安丘市| 安庆市| 灵丘县| 阳信县| 怀来县| 锡林郭勒盟| 天台县| 新巴尔虎右旗| 泾川县| 庆城县| 大连市| 新竹县| 平山县| 丽水市| 合作市| 五河县| 甘孜| 上犹县|