1.自定义注解
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = {SensitiveWordValidatorUtil.class}) 验证器
public @interface SensitiveWord {
String message() default "不能有敏感词";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
String filed() default "";
}
2.容器启动加载数据
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
/**
* 初始化敏感词库
*/
@Component
public class SensitiveWordRunner implements ApplicationRunner {
@Autowired
private SensitiveWordService sensitiveWordService;
@Override
public void run(ApplicationArguments args) {
SensitiveWordValidatorUtil.sensitiveWordMap = sensitiveWordService.getSensitiveWordMap();
log.info("================== 结束:初始化敏感词到内存 ==================");
}
}
3. ConstraintValidator自定义校验注解
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* 敏感词过滤工具类
*/
@Slf4j
public class SensitiveWordValidatorUtil implements ConstraintValidator<SensitiveWord, String> {
private String message;
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if(StringUtils.isBlank(value)) {
return true;
}
Set<String> sensitiveWordSet = SensitiveWordValidatorUtil.getSensitiveWord(value, 2);
if(CollectionUtils.isNotEmpty(sensitiveWordSet)){
String sensitiveWord = sensitiveWordSet.iterator().next();
log.info("================== 敏感词检查:检查内容是{},匹配的敏感词是{} ==================", value, sensitiveWord);
//禁止默认消息返回
context.disableDefaultConstraintViolation();
//自定义返回消息
context.buildConstraintViolationWithTemplate(String.format(this.message, sensitiveWord)).addConstraintViolation();
return false;
}
return true;
}
@Override
public void initialize(SensitiveWord sensitiveWord) {
this.message = sensitiveWord.message();
}
/**
* 敏感词库
*/
public static Map sensitiveWordMap = null;
/**
* 只过滤最小敏感词
*/
public static int minMatchTYpe = 1;
/**
* 过滤所有敏感词
*/
public static int maxMatchType = 2;
/**
* 敏感词库敏感词数量
* @return
*/
public static int getWordSize() {
if (SensitiveWordValidatorUtil.sensitiveWordMap == null) {
return 0;
}
return SensitiveWordValidatorUtil.sensitiveWordMap.size();
}
/**
* 是否包含敏感词
* @param txt
* @param matchType
* @return
*/
public static boolean isContaintSensitiveWord(String txt, int matchType) {
boolean flag = false;
for (int i = 0; i < txt.length(); i++) {
int matchFlag = checkSensitiveWord(txt, i,matchType);
if (matchFlag > 0) {
flag = true;
}
}
return flag;
}
/**
* 获取敏感词内容
* @param txt
* @param matchType
* @return 敏感词内容
*/
public static Set<String> getSensitiveWord(String txt, int matchType) {
Set<String> sensitiveWordList = new HashSet<String>();
for (int i = 0; i < txt.length(); i++) {
int length = checkSensitiveWord(txt,i, matchType);
if (length > 0) {
// 将检测出的敏感词保存到集合中
sensitiveWordList.add(txt.substring(i, i + length));
i = i + length - 1;
}
}
return sensitiveWordList;
}
/**
* 替换敏感词
* @param txt
* @param matchType
* @param replaceChar
* @return
*/
public static String replaceSensitiveWord(String txt, int matchType, String replaceChar) {
String resultTxt = txt;
Set<String> set = getSensitiveWord(txt, matchType);
Iterator<String> iterator = set.iterator();
String word = null;
String replaceString = null;
while (iterator.hasNext()) {
word = iterator.next();
replaceString = getReplaceChars(replaceChar, word.length());
resultTxt = resultTxt.replaceAll(word, replaceString);
}
return resultTxt;
}
/**
* 替换敏感词内容
* @param replaceChar
* @param length
* @return
*/
private static String getReplaceChars(String replaceChar, int length) {
String resultReplace = replaceChar;
for (int i = 1; i < length; i++) {
resultReplace += replaceChar;
}
return resultReplace;
}
/**
* 检查敏感词数量
* @param txt
* @param matchType
* @return
*/
public static int checkSensitiveWord(String txt, int beginIndex, int matchType) {
boolean flag = false;
// 记录敏感词数量
int matchFlag = 0;
char word = 0;
Map nowMap = SensitiveWordValidatorUtil.sensitiveWordMap;
for (int i = beginIndex; i < txt.length(); i++) {
word = txt.charAt(i);
// 判断该字是否存在于敏感词库中
nowMap = (Map) nowMap.get(word);
if (nowMap != null) {
matchFlag++;
// 判断是否是敏感词的结尾字,如果是结尾字则判断是否继续检测
if ("1".equals(nowMap.get("isEnd"))) {
flag = true;
// 判断过滤类型,如果是小过滤则跳出循环,否则继续循环
if (SensitiveWordValidatorUtil.minMatchTYpe == matchType) {
break;
}
}
} else {
break;
}
}
if (!flag) {
matchFlag = 0;
}
return matchFlag;
}
}