Commit 9a31613e5b766977df62a4977a40ef08bdeefa0b

Authored by YunaiV
1 parent 8093ef3b

【移除】敏感词的管理,简化项目的复杂度

Showing 17 changed files with 0 additions and 1204 deletions
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/sensitiveword/SensitiveWordApi.java deleted
1 -package cn.iocoder.yudao.module.system.api.sensitiveword;  
2 -  
3 -import java.util.List;  
4 -  
5 -/**  
6 - * 敏感词 API 接口  
7 - *  
8 - * @author 永不言败  
9 - */  
10 -public interface SensitiveWordApi {  
11 -  
12 - /**  
13 - * 获得文本所包含的不合法的敏感词数组  
14 - *  
15 - * @param text 文本  
16 - * @param tags 标签数组  
17 - * @return 不合法的敏感词数组  
18 - */  
19 - List<String> validateText(String text, List<String> tags);  
20 -  
21 - /**  
22 - * 判断文本是否包含敏感词  
23 - *  
24 - * @param text 文本  
25 - * @param tags 表述数组  
26 - * @return 是否包含  
27 - */  
28 - boolean isTextValid(String text, List<String> tags);  
29 -  
30 -}  
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java
@@ -115,10 +115,6 @@ public interface ErrorCodeConstants { @@ -115,10 +115,6 @@ public interface ErrorCodeConstants {
115 ErrorCode TENANT_PACKAGE_USED = new ErrorCode(1_002_016_001, "租户正在使用该套餐,请给租户重新设置套餐后再尝试删除"); 115 ErrorCode TENANT_PACKAGE_USED = new ErrorCode(1_002_016_001, "租户正在使用该套餐,请给租户重新设置套餐后再尝试删除");
116 ErrorCode TENANT_PACKAGE_DISABLE = new ErrorCode(1_002_016_002, "名字为【{}】的租户套餐已被禁用"); 116 ErrorCode TENANT_PACKAGE_DISABLE = new ErrorCode(1_002_016_002, "名字为【{}】的租户套餐已被禁用");
117 117
118 - // ========== 错误码模块 1-002-017-000 ==========  
119 - ErrorCode ERROR_CODE_NOT_EXISTS = new ErrorCode(1_002_017_000, "错误码不存在");  
120 - ErrorCode ERROR_CODE_DUPLICATE = new ErrorCode(1_002_017_001, "已经存在编码为【{}】的错误码");  
121 -  
122 // ========== 社交用户 1-002-018-000 ========== 118 // ========== 社交用户 1-002-018-000 ==========
123 ErrorCode SOCIAL_USER_AUTH_FAILURE = new ErrorCode(1_002_018_000, "社交授权失败,原因是:{}"); 119 ErrorCode SOCIAL_USER_AUTH_FAILURE = new ErrorCode(1_002_018_000, "社交授权失败,原因是:{}");
124 ErrorCode SOCIAL_USER_NOT_FOUND = new ErrorCode(1_002_018_001, "社交授权失败,找不到对应的用户"); 120 ErrorCode SOCIAL_USER_NOT_FOUND = new ErrorCode(1_002_018_001, "社交授权失败,找不到对应的用户");
@@ -127,10 +123,6 @@ public interface ErrorCodeConstants { @@ -127,10 +123,6 @@ public interface ErrorCodeConstants {
127 ErrorCode SOCIAL_CLIENT_NOT_EXISTS = new ErrorCode(1_002_018_201, "社交客户端不存在"); 123 ErrorCode SOCIAL_CLIENT_NOT_EXISTS = new ErrorCode(1_002_018_201, "社交客户端不存在");
128 ErrorCode SOCIAL_CLIENT_UNIQUE = new ErrorCode(1_002_018_202, "社交客户端已存在配置"); 124 ErrorCode SOCIAL_CLIENT_UNIQUE = new ErrorCode(1_002_018_202, "社交客户端已存在配置");
129 125
130 - // ========== 系统敏感词 1-002-019-000 =========  
131 - ErrorCode SENSITIVE_WORD_NOT_EXISTS = new ErrorCode(1_002_019_000, "系统敏感词在所有标签中都不存在");  
132 - ErrorCode SENSITIVE_WORD_EXISTS = new ErrorCode(1_002_019_001, "系统敏感词已在标签中存在");  
133 -  
134 // ========== OAuth2 客户端 1-002-020-000 ========= 126 // ========== OAuth2 客户端 1-002-020-000 =========
135 ErrorCode OAUTH2_CLIENT_NOT_EXISTS = new ErrorCode(1_002_020_000, "OAuth2 客户端不存在"); 127 ErrorCode OAUTH2_CLIENT_NOT_EXISTS = new ErrorCode(1_002_020_000, "OAuth2 客户端不存在");
136 ErrorCode OAUTH2_CLIENT_EXISTS = new ErrorCode(1_002_020_001, "OAuth2 客户端编号已存在"); 128 ErrorCode OAUTH2_CLIENT_EXISTS = new ErrorCode(1_002_020_001, "OAuth2 客户端编号已存在");
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/sensitiveword/SensitiveWordApiImpl.java deleted
1 -package cn.iocoder.yudao.module.system.api.sensitiveword;  
2 -  
3 -import cn.iocoder.yudao.module.system.service.sensitiveword.SensitiveWordService;  
4 -import org.springframework.stereotype.Service;  
5 -  
6 -import jakarta.annotation.Resource;  
7 -import java.util.List;  
8 -  
9 -/**  
10 - * 敏感词 API 实现类  
11 - *  
12 - * @author 永不言败  
13 - */  
14 -@Service  
15 -public class SensitiveWordApiImpl implements SensitiveWordApi {  
16 -  
17 - @Resource  
18 - private SensitiveWordService sensitiveWordService;  
19 -  
20 - @Override  
21 - public List<String> validateText(String text, List<String> tags) {  
22 - return sensitiveWordService.validateText(text, tags);  
23 - }  
24 -  
25 - @Override  
26 - public boolean isTextValid(String text, List<String> tags) {  
27 - return sensitiveWordService.isTextValid(text, tags);  
28 - }  
29 -}  
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/SensitiveWordController.http deleted
1 -### 请求 /system/sensitive-word/validate-text 接口 => 成功  
2 -GET {{baseUrl}}/system/sensitive-word/validate-text?text=XXX&tags=短信&tags=蔬菜  
3 -Authorization: Bearer {{token}}  
4 -tenant-id: {{adminTenentId}}  
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/SensitiveWordController.java deleted
1 -package cn.iocoder.yudao.module.system.controller.admin.sensitiveword;  
2 -  
3 -import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;  
4 -import cn.iocoder.yudao.framework.common.pojo.CommonResult;  
5 -import cn.iocoder.yudao.framework.common.pojo.PageParam;  
6 -import cn.iocoder.yudao.framework.common.pojo.PageResult;  
7 -import cn.iocoder.yudao.framework.common.util.object.BeanUtils;  
8 -import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;  
9 -import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordPageReqVO;  
10 -import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordRespVO;  
11 -import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordSaveVO;  
12 -import cn.iocoder.yudao.module.system.dal.dataobject.sensitiveword.SensitiveWordDO;  
13 -import cn.iocoder.yudao.module.system.service.sensitiveword.SensitiveWordService;  
14 -import io.swagger.v3.oas.annotations.Operation;  
15 -import io.swagger.v3.oas.annotations.Parameter;  
16 -import io.swagger.v3.oas.annotations.tags.Tag;  
17 -import jakarta.annotation.Resource;  
18 -import jakarta.servlet.http.HttpServletResponse;  
19 -import jakarta.validation.Valid;  
20 -import org.springframework.security.access.prepost.PreAuthorize;  
21 -import org.springframework.validation.annotation.Validated;  
22 -import org.springframework.web.bind.annotation.*;  
23 -  
24 -import java.io.IOException;  
25 -import java.util.List;  
26 -import java.util.Set;  
27 -  
28 -import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;  
29 -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;  
30 -  
31 -@Tag(name = "管理后台 - 敏感词")  
32 -@RestController  
33 -@RequestMapping("/system/sensitive-word")  
34 -@Validated  
35 -public class SensitiveWordController {  
36 -  
37 - @Resource  
38 - private SensitiveWordService sensitiveWordService;  
39 -  
40 - @PostMapping("/create")  
41 - @Operation(summary = "创建敏感词")  
42 - @PreAuthorize("@ss.hasPermission('system:sensitive-word:create')")  
43 - public CommonResult<Long> createSensitiveWord(@Valid @RequestBody SensitiveWordSaveVO createReqVO) {  
44 - return success(sensitiveWordService.createSensitiveWord(createReqVO));  
45 - }  
46 -  
47 - @PutMapping("/update")  
48 - @Operation(summary = "更新敏感词")  
49 - @PreAuthorize("@ss.hasPermission('system:sensitive-word:update')")  
50 - public CommonResult<Boolean> updateSensitiveWord(@Valid @RequestBody SensitiveWordSaveVO updateReqVO) {  
51 - sensitiveWordService.updateSensitiveWord(updateReqVO);  
52 - return success(true);  
53 - }  
54 -  
55 - @DeleteMapping("/delete")  
56 - @Operation(summary = "删除敏感词")  
57 - @Parameter(name = "id", description = "编号", required = true)  
58 - @PreAuthorize("@ss.hasPermission('system:sensitive-word:delete')")  
59 - public CommonResult<Boolean> deleteSensitiveWord(@RequestParam("id") Long id) {  
60 - sensitiveWordService.deleteSensitiveWord(id);  
61 - return success(true);  
62 - }  
63 -  
64 - @GetMapping("/get")  
65 - @Operation(summary = "获得敏感词")  
66 - @Parameter(name = "id", description = "编号", required = true, example = "1024")  
67 - @PreAuthorize("@ss.hasPermission('system:sensitive-word:query')")  
68 - public CommonResult<SensitiveWordRespVO> getSensitiveWord(@RequestParam("id") Long id) {  
69 - SensitiveWordDO sensitiveWord = sensitiveWordService.getSensitiveWord(id);  
70 - return success(BeanUtils.toBean(sensitiveWord, SensitiveWordRespVO.class));  
71 - }  
72 -  
73 - @GetMapping("/page")  
74 - @Operation(summary = "获得敏感词分页")  
75 - @PreAuthorize("@ss.hasPermission('system:sensitive-word:query')")  
76 - public CommonResult<PageResult<SensitiveWordRespVO>> getSensitiveWordPage(@Valid SensitiveWordPageReqVO pageVO) {  
77 - PageResult<SensitiveWordDO> pageResult = sensitiveWordService.getSensitiveWordPage(pageVO);  
78 - return success(BeanUtils.toBean(pageResult, SensitiveWordRespVO.class));  
79 - }  
80 -  
81 - @GetMapping("/export-excel")  
82 - @Operation(summary = "导出敏感词 Excel")  
83 - @PreAuthorize("@ss.hasPermission('system:sensitive-word:export')")  
84 - @ApiAccessLog(operateType = EXPORT)  
85 - public void exportSensitiveWordExcel(@Valid SensitiveWordPageReqVO exportReqVO,  
86 - HttpServletResponse response) throws IOException {  
87 - exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);  
88 - List<SensitiveWordDO> list = sensitiveWordService.getSensitiveWordPage(exportReqVO).getList();  
89 - // 导出 Excel  
90 - ExcelUtils.write(response, "敏感词.xls", "数据", SensitiveWordRespVO.class,  
91 - BeanUtils.toBean(list, SensitiveWordRespVO.class));  
92 - }  
93 -  
94 - @GetMapping("/get-tags")  
95 - @Operation(summary = "获取所有敏感词的标签数组")  
96 - @PreAuthorize("@ss.hasPermission('system:sensitive-word:query')")  
97 - public CommonResult<Set<String>> getSensitiveWordTagSet() {  
98 - return success(sensitiveWordService.getSensitiveWordTagSet());  
99 - }  
100 -  
101 - @GetMapping("/validate-text")  
102 - @Operation(summary = "获得文本所包含的不合法的敏感词数组")  
103 - public CommonResult<List<String>> validateText(@RequestParam("text") String text,  
104 - @RequestParam(value = "tags", required = false) List<String> tags) {  
105 - return success(sensitiveWordService.validateText(text, tags));  
106 - }  
107 -  
108 -}  
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordPageReqVO.java deleted
1 -package cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo;  
2 -  
3 -import cn.iocoder.yudao.framework.common.pojo.PageParam;  
4 -import io.swagger.v3.oas.annotations.media.Schema;  
5 -import lombok.Data;  
6 -import lombok.EqualsAndHashCode;  
7 -import lombok.ToString;  
8 -import org.springframework.format.annotation.DateTimeFormat;  
9 -  
10 -import java.time.LocalDateTime;  
11 -  
12 -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;  
13 -  
14 -@Schema(description = "管理后台 - 敏感词分页 Request VO")  
15 -@Data  
16 -@EqualsAndHashCode(callSuper = true)  
17 -@ToString(callSuper = true)  
18 -public class SensitiveWordPageReqVO extends PageParam {  
19 -  
20 - @Schema(description = "敏感词", example = "敏感词")  
21 - private String name;  
22 -  
23 - @Schema(description = "标签", example = "短信,评论")  
24 - private String tag;  
25 -  
26 - @Schema(description = "状态,参见 CommonStatusEnum 枚举类", example = "1")  
27 - private Integer status;  
28 -  
29 - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)  
30 - @Schema(description = "创建时间")  
31 - private LocalDateTime[] createTime;  
32 -  
33 -}  
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordRespVO.java deleted
1 -package cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo;  
2 -  
3 -import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;  
4 -import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;  
5 -import cn.iocoder.yudao.framework.excel.core.convert.JsonConvert;  
6 -import cn.iocoder.yudao.module.system.enums.DictTypeConstants;  
7 -import com.alibaba.excel.annotation.ExcelProperty;  
8 -import io.swagger.v3.oas.annotations.media.Schema;  
9 -import lombok.Data;  
10 -import lombok.EqualsAndHashCode;  
11 -import lombok.ToString;  
12 -  
13 -import java.time.LocalDateTime;  
14 -import java.util.List;  
15 -  
16 -@Schema(description = "管理后台 - 敏感词 Response VO")  
17 -@Data  
18 -public class SensitiveWordRespVO {  
19 -  
20 - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")  
21 - @ExcelProperty("编号")  
22 - private Long id;  
23 -  
24 - @Schema(description = "敏感词", requiredMode = Schema.RequiredMode.REQUIRED, example = "敏感词")  
25 - @ExcelProperty("敏感词")  
26 - private String name;  
27 -  
28 - @Schema(description = "标签", requiredMode = Schema.RequiredMode.REQUIRED, example = "短信,评论")  
29 - @ExcelProperty(value = "标签", converter = JsonConvert.class)  
30 - private List<String> tags;  
31 -  
32 - @Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")  
33 - @ExcelProperty(value = "状态", converter = DictConvert.class)  
34 - @DictFormat(DictTypeConstants.COMMON_STATUS)  
35 - private Integer status;  
36 -  
37 - @Schema(description = "描述", example = "污言秽语")  
38 - @ExcelProperty("描述")  
39 - private String description;  
40 -  
41 - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)  
42 - @ExcelProperty("创建时间")  
43 - private LocalDateTime createTime;  
44 -  
45 -}  
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordSaveVO.java deleted
1 -package cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo;  
2 -  
3 -import io.swagger.v3.oas.annotations.media.Schema;  
4 -import lombok.Data;  
5 -  
6 -import jakarta.validation.constraints.NotNull;  
7 -import java.util.List;  
8 -  
9 -@Schema(description = "管理后台 - 敏感词创建/修改 Request VO")  
10 -@Data  
11 -public class SensitiveWordSaveVO {  
12 -  
13 - @Schema(description = "编号", example = "1")  
14 - private Long id;  
15 -  
16 - @Schema(description = "敏感词", requiredMode = Schema.RequiredMode.REQUIRED, example = "敏感词")  
17 - @NotNull(message = "敏感词不能为空")  
18 - private String name;  
19 -  
20 - @Schema(description = "标签", requiredMode = Schema.RequiredMode.REQUIRED, example = "短信,评论")  
21 - @NotNull(message = "标签不能为空")  
22 - private List<String> tags;  
23 -  
24 - @Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")  
25 - @NotNull(message = "状态不能为空")  
26 - private Integer status;  
27 -  
28 - @Schema(description = "描述", example = "污言秽语")  
29 - private String description;  
30 -  
31 -}  
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sensitiveword/SensitiveWordDO.java deleted
1 -package cn.iocoder.yudao.module.system.dal.dataobject.sensitiveword;  
2 -  
3 -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;  
4 -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;  
5 -import cn.iocoder.yudao.framework.mybatis.core.type.StringListTypeHandler;  
6 -import com.baomidou.mybatisplus.annotation.KeySequence;  
7 -import com.baomidou.mybatisplus.annotation.TableField;  
8 -import com.baomidou.mybatisplus.annotation.TableId;  
9 -import com.baomidou.mybatisplus.annotation.TableName;  
10 -import lombok.*;  
11 -  
12 -import java.util.List;  
13 -  
14 -/**  
15 - * 敏感词 DO  
16 - *  
17 - * @author 永不言败  
18 - */  
19 -@TableName(value = "system_sensitive_word", autoResultMap = true)  
20 -@KeySequence("system_sensitive_word_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。  
21 -@Data  
22 -@EqualsAndHashCode(callSuper = true)  
23 -@ToString(callSuper = true)  
24 -@Builder  
25 -@NoArgsConstructor  
26 -@AllArgsConstructor  
27 -public class SensitiveWordDO extends BaseDO {  
28 -  
29 - /**  
30 - * 编号  
31 - */  
32 - @TableId  
33 - private Long id;  
34 - /**  
35 - * 敏感词  
36 - */  
37 - private String name;  
38 - /**  
39 - * 描述  
40 - */  
41 - private String description;  
42 - /**  
43 - * 标签数组  
44 - *  
45 - * 用于实现不同的业务场景下,需要使用不同标签的敏感词。  
46 - * 例如说,tag 有短信、论坛两种,敏感词 "推广" 在短信下是敏感词,在论坛下不是敏感词。  
47 - * 此时,我们会存储一条敏感词记录,它的 name 为"推广",tag 为短信。  
48 - */  
49 - @TableField(typeHandler = StringListTypeHandler.class)  
50 - private List<String> tags;  
51 - /**  
52 - * 状态  
53 - *  
54 - * 枚举 {@link CommonStatusEnum}  
55 - */  
56 - private Integer status;  
57 -  
58 -}  
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sensitiveword/SensitiveWordMapper.java deleted
1 -package cn.iocoder.yudao.module.system.dal.mysql.sensitiveword;  
2 -  
3 -import cn.iocoder.yudao.framework.common.pojo.PageResult;  
4 -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;  
5 -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;  
6 -import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordPageReqVO;  
7 -import cn.iocoder.yudao.module.system.dal.dataobject.sensitiveword.SensitiveWordDO;  
8 -import org.apache.ibatis.annotations.Mapper;  
9 -import org.apache.ibatis.annotations.Select;  
10 -  
11 -import java.time.LocalDateTime;  
12 -  
13 -/**  
14 - * 敏感词 Mapper  
15 - *  
16 - * @author 永不言败  
17 - */  
18 -@Mapper  
19 -public interface SensitiveWordMapper extends BaseMapperX<SensitiveWordDO> {  
20 -  
21 - default PageResult<SensitiveWordDO> selectPage(SensitiveWordPageReqVO reqVO) {  
22 - return selectPage(reqVO, new LambdaQueryWrapperX<SensitiveWordDO>()  
23 - .likeIfPresent(SensitiveWordDO::getName, reqVO.getName())  
24 - .likeIfPresent(SensitiveWordDO::getTags, reqVO.getTag())  
25 - .eqIfPresent(SensitiveWordDO::getStatus, reqVO.getStatus())  
26 - .betweenIfPresent(SensitiveWordDO::getCreateTime, reqVO.getCreateTime())  
27 - .orderByDesc(SensitiveWordDO::getId));  
28 - }  
29 - default SensitiveWordDO selectByName(String name) {  
30 - return selectOne(SensitiveWordDO::getName, name);  
31 - }  
32 -  
33 - @Select("SELECT COUNT(*) FROM system_sensitive_word WHERE update_time > #{maxUpdateTime}")  
34 - Long selectCountByUpdateTimeGt(LocalDateTime maxTime);  
35 -  
36 -}  
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sensitiveword/SensitiveWordService.java deleted
1 -package cn.iocoder.yudao.module.system.service.sensitiveword;  
2 -  
3 -import cn.iocoder.yudao.framework.common.pojo.PageResult;  
4 -import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordPageReqVO;  
5 -import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordSaveVO;  
6 -import cn.iocoder.yudao.module.system.dal.dataobject.sensitiveword.SensitiveWordDO;  
7 -  
8 -import jakarta.validation.Valid;  
9 -import java.util.List;  
10 -import java.util.Set;  
11 -  
12 -/**  
13 - * 敏感词 Service 接口  
14 - *  
15 - * @author 永不言败  
16 - */  
17 -public interface SensitiveWordService {  
18 -  
19 - /**  
20 - * 创建敏感词  
21 - *  
22 - * @param createReqVO 创建信息  
23 - * @return 编号  
24 - */  
25 - Long createSensitiveWord(@Valid SensitiveWordSaveVO createReqVO);  
26 -  
27 - /**  
28 - * 更新敏感词  
29 - *  
30 - * @param updateReqVO 更新信息  
31 - */  
32 - void updateSensitiveWord(@Valid SensitiveWordSaveVO updateReqVO);  
33 -  
34 - /**  
35 - * 删除敏感词  
36 - *  
37 - * @param id 编号  
38 - */  
39 - void deleteSensitiveWord(Long id);  
40 -  
41 - /**  
42 - * 获得敏感词  
43 - *  
44 - * @param id 编号  
45 - * @return 敏感词  
46 - */  
47 - SensitiveWordDO getSensitiveWord(Long id);  
48 -  
49 - /**  
50 - * 获得敏感词列表  
51 - *  
52 - * @return 敏感词列表  
53 - */  
54 - List<SensitiveWordDO> getSensitiveWordList();  
55 -  
56 - /**  
57 - * 获得敏感词分页  
58 - *  
59 - * @param pageReqVO 分页查询  
60 - * @return 敏感词分页  
61 - */  
62 - PageResult<SensitiveWordDO> getSensitiveWordPage(SensitiveWordPageReqVO pageReqVO);  
63 -  
64 - /**  
65 - * 获得所有敏感词的标签数组  
66 - *  
67 - * @return 标签数组  
68 - */  
69 - Set<String> getSensitiveWordTagSet();  
70 -  
71 - /**  
72 - * 获得文本所包含的不合法的敏感词数组  
73 - *  
74 - * @param text 文本  
75 - * @param tags 标签数组  
76 - * @return 不合法的敏感词数组  
77 - */  
78 - List<String> validateText(String text, List<String> tags);  
79 -  
80 - /**  
81 - * 判断文本是否包含敏感词  
82 - *  
83 - * @param text 文本  
84 - * @param tags 标签数组  
85 - * @return 是否包含敏感词  
86 - */  
87 - boolean isTextValid(String text, List<String> tags);  
88 -  
89 -}  
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sensitiveword/SensitiveWordServiceImpl.java deleted
1 -package cn.iocoder.yudao.module.system.service.sensitiveword;  
2 -  
3 -import cn.hutool.core.collection.CollUtil;  
4 -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;  
5 -import cn.iocoder.yudao.framework.common.pojo.PageResult;  
6 -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;  
7 -import cn.iocoder.yudao.framework.common.util.object.BeanUtils;  
8 -import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordPageReqVO;  
9 -import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordSaveVO;  
10 -import cn.iocoder.yudao.module.system.dal.dataobject.sensitiveword.SensitiveWordDO;  
11 -import cn.iocoder.yudao.module.system.dal.mysql.sensitiveword.SensitiveWordMapper;  
12 -import cn.iocoder.yudao.module.system.util.collection.SimpleTrie;  
13 -import com.google.common.collect.HashMultimap;  
14 -import com.google.common.collect.Multimap;  
15 -import lombok.Getter;  
16 -import lombok.extern.slf4j.Slf4j;  
17 -import org.springframework.scheduling.annotation.Scheduled;  
18 -import org.springframework.stereotype.Service;  
19 -import org.springframework.util.Assert;  
20 -import org.springframework.validation.annotation.Validated;  
21 -  
22 -import jakarta.annotation.PostConstruct;  
23 -import jakarta.annotation.Resource;  
24 -import java.time.LocalDateTime;  
25 -import java.util.*;  
26 -import java.util.concurrent.TimeUnit;  
27 -  
28 -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;  
29 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;  
30 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getMaxValue;  
31 -import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SENSITIVE_WORD_EXISTS;  
32 -import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SENSITIVE_WORD_NOT_EXISTS;  
33 -  
34 -/**  
35 - * 敏感词 Service 实现类  
36 - *  
37 - * @author 永不言败  
38 - */  
39 -@Service  
40 -@Slf4j  
41 -@Validated  
42 -public class SensitiveWordServiceImpl implements SensitiveWordService {  
43 -  
44 - /**  
45 - * 是否开启敏感词功能  
46 - */  
47 - public static Boolean ENABLED = false;  
48 -  
49 - /**  
50 - * 敏感词列表缓存  
51 - */  
52 - @Getter  
53 - private volatile List<SensitiveWordDO> sensitiveWordCache = Collections.emptyList();  
54 - /**  
55 - * 敏感词标签缓存  
56 - * key:敏感词编号 {@link SensitiveWordDO#getId()}  
57 - * <p>  
58 - * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向  
59 - */  
60 - @Getter  
61 - private volatile Set<String> sensitiveWordTagsCache = Collections.emptySet();  
62 -  
63 - @Resource  
64 - private SensitiveWordMapper sensitiveWordMapper;  
65 -  
66 - /**  
67 - * 默认的敏感词的字典树,包含所有敏感词  
68 - */  
69 - @Getter  
70 - private volatile SimpleTrie defaultSensitiveWordTrie = new SimpleTrie(Collections.emptySet());  
71 - /**  
72 - * 标签与敏感词的字段数的映射  
73 - */  
74 - @Getter  
75 - private volatile Map<String, SimpleTrie> tagSensitiveWordTries = Collections.emptyMap();  
76 -  
77 - /**  
78 - * 初始化缓存  
79 - */  
80 - @PostConstruct  
81 - public void initLocalCache() {  
82 - if (!ENABLED) {  
83 - return;  
84 - }  
85 -  
86 - // 第一步:查询数据  
87 - List<SensitiveWordDO> sensitiveWords = sensitiveWordMapper.selectList();  
88 - log.info("[initLocalCache][缓存敏感词,数量为:{}]", sensitiveWords.size());  
89 -  
90 - // 第二步:构建缓存  
91 - // 写入 sensitiveWordTagsCache 缓存  
92 - Set<String> tags = new HashSet<>();  
93 - sensitiveWords.forEach(word -> tags.addAll(word.getTags()));  
94 - sensitiveWordTagsCache = tags;  
95 - sensitiveWordCache = sensitiveWords;  
96 - // 写入 defaultSensitiveWordTrie、tagSensitiveWordTries 缓存  
97 - initSensitiveWordTrie(sensitiveWords);  
98 - }  
99 -  
100 - private void initSensitiveWordTrie(List<SensitiveWordDO> wordDOs) {  
101 - // 过滤禁用的敏感词  
102 - wordDOs = filterList(wordDOs, word -> word.getStatus().equals(CommonStatusEnum.ENABLE.getStatus()));  
103 -  
104 - // 初始化默认的 defaultSensitiveWordTrie  
105 - this.defaultSensitiveWordTrie = new SimpleTrie(CollectionUtils.convertList(wordDOs, SensitiveWordDO::getName));  
106 -  
107 - // 初始化 tagSensitiveWordTries  
108 - Multimap<String, String> tagWords = HashMultimap.create();  
109 - for (SensitiveWordDO word : wordDOs) {  
110 - if (CollUtil.isEmpty(word.getTags())) {  
111 - continue;  
112 - }  
113 - word.getTags().forEach(tag -> tagWords.put(tag, word.getName()));  
114 - }  
115 - // 添加到 tagSensitiveWordTries 中  
116 - Map<String, SimpleTrie> tagSensitiveWordTries = new HashMap<>();  
117 - tagWords.asMap().forEach((tag, words) -> tagSensitiveWordTries.put(tag, new SimpleTrie(words)));  
118 - this.tagSensitiveWordTries = tagSensitiveWordTries;  
119 - }  
120 -  
121 - /**  
122 - * 通过定时任务轮询,刷新缓存  
123 - *  
124 - * 目的:多节点部署时,通过轮询”通知“所有节点,进行刷新  
125 - */  
126 - @Scheduled(initialDelay = 60, fixedRate = 60, timeUnit = TimeUnit.SECONDS)  
127 - public void refreshLocalCache() {  
128 - // 情况一:如果缓存里没有数据,则直接刷新缓存  
129 - if (CollUtil.isEmpty(sensitiveWordCache)) {  
130 - initLocalCache();  
131 - return;  
132 - }  
133 -  
134 - // 情况二,如果缓存里数据,则通过 updateTime 判断是否有数据变更,有变更则刷新缓存  
135 - LocalDateTime maxTime = getMaxValue(sensitiveWordCache, SensitiveWordDO::getUpdateTime);  
136 - if (sensitiveWordMapper.selectCountByUpdateTimeGt(maxTime) > 0) {  
137 - initLocalCache();  
138 - }  
139 - }  
140 -  
141 - @Override  
142 - public Long createSensitiveWord(SensitiveWordSaveVO createReqVO) {  
143 - // 校验唯一性  
144 - validateSensitiveWordNameUnique(null, createReqVO.getName());  
145 -  
146 - // 插入  
147 - SensitiveWordDO sensitiveWord = BeanUtils.toBean(createReqVO, SensitiveWordDO.class);  
148 - sensitiveWordMapper.insert(sensitiveWord);  
149 -  
150 - // 刷新缓存  
151 - initLocalCache();  
152 - return sensitiveWord.getId();  
153 - }  
154 -  
155 - @Override  
156 - public void updateSensitiveWord(SensitiveWordSaveVO updateReqVO) {  
157 - // 校验唯一性  
158 - validateSensitiveWordExists(updateReqVO.getId());  
159 - validateSensitiveWordNameUnique(updateReqVO.getId(), updateReqVO.getName());  
160 -  
161 - // 更新  
162 - SensitiveWordDO updateObj = BeanUtils.toBean(updateReqVO, SensitiveWordDO.class);  
163 - sensitiveWordMapper.updateById(updateObj);  
164 -  
165 - // 刷新缓存  
166 - initLocalCache();  
167 - }  
168 -  
169 - @Override  
170 - public void deleteSensitiveWord(Long id) {  
171 - // 校验存在  
172 - validateSensitiveWordExists(id);  
173 - // 删除  
174 - sensitiveWordMapper.deleteById(id);  
175 -  
176 - // 刷新缓存  
177 - initLocalCache();  
178 - }  
179 -  
180 - private void validateSensitiveWordNameUnique(Long id, String name) {  
181 - SensitiveWordDO word = sensitiveWordMapper.selectByName(name);  
182 - if (word == null) {  
183 - return;  
184 - }  
185 - // 如果 id 为空,说明不用比较是否为相同 id 的敏感词  
186 - if (id == null) {  
187 - throw exception(SENSITIVE_WORD_EXISTS);  
188 - }  
189 - if (!word.getId().equals(id)) {  
190 - throw exception(SENSITIVE_WORD_EXISTS);  
191 - }  
192 - }  
193 -  
194 - private void validateSensitiveWordExists(Long id) {  
195 - if (sensitiveWordMapper.selectById(id) == null) {  
196 - throw exception(SENSITIVE_WORD_NOT_EXISTS);  
197 - }  
198 - }  
199 -  
200 - @Override  
201 - public SensitiveWordDO getSensitiveWord(Long id) {  
202 - return sensitiveWordMapper.selectById(id);  
203 - }  
204 -  
205 - @Override  
206 - public List<SensitiveWordDO> getSensitiveWordList() {  
207 - return sensitiveWordMapper.selectList();  
208 - }  
209 -  
210 - @Override  
211 - public PageResult<SensitiveWordDO> getSensitiveWordPage(SensitiveWordPageReqVO pageReqVO) {  
212 - return sensitiveWordMapper.selectPage(pageReqVO);  
213 - }  
214 -  
215 - @Override  
216 - public Set<String> getSensitiveWordTagSet() {  
217 - return sensitiveWordTagsCache;  
218 - }  
219 -  
220 - @Override  
221 - public List<String> validateText(String text, List<String> tags) {  
222 - Assert.isTrue(ENABLED, "敏感词功能未开启,请将 ENABLED 设置为 true");  
223 -  
224 - // 无标签时,默认所有  
225 - if (CollUtil.isEmpty(tags)) {  
226 - return defaultSensitiveWordTrie.validate(text);  
227 - }  
228 - // 有标签的情况  
229 - Set<String> result = new HashSet<>();  
230 - tags.forEach(tag -> {  
231 - SimpleTrie trie = tagSensitiveWordTries.get(tag);  
232 - if (trie == null) {  
233 - return;  
234 - }  
235 - result.addAll(trie.validate(text));  
236 - });  
237 - return new ArrayList<>(result);  
238 - }  
239 -  
240 - @Override  
241 - public boolean isTextValid(String text, List<String> tags) {  
242 - Assert.isTrue(ENABLED, "敏感词功能未开启,请将 ENABLED 设置为 true");  
243 -  
244 - // 无标签时,默认所有  
245 - if (CollUtil.isEmpty(tags)) {  
246 - return defaultSensitiveWordTrie.isValid(text);  
247 - }  
248 - // 有标签的情况  
249 - for (String tag : tags) {  
250 - SimpleTrie trie = tagSensitiveWordTries.get(tag);  
251 - if (trie == null) {  
252 - continue;  
253 - }  
254 - // 如果有一个标签不合法,则返回 false 不合法  
255 - if (!trie.isValid(text)) {  
256 - return false;  
257 - }  
258 - }  
259 - return true;  
260 - }  
261 -  
262 -}  
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/util/collection/SimpleTrie.java deleted
1 -package cn.iocoder.yudao.module.system.util.collection;  
2 -  
3 -import cn.hutool.core.collection.CollUtil;  
4 -  
5 -import java.util.*;  
6 -  
7 -/**  
8 - * 基于前缀树,实现敏感词的校验  
9 - * <p>  
10 - * 相比 Apache Common 提供的 PatriciaTrie 来说,性能可能会更加好一些。  
11 - *  
12 - * @author 芋道源码  
13 - */  
14 -@SuppressWarnings("unchecked")  
15 -public class SimpleTrie {  
16 -  
17 - /**  
18 - * 一个敏感词结束后对应的 key  
19 - */  
20 - private static final Character CHARACTER_END = '\0';  
21 -  
22 - /**  
23 - * 使用敏感词,构建的前缀树  
24 - */  
25 - private final Map<Character, Object> children;  
26 -  
27 - /**  
28 - * 基于字符串,构建前缀树  
29 - *  
30 - * @param strs 字符串数组  
31 - */  
32 - public SimpleTrie(Collection<String> strs) {  
33 - // 排序,优先使用较短的前缀  
34 - strs = CollUtil.sort(strs, String::compareTo);  
35 - // 构建树  
36 - children = new HashMap<>();  
37 - for (String str : strs) {  
38 - Map<Character, Object> child = children;  
39 - // 遍历每个字符  
40 - for (Character c : str.toCharArray()) {  
41 - // 如果已经到达结束,就没必要在添加更长的敏感词。  
42 - // 例如说,有两个敏感词是:吃饭啊、吃饭。输入一句话是 “我要吃饭啊”,则只要匹配到 “吃饭” 这个敏感词即可。  
43 - if (child.containsKey(CHARACTER_END)) {  
44 - break;  
45 - }  
46 - if (!child.containsKey(c)) {  
47 - child.put(c, new HashMap<>());  
48 - }  
49 - child = (Map<Character, Object>) child.get(c);  
50 - }  
51 - // 结束  
52 - child.put(CHARACTER_END, null);  
53 - }  
54 - }  
55 -  
56 - /**  
57 - * 验证文本是否合法,即不包含敏感词  
58 - *  
59 - * @param text 文本  
60 - * @return 是否 true-合法 false-不合法  
61 - */  
62 - public boolean isValid(String text) {  
63 - // 遍历 text,使用每一个 [i, n) 段的字符串,使用 children 前缀树匹配,是否包含敏感词  
64 - for (int i = 0; i < text.length(); i++) {  
65 - Map<Character, Object> child = (Map<Character, Object>) children.get(text.charAt(i));  
66 - if (child == null) {  
67 - continue;  
68 - }  
69 - boolean ok = recursion(text, i + 1, child);  
70 - if (!ok) {  
71 - return false;  
72 - }  
73 - }  
74 - return true;  
75 - }  
76 -  
77 - /**  
78 - * 验证文本从指定位置开始,是否不包含某个敏感词  
79 - *  
80 - * @param text 文本  
81 - * @param index 开始位置  
82 - * @param child 节点(当前遍历到的)  
83 - * @return 是否不包含 true-不包含 false-包含  
84 - */  
85 - private boolean recursion(String text, int index, Map<Character, Object> child) {  
86 - if (child.containsKey(CHARACTER_END)) {  
87 - return false;  
88 - }  
89 - if (index == text.length()) {  
90 - return true;  
91 - }  
92 - child = (Map<Character, Object>) child.get(text.charAt(index));  
93 - return child == null || !child.containsKey(CHARACTER_END) && recursion(text, ++index, child);  
94 - }  
95 -  
96 - /**  
97 - * 获得文本所包含的不合法的敏感词  
98 - *  
99 - * 注意,才当即最短匹配原则。例如说:当敏感词存在 “煞笔”,“煞笔二货 ”时,只会返回 “煞笔”。  
100 - *  
101 - * @param text 文本  
102 - * @return 匹配的敏感词  
103 - */  
104 - public List<String> validate(String text) {  
105 - Set<String> results = new HashSet<>();  
106 - for (int i = 0; i < text.length(); i++) {  
107 - Character c = text.charAt(i);  
108 - Map<Character, Object> child = (Map<Character, Object>) children.get(c);  
109 - if (child == null) {  
110 - continue;  
111 - }  
112 - StringBuilder result = new StringBuilder().append(c);  
113 - boolean ok = recursionWithResult(text, i + 1, child, result);  
114 - if (!ok) {  
115 - results.add(result.toString());  
116 - }  
117 - }  
118 - return new ArrayList<>(results);  
119 - }  
120 -  
121 - /**  
122 - * 返回文本从 index 开始的敏感词,并使用 StringBuilder 参数进行返回  
123 - *  
124 - * 逻辑和 {@link #recursion(String, int, Map)} 是一致,只是多了 result 返回结果  
125 - *  
126 - * @param text 文本  
127 - * @param index 开始未知  
128 - * @param child 节点(当前遍历到的)  
129 - * @param result 返回敏感词  
130 - * @return 是否有敏感词  
131 - */  
132 - @SuppressWarnings("unchecked")  
133 - private static boolean recursionWithResult(String text, int index, Map<Character, Object> child, StringBuilder result) {  
134 - if (child.containsKey(CHARACTER_END)) {  
135 - return false;  
136 - }  
137 - if (index == text.length()) {  
138 - return true;  
139 - }  
140 - Character c = text.charAt(index);  
141 - child = (Map<Character, Object>) child.get(c);  
142 - if (child == null) {  
143 - return true;  
144 - }  
145 - if (child.containsKey(CHARACTER_END)) {  
146 - result.append(c);  
147 - return false;  
148 - }  
149 - return recursionWithResult(text, ++index, child, result.append(c));  
150 - }  
151 -  
152 -}  
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sensitiveword/SensitiveWordServiceImplTest.java deleted
1 -package cn.iocoder.yudao.module.system.service.sensitiveword;  
2 -  
3 -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;  
4 -import cn.iocoder.yudao.framework.common.pojo.PageResult;  
5 -import cn.iocoder.yudao.framework.common.util.collection.SetUtils;  
6 -import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;  
7 -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;  
8 -import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordPageReqVO;  
9 -import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordSaveVO;  
10 -import cn.iocoder.yudao.module.system.dal.dataobject.sensitiveword.SensitiveWordDO;  
11 -import cn.iocoder.yudao.module.system.dal.mysql.sensitiveword.SensitiveWordMapper;  
12 -import org.junit.jupiter.api.BeforeEach;  
13 -import org.junit.jupiter.api.Test;  
14 -import org.springframework.context.annotation.Import;  
15 -  
16 -import jakarta.annotation.Resource;  
17 -import java.time.Duration;  
18 -import java.time.LocalDateTime;  
19 -import java.util.Arrays;  
20 -import java.util.List;  
21 -  
22 -import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;  
23 -import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;  
24 -import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;  
25 -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;  
26 -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;  
27 -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;  
28 -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;  
29 -import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SENSITIVE_WORD_NOT_EXISTS;  
30 -import static java.util.Collections.singletonList;  
31 -import static org.junit.jupiter.api.Assertions.*;  
32 -  
33 -/**  
34 - * {@link SensitiveWordServiceImpl} 的单元测试类  
35 - *  
36 - * @author 永不言败  
37 - */  
38 -@Import(SensitiveWordServiceImpl.class)  
39 -public class SensitiveWordServiceImplTest extends BaseDbUnitTest {  
40 -  
41 - @Resource  
42 - private SensitiveWordServiceImpl sensitiveWordService;  
43 -  
44 - @Resource  
45 - private SensitiveWordMapper sensitiveWordMapper;  
46 -  
47 - @BeforeEach  
48 - public void setUp() {  
49 - SensitiveWordServiceImpl.ENABLED = true;  
50 - }  
51 -  
52 - @Test  
53 - public void testInitLocalCache() {  
54 - SensitiveWordDO wordDO1 = randomPojo(SensitiveWordDO.class, o -> o.setName("傻瓜")  
55 - .setTags(singletonList("论坛")).setStatus(CommonStatusEnum.ENABLE.getStatus()));  
56 - sensitiveWordMapper.insert(wordDO1);  
57 - SensitiveWordDO wordDO2 = randomPojo(SensitiveWordDO.class, o -> o.setName("笨蛋")  
58 - .setTags(singletonList("蔬菜")).setStatus(CommonStatusEnum.ENABLE.getStatus()));  
59 - sensitiveWordMapper.insert(wordDO2);  
60 - SensitiveWordDO wordDO3 = randomPojo(SensitiveWordDO.class, o -> o.setName("白")  
61 - .setTags(singletonList("测试")).setStatus(CommonStatusEnum.ENABLE.getStatus()));  
62 - sensitiveWordMapper.insert(wordDO3);  
63 - SensitiveWordDO wordDO4 = randomPojo(SensitiveWordDO.class, o -> o.setName("白痴")  
64 - .setTags(singletonList("测试")).setStatus(CommonStatusEnum.ENABLE.getStatus()));  
65 - sensitiveWordMapper.insert(wordDO4);  
66 -  
67 - // 调用  
68 - sensitiveWordService.initLocalCache();  
69 - // 断言 sensitiveWordTagsCache 缓存  
70 - assertEquals(SetUtils.asSet("论坛", "蔬菜", "测试"), sensitiveWordService.getSensitiveWordTagSet());  
71 - // 断言 sensitiveWordCache  
72 - assertEquals(4, sensitiveWordService.getSensitiveWordCache().size());  
73 - assertPojoEquals(wordDO1, sensitiveWordService.getSensitiveWordCache().get(0));  
74 - assertPojoEquals(wordDO2, sensitiveWordService.getSensitiveWordCache().get(1));  
75 - assertPojoEquals(wordDO3, sensitiveWordService.getSensitiveWordCache().get(2));  
76 - // 断言 tagSensitiveWordTries 缓存  
77 - assertNotNull(sensitiveWordService.getDefaultSensitiveWordTrie());  
78 - assertEquals(3, sensitiveWordService.getTagSensitiveWordTries().size());  
79 - assertNotNull(sensitiveWordService.getTagSensitiveWordTries().get("论坛"));  
80 - assertNotNull(sensitiveWordService.getTagSensitiveWordTries().get("蔬菜"));  
81 - assertNotNull(sensitiveWordService.getTagSensitiveWordTries().get("测试"));  
82 - }  
83 -  
84 - @Test  
85 - public void testRefreshLocalCache() {  
86 - // mock 数据  
87 - SensitiveWordDO wordDO1 = randomPojo(SensitiveWordDO.class, o -> o.setName("傻瓜")  
88 - .setTags(singletonList("论坛")).setStatus(CommonStatusEnum.ENABLE.getStatus()));  
89 - wordDO1.setUpdateTime(LocalDateTime.now());  
90 - sensitiveWordMapper.insert(wordDO1);  
91 - sensitiveWordService.initLocalCache();  
92 - // mock 数据 ②  
93 - SensitiveWordDO wordDO2 = randomPojo(SensitiveWordDO.class, o -> o.setName("笨蛋")  
94 - .setTags(singletonList("蔬菜")).setStatus(CommonStatusEnum.ENABLE.getStatus()));  
95 - wordDO2.setUpdateTime(LocalDateTimeUtils.addTime(Duration.ofMinutes(1))); // 避免时间相同  
96 - sensitiveWordMapper.insert(wordDO2);  
97 -  
98 - // 调用  
99 - sensitiveWordService.refreshLocalCache();  
100 - // 断言 sensitiveWordTagsCache 缓存  
101 - assertEquals(SetUtils.asSet("论坛", "蔬菜"), sensitiveWordService.getSensitiveWordTagSet());  
102 - // 断言 sensitiveWordCache  
103 - assertEquals(2, sensitiveWordService.getSensitiveWordCache().size());  
104 - assertPojoEquals(wordDO1, sensitiveWordService.getSensitiveWordCache().get(0));  
105 - assertPojoEquals(wordDO2, sensitiveWordService.getSensitiveWordCache().get(1));  
106 - // 断言 tagSensitiveWordTries 缓存  
107 - assertNotNull(sensitiveWordService.getDefaultSensitiveWordTrie());  
108 - assertEquals(2, sensitiveWordService.getTagSensitiveWordTries().size());  
109 - assertNotNull(sensitiveWordService.getTagSensitiveWordTries().get("论坛"));  
110 - assertNotNull(sensitiveWordService.getTagSensitiveWordTries().get("蔬菜"));  
111 - }  
112 -  
113 - @Test  
114 - public void testCreateSensitiveWord_success() {  
115 - // 准备参数  
116 - SensitiveWordSaveVO reqVO = randomPojo(SensitiveWordSaveVO.class)  
117 - .setId(null); // 防止 id 被赋值  
118 -  
119 - // 调用  
120 - Long sensitiveWordId = sensitiveWordService.createSensitiveWord(reqVO);  
121 - // 断言  
122 - assertNotNull(sensitiveWordId);  
123 - // 校验记录的属性是否正确  
124 - SensitiveWordDO sensitiveWord = sensitiveWordMapper.selectById(sensitiveWordId);  
125 - assertPojoEquals(reqVO, sensitiveWord, "id");  
126 - }  
127 -  
128 - @Test  
129 - public void testUpdateSensitiveWord_success() {  
130 - // mock 数据  
131 - SensitiveWordDO dbSensitiveWord = randomPojo(SensitiveWordDO.class);  
132 - sensitiveWordMapper.insert(dbSensitiveWord);// @Sql: 先插入出一条存在的数据  
133 - // 准备参数  
134 - SensitiveWordSaveVO reqVO = randomPojo(SensitiveWordSaveVO.class, o -> {  
135 - o.setId(dbSensitiveWord.getId()); // 设置更新的 ID  
136 - });  
137 -  
138 - // 调用  
139 - sensitiveWordService.updateSensitiveWord(reqVO);  
140 - // 校验是否更新正确  
141 - SensitiveWordDO sensitiveWord = sensitiveWordMapper.selectById(reqVO.getId()); // 获取最新的  
142 - assertPojoEquals(reqVO, sensitiveWord);  
143 - }  
144 -  
145 - @Test  
146 - public void testUpdateSensitiveWord_notExists() {  
147 - // 准备参数  
148 - SensitiveWordSaveVO reqVO = randomPojo(SensitiveWordSaveVO.class);  
149 -  
150 - // 调用, 并断言异常  
151 - assertServiceException(() -> sensitiveWordService.updateSensitiveWord(reqVO), SENSITIVE_WORD_NOT_EXISTS);  
152 - }  
153 -  
154 - @Test  
155 - public void testDeleteSensitiveWord_success() {  
156 - // mock 数据  
157 - SensitiveWordDO dbSensitiveWord = randomPojo(SensitiveWordDO.class);  
158 - sensitiveWordMapper.insert(dbSensitiveWord);// @Sql: 先插入出一条存在的数据  
159 - // 准备参数  
160 - Long id = dbSensitiveWord.getId();  
161 -  
162 - // 调用  
163 - sensitiveWordService.deleteSensitiveWord(id);  
164 - // 校验数据不存在了  
165 - assertNull(sensitiveWordMapper.selectById(id));  
166 - }  
167 -  
168 - @Test  
169 - public void testDeleteSensitiveWord_notExists() {  
170 - // 准备参数  
171 - Long id = randomLongId();  
172 -  
173 - // 调用, 并断言异常  
174 - assertServiceException(() -> sensitiveWordService.deleteSensitiveWord(id), SENSITIVE_WORD_NOT_EXISTS);  
175 - }  
176 -  
177 - @Test  
178 - public void testGetSensitiveWord() {  
179 - // mock 数据  
180 - SensitiveWordDO sensitiveWord = randomPojo(SensitiveWordDO.class);  
181 - sensitiveWordMapper.insert(sensitiveWord);  
182 - // 准备参数  
183 - Long id = sensitiveWord.getId();  
184 -  
185 - // 调用  
186 - SensitiveWordDO dbSensitiveWord = sensitiveWordService.getSensitiveWord(id);  
187 - // 断言  
188 - assertPojoEquals(sensitiveWord, dbSensitiveWord);  
189 - }  
190 -  
191 - @Test  
192 - public void testGetSensitiveWordList() {  
193 - // mock 数据  
194 - SensitiveWordDO sensitiveWord01 = randomPojo(SensitiveWordDO.class);  
195 - sensitiveWordMapper.insert(sensitiveWord01);  
196 - SensitiveWordDO sensitiveWord02 = randomPojo(SensitiveWordDO.class);  
197 - sensitiveWordMapper.insert(sensitiveWord02);  
198 -  
199 - // 调用  
200 - List<SensitiveWordDO> list = sensitiveWordService.getSensitiveWordList();  
201 - // 断言  
202 - assertEquals(2, list.size());  
203 - assertEquals(sensitiveWord01, list.get(0));  
204 - assertEquals(sensitiveWord02, list.get(1));  
205 - }  
206 -  
207 - @Test  
208 - public void testGetSensitiveWordPage() {  
209 - // mock 数据  
210 - SensitiveWordDO dbSensitiveWord = randomPojo(SensitiveWordDO.class, o -> { // 等会查询到  
211 - o.setName("笨蛋");  
212 - o.setTags(Arrays.asList("论坛", "蔬菜"));  
213 - o.setStatus(CommonStatusEnum.ENABLE.getStatus());  
214 - o.setCreateTime(buildTime(2022, 2, 8));  
215 - });  
216 - sensitiveWordMapper.insert(dbSensitiveWord);  
217 - // 测试 name 不匹配  
218 - sensitiveWordMapper.insert(cloneIgnoreId(dbSensitiveWord, o -> o.setName("傻瓜")));  
219 - // 测试 tags 不匹配  
220 - sensitiveWordMapper.insert(cloneIgnoreId(dbSensitiveWord, o -> o.setTags(Arrays.asList("短信", "日用品"))));  
221 - // 测试 createTime 不匹配  
222 - sensitiveWordMapper.insert(cloneIgnoreId(dbSensitiveWord, o -> o.setCreateTime(buildTime(2022, 2, 16))));  
223 - // 准备参数  
224 - SensitiveWordPageReqVO reqVO = new SensitiveWordPageReqVO();  
225 - reqVO.setName("笨");  
226 - reqVO.setTag("论坛");  
227 - reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());  
228 - reqVO.setCreateTime(buildBetweenTime(2022, 2, 1, 2022, 2, 12));  
229 -  
230 - // 调用  
231 - PageResult<SensitiveWordDO> pageResult = sensitiveWordService.getSensitiveWordPage(reqVO);  
232 - // 断言  
233 - assertEquals(1, pageResult.getTotal());  
234 - assertEquals(1, pageResult.getList().size());  
235 - assertPojoEquals(dbSensitiveWord, pageResult.getList().get(0));  
236 - }  
237 -  
238 - @Test  
239 - public void testValidateText_noTag() {  
240 - testInitLocalCache();  
241 - // 准备参数  
242 - String text = "你是傻瓜,你是笨蛋";  
243 - // 调用  
244 - List<String> result = sensitiveWordService.validateText(text, null);  
245 - // 断言  
246 - assertEquals(Arrays.asList("傻瓜", "笨蛋"), result);  
247 -  
248 - // 准备参数  
249 - String text2 = "你是傻瓜,你是笨蛋,你是白";  
250 - // 调用  
251 - List<String> result2 = sensitiveWordService.validateText(text2, null);  
252 - // 断言  
253 - assertEquals(Arrays.asList("傻瓜", "笨蛋","白"), result2);  
254 - }  
255 -  
256 - @Test  
257 - public void testValidateText_hasTag() {  
258 - testInitLocalCache();  
259 - // 准备参数  
260 - String text = "你是傻瓜,你是笨蛋";  
261 - // 调用  
262 - List<String> result = sensitiveWordService.validateText(text, singletonList("论坛"));  
263 - // 断言  
264 - assertEquals(singletonList("傻瓜"), result);  
265 -  
266 -  
267 - // 准备参数  
268 - String text2 = "你是白";  
269 - // 调用  
270 - List<String> result2 = sensitiveWordService.validateText(text2, singletonList("测试"));  
271 - // 断言  
272 - assertEquals(singletonList("白"), result2);  
273 - }  
274 -  
275 - @Test  
276 - public void testIsTestValid_noTag() {  
277 - testInitLocalCache();  
278 - // 准备参数  
279 - String text = "你是傻瓜,你是笨蛋";  
280 - // 调用,断言  
281 - assertFalse(sensitiveWordService.isTextValid(text, null));  
282 -  
283 - // 准备参数  
284 - String text2 = "你是白";  
285 - // 调用,断言  
286 - assertFalse(sensitiveWordService.isTextValid(text2, null));  
287 - }  
288 -  
289 - @Test  
290 - public void testIsTestValid_hasTag() {  
291 - testInitLocalCache();  
292 - // 准备参数  
293 - String text = "你是傻瓜,你是笨蛋";  
294 - // 调用,断言  
295 - assertFalse(sensitiveWordService.isTextValid(text, singletonList("论坛")));  
296 -  
297 - // 准备参数  
298 - String text2 = "你是白";  
299 - // 调用,断言  
300 - assertFalse(sensitiveWordService.isTextValid(text2, singletonList("测试")));  
301 - }  
302 -  
303 -}  
yudao-module-system/yudao-module-system-biz/src/test/resources/sql/clean.sql
@@ -21,7 +21,6 @@ DELETE FROM &quot;system_social_user&quot;; @@ -21,7 +21,6 @@ DELETE FROM &quot;system_social_user&quot;;
21 DELETE FROM "system_social_user_bind"; 21 DELETE FROM "system_social_user_bind";
22 DELETE FROM "system_tenant"; 22 DELETE FROM "system_tenant";
23 DELETE FROM "system_tenant_package"; 23 DELETE FROM "system_tenant_package";
24 -DELETE FROM "system_sensitive_word";  
25 DELETE FROM "system_oauth2_client"; 24 DELETE FROM "system_oauth2_client";
26 DELETE FROM "system_oauth2_approve"; 25 DELETE FROM "system_oauth2_approve";
27 DELETE FROM "system_oauth2_access_token"; 26 DELETE FROM "system_oauth2_access_token";
yudao-module-system/yudao-module-system-biz/src/test/resources/sql/create_tables.sql
@@ -416,20 +416,6 @@ CREATE TABLE IF NOT EXISTS &quot;system_tenant_package&quot; ( @@ -416,20 +416,6 @@ CREATE TABLE IF NOT EXISTS &quot;system_tenant_package&quot; (
416 PRIMARY KEY ("id") 416 PRIMARY KEY ("id")
417 ) COMMENT '租户套餐表'; 417 ) COMMENT '租户套餐表';
418 418
419 -CREATE TABLE IF NOT EXISTS "system_sensitive_word" (  
420 - "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,  
421 - "name" varchar(255) NOT NULL,  
422 - "tags" varchar(1024) NOT NULL,  
423 - "status" bit NOT NULL DEFAULT FALSE,  
424 - "description" varchar(512),  
425 - "creator" varchar(64) DEFAULT '',  
426 - "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,  
427 - "updater" varchar(64) DEFAULT '',  
428 - "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,  
429 - "deleted" bit NOT NULL DEFAULT FALSE,  
430 - PRIMARY KEY ("id")  
431 -) COMMENT '系统敏感词';  
432 -  
433 CREATE TABLE IF NOT EXISTS "system_oauth2_client" ( 419 CREATE TABLE IF NOT EXISTS "system_oauth2_client" (
434 "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, 420 "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
435 "client_id" varchar NOT NULL, 421 "client_id" varchar NOT NULL,
yudao-server/src/main/resources/application-local.yaml
@@ -170,7 +170,6 @@ logging: @@ -170,7 +170,6 @@ logging:
170 cn.iocoder.yudao.module.pay.dal.mysql: debug 170 cn.iocoder.yudao.module.pay.dal.mysql: debug
171 cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyTaskMapper: INFO # 配置 JobLogMapper 的日志级别为 info 171 cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyTaskMapper: INFO # 配置 JobLogMapper 的日志级别为 info
172 cn.iocoder.yudao.module.system.dal.mysql: debug 172 cn.iocoder.yudao.module.system.dal.mysql: debug
173 - cn.iocoder.yudao.module.system.dal.mysql.sensitiveword.SensitiveWordMapper: INFO # 配置 SensitiveWordMapper 的日志级别为 info  
174 cn.iocoder.yudao.module.system.dal.mysql.sms.SmsChannelMapper: INFO # 配置 SmsChannelMapper 的日志级别为 info 173 cn.iocoder.yudao.module.system.dal.mysql.sms.SmsChannelMapper: INFO # 配置 SmsChannelMapper 的日志级别为 info
175 cn.iocoder.yudao.module.tool.dal.mysql: debug 174 cn.iocoder.yudao.module.tool.dal.mysql: debug
176 cn.iocoder.yudao.module.member.dal.mysql: debug 175 cn.iocoder.yudao.module.member.dal.mysql: debug