Skip to content

Commit 82f1835

Browse files
authored
feat: 添加敏感词模块 (#11)
1 parent efb0eea commit 82f1835

File tree

13 files changed

+420
-0
lines changed

13 files changed

+420
-0
lines changed

continew-starter-dependencies/pom.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,13 @@
593593
<version>${revision}</version>
594594
</dependency>
595595

596+
<!-- 敏感词模块 -->
597+
<dependency>
598+
<groupId>top.continew</groupId>
599+
<artifactId>continew-starter-sensitive-words</artifactId>
600+
<version>${revision}</version>
601+
</dependency>
602+
596603
</dependencies>
597604
</dependencyManagement>
598605

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
<parent>
7+
<groupId>top.continew</groupId>
8+
<artifactId>continew-starter</artifactId>
9+
<version>${revision}</version>
10+
</parent>
11+
12+
<artifactId>continew-starter-sensitive-words</artifactId>
13+
<description>Continew starter sensitive words 模块</description>
14+
15+
<dependencies>
16+
<!-- Spring Boot Starter(自动配置相关依赖) -->
17+
<dependency>
18+
<groupId>org.springframework.boot</groupId>
19+
<artifactId>spring-boot-starter</artifactId>
20+
</dependency>
21+
<dependency>
22+
<groupId>org.springframework.boot</groupId>
23+
<artifactId>spring-boot-configuration-processor</artifactId>
24+
</dependency>
25+
26+
<!-- Hutool(工具类库) -->
27+
<dependency>
28+
<groupId>cn.hutool</groupId>
29+
<artifactId>hutool-dfa</artifactId>
30+
</dependency>
31+
32+
<dependency>
33+
<groupId>org.springframework.boot</groupId>
34+
<artifactId>spring-boot-starter-validation</artifactId>
35+
</dependency>
36+
37+
<dependency>
38+
<groupId>org.projectlombok</groupId>
39+
<artifactId>lombok</artifactId>
40+
</dependency>
41+
</dependencies>
42+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
3+
* <p>
4+
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* <p>
8+
* http://www.gnu.org/licenses/lgpl.html
9+
* <p>
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package top.continew.starter.sensitive.words.autoconfigure;
18+
19+
import jakarta.annotation.PostConstruct;
20+
import org.slf4j.Logger;
21+
import org.slf4j.LoggerFactory;
22+
import org.springframework.boot.autoconfigure.AutoConfiguration;
23+
24+
/**
25+
* JSR 303 校验器自动配置
26+
*
27+
* @author Charles7c
28+
* @since 2.3.0
29+
*/
30+
@AutoConfiguration
31+
public class SensitiveWordsAutoConfiguration {
32+
33+
private static final Logger log = LoggerFactory.getLogger(SensitiveWordsAutoConfiguration.class);
34+
35+
@PostConstruct
36+
public void postConstruct() {
37+
log.debug("[ContiNew Starter] - Auto Configuration 'sensitive words service' completed initialization.");
38+
}
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
3+
* <p>
4+
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* <p>
8+
* http://www.gnu.org/licenses/lgpl.html
9+
* <p>
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package top.continew.starter.sensitive.words.autoconfigure;
18+
19+
import lombok.Data;
20+
import org.springframework.boot.context.properties.ConfigurationProperties;
21+
import org.springframework.stereotype.Component;
22+
23+
import java.util.List;
24+
25+
@Data
26+
@Component
27+
@ConfigurationProperties(prefix = "continew.sensitive-words")
28+
public class SensitiveWordsProperties {
29+
// 敏感词注入类型
30+
private String type;
31+
private List<String> values;
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
3+
* <p>
4+
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* <p>
8+
* http://www.gnu.org/licenses/lgpl.html
9+
* <p>
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package top.continew.starter.sensitive.words.service;
18+
19+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
20+
import org.springframework.stereotype.Component;
21+
import top.continew.starter.sensitive.words.autoconfigure.SensitiveWordsProperties;
22+
23+
import java.util.List;
24+
25+
/**
26+
* 默认敏感词配置
27+
*/
28+
@Component
29+
@ConditionalOnProperty(prefix = "continew.sensitive-words", name = "type", havingValue = "default", matchIfMissing = true)
30+
public class DefaultSensitiveWordsConfig implements SensitiveWordsConfig {
31+
32+
private final SensitiveWordsProperties properties;
33+
34+
public DefaultSensitiveWordsConfig(SensitiveWordsProperties properties) {
35+
this.properties = properties;
36+
}
37+
38+
@Override
39+
public List<String> getWords() {
40+
if (properties.getValues() != null) {
41+
return properties.getValues();
42+
}
43+
return List.of();
44+
}
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
3+
* <p>
4+
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* <p>
8+
* http://www.gnu.org/licenses/lgpl.html
9+
* <p>
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package top.continew.starter.sensitive.words.service;
18+
19+
import cn.hutool.dfa.WordTree;
20+
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
21+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
22+
import org.springframework.stereotype.Component;
23+
24+
import java.util.List;
25+
26+
/**
27+
* 默认敏感词服务
28+
*/
29+
@Component
30+
@ConditionalOnBean(SensitiveWordsConfig.class)
31+
@ConditionalOnMissingBean(SensitiveWordsService.class)
32+
public class DefaultSensitiveWordsService implements SensitiveWordsService {
33+
34+
private final SensitiveWordsConfig sensitiveWordsConfig;
35+
36+
private WordTree tree = new WordTree();
37+
38+
public DefaultSensitiveWordsService(SensitiveWordsConfig sensitiveWordsConfig) {
39+
this.sensitiveWordsConfig = sensitiveWordsConfig;
40+
if (sensitiveWordsConfig != null && sensitiveWordsConfig.getWords() != null) {
41+
tree.addWords(sensitiveWordsConfig.getWords());
42+
}
43+
}
44+
45+
@Override
46+
public List<String> check(String content) {
47+
return tree.matchAll(content, -1, false, true);
48+
}
49+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
3+
* <p>
4+
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* <p>
8+
* http://www.gnu.org/licenses/lgpl.html
9+
* <p>
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package top.continew.starter.sensitive.words.service;
18+
19+
import java.util.List;
20+
21+
/**
22+
* 敏感词配置
23+
*/
24+
public interface SensitiveWordsConfig {
25+
26+
List<String> getWords();
27+
28+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
3+
* <p>
4+
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* <p>
8+
* http://www.gnu.org/licenses/lgpl.html
9+
* <p>
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package top.continew.starter.sensitive.words.service;
18+
19+
import java.util.List;
20+
21+
public interface SensitiveWordsService {
22+
/**
23+
* 检查敏感词
24+
*
25+
* @param content 待检测字符串
26+
* @return 敏感词列表
27+
*/
28+
List<String> check(String content);
29+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
3+
* <p>
4+
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* <p>
8+
* http://www.gnu.org/licenses/lgpl.html
9+
* <p>
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package top.continew.starter.sensitive.words.validate;
18+
19+
import jakarta.validation.Constraint;
20+
import jakarta.validation.Payload;
21+
22+
import java.lang.annotation.*;
23+
24+
@Target({ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
25+
@Retention(RetentionPolicy.RUNTIME)
26+
@Documented
27+
@Constraint(validatedBy = {SensitiveWordValidator.class})
28+
public @interface SensitiveWord {
29+
30+
String message() default "有敏感词,请检测!";
31+
32+
Class<?>[] groups() default {};
33+
34+
Class<? extends Payload>[] payload() default {};
35+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
3+
* <p>
4+
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* <p>
8+
* http://www.gnu.org/licenses/lgpl.html
9+
* <p>
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package top.continew.starter.sensitive.words.validate;
18+
19+
import jakarta.annotation.Resource;
20+
import jakarta.validation.ConstraintValidator;
21+
import jakarta.validation.ConstraintValidatorContext;
22+
import top.continew.starter.sensitive.words.service.SensitiveWordsService;
23+
24+
import java.util.List;
25+
26+
public class SensitiveWordValidator implements ConstraintValidator<SensitiveWord, String> {
27+
28+
@Resource
29+
private SensitiveWordsService sensitiveWordsService;
30+
31+
/**
32+
* 初始化方法,可以用自定义注解中获取值进行初始化
33+
*
34+
* @param {@link SensitiveWord } constraintAnnotation 注解值内容
35+
*/
36+
@Override
37+
public void initialize(SensitiveWord constraintAnnotation) {
38+
39+
}
40+
41+
/**
42+
* 实际校验自定义注解 value 值
43+
*
44+
* @param {@link String} value 待检测字符串
45+
* @param {@link ConstraintValidatorContext } constraintValidatorContext 检测的上下文
46+
* @return boolean 是否通过检测
47+
*/
48+
@Override
49+
public boolean isValid(String value, ConstraintValidatorContext context) {
50+
List<String> res = sensitiveWordsService.check(value);
51+
if (!res.isEmpty()) {
52+
// 动态设置错误消息
53+
context.disableDefaultConstraintViolation(); // 禁用默认消息
54+
context.buildConstraintViolationWithTemplate("包含敏感词: " + String.join(",", res))
55+
.addConstraintViolation();
56+
return false;
57+
}
58+
return true;
59+
}
60+
}

0 commit comments

Comments
 (0)