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 115 ErrorCode TENANT_PACKAGE_USED = new ErrorCode(1_002_016_001, "租户正在使用该套餐,请给租户重新设置套餐后再尝试删除");
116 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 118 // ========== 社交用户 1-002-018-000 ==========
123 119 ErrorCode SOCIAL_USER_AUTH_FAILURE = new ErrorCode(1_002_018_000, "社交授权失败,原因是:{}");
124 120 ErrorCode SOCIAL_USER_NOT_FOUND = new ErrorCode(1_002_018_001, "社交授权失败,找不到对应的用户");
... ... @@ -127,10 +123,6 @@ public interface ErrorCodeConstants {
127 123 ErrorCode SOCIAL_CLIENT_NOT_EXISTS = new ErrorCode(1_002_018_201, "社交客户端不存在");
128 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 126 // ========== OAuth2 客户端 1-002-020-000 =========
135 127 ErrorCode OAUTH2_CLIENT_NOT_EXISTS = new ErrorCode(1_002_020_000, "OAuth2 客户端不存在");
136 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 21 DELETE FROM "system_social_user_bind";
22 22 DELETE FROM "system_tenant";
23 23 DELETE FROM "system_tenant_package";
24   -DELETE FROM "system_sensitive_word";
25 24 DELETE FROM "system_oauth2_client";
26 25 DELETE FROM "system_oauth2_approve";
27 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 416 PRIMARY KEY ("id")
417 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 419 CREATE TABLE IF NOT EXISTS "system_oauth2_client" (
434 420 "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
435 421 "client_id" varchar NOT NULL,
... ...
yudao-server/src/main/resources/application-local.yaml
... ... @@ -170,7 +170,6 @@ logging:
170 170 cn.iocoder.yudao.module.pay.dal.mysql: debug
171 171 cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyTaskMapper: INFO # 配置 JobLogMapper 的日志级别为 info
172 172 cn.iocoder.yudao.module.system.dal.mysql: debug
173   - cn.iocoder.yudao.module.system.dal.mysql.sensitiveword.SensitiveWordMapper: INFO # 配置 SensitiveWordMapper 的日志级别为 info
174 173 cn.iocoder.yudao.module.system.dal.mysql.sms.SmsChannelMapper: INFO # 配置 SmsChannelMapper 的日志级别为 info
175 174 cn.iocoder.yudao.module.tool.dal.mysql: debug
176 175 cn.iocoder.yudao.module.member.dal.mysql: debug
... ...