敏感词更新策略问题调整,敏感词迁移至公共工具类
This commit is contained in:
		
							parent
							
								
									c276b1595c
								
							
						
					
					
						commit
						f8408030a9
					
				| @ -1,12 +1,6 @@ | |||||||
| package cn.lili.modules.system.utils; | package cn.lili.modules.system.utils; | ||||||
| 
 | 
 | ||||||
| import cn.lili.modules.system.entity.dos.SensitiveWords; |  | ||||||
| import cn.lili.modules.system.service.SensitiveWordsService; |  | ||||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||||
| import org.springframework.beans.factory.annotation.Autowired; |  | ||||||
| import org.springframework.boot.ApplicationArguments; |  | ||||||
| import org.springframework.boot.ApplicationRunner; |  | ||||||
| import org.springframework.stereotype.Component; |  | ||||||
| 
 | 
 | ||||||
| import java.io.Serializable; | import java.io.Serializable; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| @ -21,9 +15,12 @@ import java.util.NavigableSet; | |||||||
|  * 2020-02-25 14:10:16 |  * 2020-02-25 14:10:16 | ||||||
|  */ |  */ | ||||||
| @Slf4j | @Slf4j | ||||||
| @Component | public class SensitiveWordsFilter implements Serializable { | ||||||
| public class SensitiveWordsFilter implements Serializable, ApplicationRunner { |  | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * 字符* | ||||||
|  |      */ | ||||||
|  |     public final static char WILDCARD_STAR = '*'; | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * 为2的n次方,考虑到敏感词大概在10k左右, |      * 为2的n次方,考虑到敏感词大概在10k左右, | ||||||
| @ -39,96 +36,20 @@ public class SensitiveWordsFilter implements Serializable, ApplicationRunner { | |||||||
|      */ |      */ | ||||||
|     protected static SensitiveWordsNode[] nodes; |     protected static SensitiveWordsNode[] nodes; | ||||||
| 
 | 
 | ||||||
|     @Autowired |  | ||||||
|     private SensitiveWordsService sensitiveWordsService; |  | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * 增加一个敏感词,如果词的长度(trim后)小于2,则丢弃<br/> |      * 过滤铭感次 | ||||||
|      * 此方法(构建)并不是主要的性能优化点。 |  | ||||||
|      * |      * | ||||||
|      * @param word 敏感词 |      * @param sentence 过滤赐予 | ||||||
|      * @return 操作结果 |  | ||||||
|      */ |  | ||||||
|     public static boolean put(String word) { |  | ||||||
| 
 |  | ||||||
|         //长度小于2的不加入 |  | ||||||
|         if (word == null || word.trim().length() < 2) { |  | ||||||
|             return false; |  | ||||||
|         } |  | ||||||
|         //两个字符的不考虑 |  | ||||||
|         if (word.length() == 2 && word.matches("\\w\\w")) { |  | ||||||
|             return false; |  | ||||||
|         } |  | ||||||
|         StringPointer sp = new StringPointer(word.trim()); |  | ||||||
|         //计算头两个字符的hash |  | ||||||
|         int hash = sp.nextTwoCharHash(0); |  | ||||||
|         //计算头两个字符的mix表示(mix相同,两个字符相同) |  | ||||||
|         int mix = sp.nextTwoCharMix(0); |  | ||||||
|         //转为在hash桶中的位置 |  | ||||||
|         int index = hash & (nodes.length - 1); |  | ||||||
| 
 |  | ||||||
|         //从桶里拿第一个节点 |  | ||||||
|         SensitiveWordsNode node = nodes[index]; |  | ||||||
|         if (node == null) { |  | ||||||
|             //如果没有节点,则放进去一个 |  | ||||||
|             node = new SensitiveWordsNode(mix); |  | ||||||
|             //并添加词 |  | ||||||
|             node.words.add(sp); |  | ||||||
|             //放入桶里 |  | ||||||
|             nodes[index] = node; |  | ||||||
|         } else { |  | ||||||
|             //如果已经有节点(1个或多个),找到正确的节点 |  | ||||||
|             for (; node != null; node = node.next) { |  | ||||||
|                 //匹配节点 |  | ||||||
|                 if (node.headTwoCharMix == mix) { |  | ||||||
|                     node.words.add(sp); |  | ||||||
|                     return true; |  | ||||||
|                 } |  | ||||||
|                 //如果匹配到最后仍然不成功,则追加一个节点 |  | ||||||
|                 if (node.next == null) { |  | ||||||
|                     new SensitiveWordsNode(mix, node).words.add(sp); |  | ||||||
|                     return true; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         return true; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 移除敏感词 |  | ||||||
|      * |  | ||||||
|      * @param word |  | ||||||
|      * @return |      * @return | ||||||
|      */ |      */ | ||||||
|     public static void remove(String word) { |     public static String filter(String sentence) { | ||||||
| 
 |         return filter(sentence, WILDCARD_STAR); | ||||||
|         StringPointer sp = new StringPointer(word.trim()); |  | ||||||
|         //计算头两个字符的hash |  | ||||||
|         int hash = sp.nextTwoCharHash(0); |  | ||||||
|         //计算头两个字符的mix表示(mix相同,两个字符相同) |  | ||||||
|         int mix = sp.nextTwoCharMix(0); |  | ||||||
|         //转为在hash桶中的位置 |  | ||||||
|         int index = hash & (nodes.length - 1); |  | ||||||
|         SensitiveWordsNode node = nodes[index]; |  | ||||||
| 
 |  | ||||||
|         for (; node != null; node = node.next) { |  | ||||||
|             //匹配节点 |  | ||||||
|             if (node.headTwoCharMix == mix) { |  | ||||||
|                 node.words.remove(sp); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * 对句子进行敏感词过滤<br/> |      * 对句子进行敏感词过滤<br/> | ||||||
|      * 如果无敏感词返回输入的sentence对象,即可以用下面的方式判断是否有敏感词:<br/><code> |      * 如果无敏感词返回输入的sentence对象,即可以用下面的方式判断是否有敏感词:<br/> | ||||||
|      * String result = filter.filter(sentence, CharacterConstant.WILDCARD_STAR);<br/> |  | ||||||
|      * if(result != sentence){<br/> |  | ||||||
|      *   //有敏感词<br/> |  | ||||||
|      * } |  | ||||||
|      * </code> |  | ||||||
|      * |      * | ||||||
|      * @param sentence 句子 |      * @param sentence 句子 | ||||||
|      * @param replace  敏感词的替换字符 |      * @param replace  敏感词的替换字符 | ||||||
| @ -224,25 +145,95 @@ public class SensitiveWordsFilter implements Serializable, ApplicationRunner { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|     /** |     /** | ||||||
|      * 初始化敏感词 |      * 初始化敏感词 | ||||||
|      * |  | ||||||
|      * @param args |  | ||||||
|      * @throws Exception |  | ||||||
|      */ |      */ | ||||||
|     @Override |     public static void init(List<String> words) { | ||||||
|     public void run(ApplicationArguments args) { |         nodes = new SensitiveWordsNode[DEFAULT_INITIAL_CAPACITY]; | ||||||
|         try { |         for (String word : words) { | ||||||
|             nodes = new SensitiveWordsNode[DEFAULT_INITIAL_CAPACITY]; |             put(word); | ||||||
|             //加入平台添加的敏感词 |  | ||||||
|             List<SensitiveWords> list = sensitiveWordsService.list(); |  | ||||||
|             if (list != null && list.size() > 0) { |  | ||||||
|                 for (SensitiveWords sensitiveWords : list) { |  | ||||||
|                     put(sensitiveWords.getSensitiveWord()); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } catch (Exception e) { |  | ||||||
|             log.error("初始化敏感词错误", e); |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 增加一个敏感词,如果词的长度(trim后)小于2,则丢弃<br/> | ||||||
|  |      * 此方法(构建)并不是主要的性能优化点。 | ||||||
|  |      * | ||||||
|  |      * @param word 敏感词 | ||||||
|  |      * @return 操作结果 | ||||||
|  |      */ | ||||||
|  |     public static boolean put(String word) { | ||||||
|  | 
 | ||||||
|  |         //长度小于2的不加入 | ||||||
|  |         if (word == null || word.trim().length() < 2) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         //两个字符的不考虑 | ||||||
|  |         if (word.length() == 2 && word.matches("\\w\\w")) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         StringPointer sp = new StringPointer(word.trim()); | ||||||
|  |         //计算头两个字符的hash | ||||||
|  |         int hash = sp.nextTwoCharHash(0); | ||||||
|  |         //计算头两个字符的mix表示(mix相同,两个字符相同) | ||||||
|  |         int mix = sp.nextTwoCharMix(0); | ||||||
|  |         //转为在hash桶中的位置 | ||||||
|  |         int index = hash & (nodes.length - 1); | ||||||
|  | 
 | ||||||
|  |         //从桶里拿第一个节点 | ||||||
|  |         SensitiveWordsNode node = nodes[index]; | ||||||
|  |         if (node == null) { | ||||||
|  |             //如果没有节点,则放进去一个 | ||||||
|  |             node = new SensitiveWordsNode(mix); | ||||||
|  |             //并添加词 | ||||||
|  |             node.words.add(sp); | ||||||
|  |             //放入桶里 | ||||||
|  |             nodes[index] = node; | ||||||
|  |         } else { | ||||||
|  |             //如果已经有节点(1个或多个),找到正确的节点 | ||||||
|  |             for (; node != null; node = node.next) { | ||||||
|  |                 //匹配节点 | ||||||
|  |                 if (node.headTwoCharMix == mix) { | ||||||
|  |                     node.words.add(sp); | ||||||
|  |                     return true; | ||||||
|  |                 } | ||||||
|  |                 //如果匹配到最后仍然不成功,则追加一个节点 | ||||||
|  |                 if (node.next == null) { | ||||||
|  |                     new SensitiveWordsNode(mix, node).words.add(sp); | ||||||
|  |                     return true; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 移除敏感词 | ||||||
|  |      * | ||||||
|  |      * @param word | ||||||
|  |      * @return | ||||||
|  |      */ | ||||||
|  |     public static void remove(String word) { | ||||||
|  | 
 | ||||||
|  |         StringPointer sp = new StringPointer(word.trim()); | ||||||
|  |         //计算头两个字符的hash | ||||||
|  |         int hash = sp.nextTwoCharHash(0); | ||||||
|  |         //计算头两个字符的mix表示(mix相同,两个字符相同) | ||||||
|  |         int mix = sp.nextTwoCharMix(0); | ||||||
|  |         //转为在hash桶中的位置 | ||||||
|  |         int index = hash & (nodes.length - 1); | ||||||
|  |         SensitiveWordsNode node = nodes[index]; | ||||||
|  | 
 | ||||||
|  |         for (; node != null; node = node.next) { | ||||||
|  |             //匹配节点 | ||||||
|  |             if (node.headTwoCharMix == mix) { | ||||||
|  |                 node.words.remove(sp); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| } | } | ||||||
| @ -0,0 +1,40 @@ | |||||||
|  | package cn.lili.cache.impl; | ||||||
|  | 
 | ||||||
|  | import cn.lili.cache.Cache; | ||||||
|  | import cn.lili.cache.CachePrefix; | ||||||
|  | import cn.lili.common.sensitive.SensitiveWordsFilter; | ||||||
|  | import org.springframework.beans.factory.annotation.Autowired; | ||||||
|  | import org.springframework.boot.ApplicationArguments; | ||||||
|  | import org.springframework.boot.ApplicationRunner; | ||||||
|  | import org.springframework.stereotype.Component; | ||||||
|  | 
 | ||||||
|  | import java.util.List; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * 初始化敏感词 | ||||||
|  |  * | ||||||
|  |  * @author Chopper | ||||||
|  |  * @version v1.0 | ||||||
|  |  * 2021-11-23 12:08 | ||||||
|  |  */ | ||||||
|  | @Component | ||||||
|  | public class SensitiveInit implements ApplicationRunner { | ||||||
|  | 
 | ||||||
|  |     @Autowired | ||||||
|  |     private Cache<List<String>> cache; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 程序启动时,获取最新的需要过滤的敏感词 | ||||||
|  |      * | ||||||
|  |      * @param args | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public void run(ApplicationArguments args) { | ||||||
|  |         List<String> sensitives = cache.get(CachePrefix.SENSITIVE.getPrefix()); | ||||||
|  |         if (sensitives == null || sensitives.isEmpty()) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         SensitiveWordsFilter.init(sensitives); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,11 @@ | |||||||
|  | package cn.lili.common.sensitive.quartz; | ||||||
|  | /** | ||||||
|  |  *   | ||||||
|  |  * QuartzConfig  | ||||||
|  |  * @author Chopper | ||||||
|  |  * @version v1.0 | ||||||
|  |  * 2021-11-23 16:30 | ||||||
|  |  * | ||||||
|  |  */  | ||||||
|  | public class QuartzConfig { | ||||||
|  | } | ||||||
| @ -0,0 +1,11 @@ | |||||||
|  | package cn.lili.common.sensitive.quartz; | ||||||
|  | /** | ||||||
|  |  *   | ||||||
|  |  * SensitiveQuartz  | ||||||
|  |  * @author Chopper | ||||||
|  |  * @version v1.0 | ||||||
|  |  * 2021-11-23 16:31 | ||||||
|  |  * | ||||||
|  |  */  | ||||||
|  | public class SensitiveQuartz { | ||||||
|  | } | ||||||
| @ -1,20 +0,0 @@ | |||||||
| package cn.lili.modules.system.utils; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * |  | ||||||
|  * 字符常量 |  | ||||||
|  * @author Bulbasaur |  | ||||||
|  * @version v1.0 |  | ||||||
|  * @since v1.0 |  | ||||||
|  * 2020-02-25 14:10:16 |  | ||||||
|  */ |  | ||||||
| public class CharacterConstant { |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 字符* |  | ||||||
|      */ |  | ||||||
|     public final static char WILDCARD_STAR = '*'; |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,6 +0,0 @@ | |||||||
| 共产党 |  | ||||||
| 习近平 |  | ||||||
| 毛泽东 |  | ||||||
| 胡锦涛 |  | ||||||
| 邓小平 |  | ||||||
| 强奸 |  | ||||||
| @ -1,6 +0,0 @@ | |||||||
| 共产党 |  | ||||||
| 习近平 |  | ||||||
| 毛泽东 |  | ||||||
| 胡锦涛 |  | ||||||
| 邓小平 |  | ||||||
| 强奸 |  | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Chopper
						Chopper