关于java:java-如何实现开箱即用的敏感词控台服务

6次阅读

共计 5519 个字符,预计需要花费 14 分钟才能阅读完成。

sensitive-word-admin

sensitive-word-admin 是基于 sensitive-word 实现的,
一款开箱即用的敏感词控台服务。

个性

  • 根本的 CRUD
  • 开箱即用的配置控台
  • 简略易用的 API 服务

变更日志

疾速开始

数据库脚本

执行 mysql-5.7.sql 脚本。

外围表如下:

create table word
(
    id int unsigned auto_increment comment '利用自增主键' primary key,
    word varchar(128) not null comment '单词',
    type varchar(8) not null comment '类型',
    status char(1) not null default 'S' comment '状态',
    remark varchar(64) not null comment '配置形容' default '',
    operator_id varchar(64) not null default 'system' comment '操作员名称',
    create_time timestamp default CURRENT_TIMESTAMP not null comment '创立工夫戳',
    update_time timestamp default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新工夫戳'
) comment '敏感词表' ENGINE=Innodb default charset=UTF8 auto_increment=1;
create unique index uk_word on word (word) comment '惟一索引';

利用启动

间接运行 Applicaiton#main() 启动利用,启动日志如下:

2021-07-20 20:56:48.200  INFO [] 6680 --- [           main] o.a.coyote.http11.Http11NioProtocol      : Starting ProtocolHandler ["http-nio-8080"]
2021-07-20 20:56:48.219  INFO [] 6680 --- [           main] o.a.tomcat.util.net.NioSelectorPool      : Using a shared selector for servlet write/read
2021-07-20 20:56:48.248  INFO [] 6680 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2021-07-20 20:56:48.256  INFO [] 6680 --- [           main] c.g.h.sensitive.word.admin.Application   : Started Application in 14.04 seconds (JVM running for 15.82)

敏感词配置

除了 sensitive-word 自身自带的敏感词外,咱们能够依据本人的业务进行配置。

类型分为两种:禁止和容许。禁止阐明是敏感词,容许阐明不认为是敏感词。

所有的类型,只有在状态为失常的状况下才会失效。

测试验证

contains

是否蕴含敏感词。

http://localhost:8080/api/sensitiveWord/contains?text= 凡凡做测试

返回:

{"respCode":"0000","respMessage":"胜利","result":true}

findAll

找到所有的敏感词。

http://localhost:8080/api/sensitiveWord/findAll?text= 凡凡做测试

返回:

{"respCode":"0000","respMessage":"胜利","total":2,"list":["凡凡","测试"]}

replace

替换对应的敏感词。

http://localhost:8080/api/sensitiveWord/replace?text= 凡凡做测试

返回:

{"respCode":"0000","respMessage":"胜利","result":"** 做 **"}

所有的后果能够依据控台更改,实时失效。

实现原理

底层依赖

依赖 https://github.com/houbb/sensitive-word 提供的敏感词工具。

因为原来的工具只有一些最根本的性能,无奈依据配置动态变化,不符合实际利用场景。

所以在原有的根底上实现了一个开箱即用的控台,并且提供了简略的 API。

对于敏感词工具自身,本篇不做介绍,举荐浏览:

敏感词应用入门介绍

技术选型

springboot

mybatis-plus

vue

基于数据库的敏感词

自定义的敏感词相干数据存储在数据库,对应的定义如下:

/**
 * 自定义敏感词
 * 
 * @author 老马啸东风
 * @since 1.1.0
 */
@Component
public class MyDdWordDeny implements IWordDeny {

    @Autowired
    private WordService wordService;

    @Override
    public List<String> deny() {Wrapper<Word> wordWrapper = new EntityWrapper<>();
        wordWrapper.eq("type", WordTypeEnum.DENY.getCode());
        wordWrapper.eq("status", WordStatusEnum.S.getCode());

        List<Word> wordList = wordService.selectList(wordWrapper);

        return CollectionUtil.toList(wordList, new IHandler<Word, String>() {
            @Override
            public String handle(Word word) {return word.getWord();
            }
        });
    }

}

/**
 * 自定义白名单
 * 
 * @author 老马啸东风
 * @since 1.1.0
 */
@Component
public class MyDdWordAllow implements IWordAllow {

    @Autowired
    private WordService wordService;

    @Override
    public List<String> allow() {Wrapper<Word> wordWrapper = new EntityWrapper<>();
        wordWrapper.eq("type", WordTypeEnum.ALLOW.getCode());
        wordWrapper.eq("status", WordStatusEnum.S.getCode());

        List<Word> wordList = wordService.selectList(wordWrapper);

        return CollectionUtil.toList(wordList, new IHandler<Word, String>() {
            @Override
            public String handle(Word word) {return word.getWord();
            }
        });
    }

}

敏感词疏导类初始化

对应的敏感类初始化也比较简单,咱们在零碎默认的根底上,增加上自定义的数据。

@Configuration
public class SensitiveWordConfig {

    @Autowired
    private MyDdWordAllow myDdWordAllow;

    @Autowired
    private MyDdWordDeny myDdWordDeny;

    /**
     * 初始化疏导类
     * @return 初始化疏导类
     * @since 1.0.0
     */
    @Bean
    public SensitiveWordBs sensitiveWordBs() {return SensitiveWordBs.newInstance()
                .wordAllow(WordAllows.chains(WordAllows.system(), myDdWordAllow))
                .wordDeny(WordDenys.chains(WordDenys.system(), myDdWordDeny))
                .ignoreRepeat(false)
                // 各种其余配置
                .init();}

}

配置变更及敏感词刷新

每一次敏感词配置产生变更的时候,咱们都被动刷新一下敏感词词典信息。

/**
 * <p>
 * 敏感词表 前端控制器
 * </p>
 *
 * @author 老马啸东风
 * @since 2021-07-07
 */
@Controller
@RequestMapping("/word")
@TraceId
@AutoLog
public class WordController {

    @Autowired
    private WordService wordService;

    @Autowired
    private SensitiveWordBs sensitiveWordBs;

    /**
    * 首页
    */
    @RequestMapping("/index")
    public String index() {return "word/index";}

    /**
    * 增加元素
    * @param entity 实体
    * @return 后果
    */
    @RequestMapping("/add")
    @ResponseBody
    public BaseResp add(@RequestBody final Word entity) {wordService.insert(entity);

        refreshSensitiveWord();
        return RespUtil.success();}

    /**
    * 编辑
    * @param entity 实体
    * @return 后果
    */
    @RequestMapping("/edit")
    @ResponseBody
    public BaseResp edit(final Word entity) {wordService.updateById(entity);

        refreshSensitiveWord();
        return RespUtil.success();}

    /**
    * 删除
    * @param id 实体
    * @return 后果
    */
    @RequestMapping("/remove/{id}")
    @ResponseBody
    public BaseResp remove(@PathVariable final Integer id) {wordService.deleteById(id);

        refreshSensitiveWord();
        return RespUtil.success();}

    /**
     * 刷新敏感詞
     *
     * 能够优化为异步,甚至批量。* @since 1.1.0
     */
    private void refreshSensitiveWord() {sensitiveWordBs.init();
    }

}

提供对外接口

这里提供的接口仅当做演示:

/**
 * api 服务
 * @author 老马啸东风
 * @since 1.1.0
 */
@RestController
@RequestMapping("/api/sensitiveWord/")
@AutoLog
@TraceId
public class ApiSensitiveWordController {

    @Autowired
    private SensitiveWordBs sensitiveWordBs;

    /**
     * 是否蕴含敏感词
     *
     * @param text 文本
     * @return 后果
     */
    @RequestMapping("/contains")
    public BaseResp contains(@RequestParam("text") String text) {boolean contains = sensitiveWordBs.contains(text);

        return RespUtil.of(contains);
    }

    /**
     * 获取所有的敏感词
     * @param text 文本
     * @return 后果
     */
    @RequestMapping("/findAll")
    public BaseResp findAll(@RequestParam("text") String text) {List<String> results = sensitiveWordBs.findAll(text);

        return RespUtil.of(results);
    }

    /**
     * 获取替换后的后果
     *
     * @param text 文本
     * @return 后果
     */
    @RequestMapping("/replace")
    public BaseResp replace(@RequestParam("text") String text) {String results = sensitiveWordBs.replace(text);

        return RespUtil.of(results);
    }

}

如果理论咱们真的对外部提供服务,必定要比这个简单的多,如果要思考平安相干问题。

举荐浏览:

如何从零实现属于本人的 API 网关?

你连对外接口签名都不会晓得?有工夫还是要学习学习

和你一起走进对称加密算法的世界

springboot 实现拦截器的 3 种形式介绍

小结

敏感词的利用十分宽泛,任何波及到用户能够自在发言的中央,就须要思考敏感词。

本文次要是为了演示如何基于 sensitive-word 实现一个开箱即用的敏感词服务,心愿对你有所帮忙。

我是老马,期待与你的下次重逢。

备注:波及的代码较多,文中做了简化。若你对源码感兴趣,能够關註 {老马啸东风},後臺回復{敏感词} 即可取得。

正文完
 0