美文网首页
soul从入门到放弃8--自定义单一职责插件

soul从入门到放弃8--自定义单一职责插件

作者: 滴流乱转的小胖子 | 来源:发表于2021-01-23 06:36 被阅读0次

一、前戏-- 功能需求

通过上一篇对soul插件链的整体概览学习,本篇开始“生搬硬套”,尽量符合soul的编码方式实现一个自定义单一职责插件。

需求:实现一个参数验签的插件,验签失败中断调用链调用直接返回错误信息,否则执行剩下调用链。

二、自定义插件类

  • 在soul-plugin项目下,新建一个子模块soul-plugin-customsign。创建SoulPlugin接口的实现类CustomSignPlugin。
  • 实现SoulPlugin接口定义方法,各方法职责如下:

execute() 方法为核心的执行方法,用户可以在里面自由的实现自己想要的功能。

getOrder() 指定插件的排序。

named() 指定插件的名称。

skip() 在特定的条件下,该插件是否被跳过。

此处附上一个小demo:

@Slf4j
public class CustomSignPlugin implements SoulPlugin {
    /**
     * 加密私钥
     */
    private String privateKey = "CDRjzk2sb99v6nUkXx8+6g";

    @Override
    public String named() {
        return PluginEnum.CUSTOMSIGN.getName();
    }
    @Override
    public Boolean skip(final ServerWebExchange exchange) {
        final SoulContext soulContext = exchange.getAttribute(Constants.CONTEXT);
        return !Objects.equals(Objects.requireNonNull(soulContext).getRpcType(), RpcTypeEnum.HTTP.getName());
    }
    @Override
    public Mono<Void> execute(ServerWebExchange exchange, SoulPluginChain chain) {
        final SoulContext soulContext = exchange.getAttribute(Constants.CONTEXT);
        String queryParam = exchange.getRequest().getURI().getQuery();
        if (StringUtils.isNotBlank(queryParam)) {
            if(!checkSignature(exchange.getRequest())) {
                log.error("接口请求验签失败");
                Object error = SoulResultWrap.error(SoulResultEnum.CHECK_CUSTOM_SIGN_EXCEPTION.getCode(), SoulResultEnum.CHECK_CUSTOM_SIGN_EXCEPTION.getMsg(), null);
                return WebFluxResultUtils.result(exchange, error);
            }
        }
        return chain.execute(exchange);
    }

    private boolean checkSignature(ServerHttpRequest request) {
        Map<String, String> map = request.getQueryParams().toSingleValueMap();
        String signReq = map.containsKey("sign")? map.get("sign").toString() : null;;
        boolean checkSignture = false;
        //验证签名
        if (map.size() > 0 && StringUtils.isNotBlank(signReq)) {
            //签名匹配,则签名认证通过
            map.remove("sign");
            if (signReq.equals(Signature.getSign(map, privateKey))
                || signReq.equalsIgnoreCase(Signature.getSign(map, privateKey))) {
                checkSignture = true;
            }
        } else {
            // 不传签名,非法强求
            checkSignture = false;
        }
        return checkSignture;
    }

    @Override
    public int getOrder() {
        return PluginEnum.CUSTOMSIGN.getCode();
    }
  • soul-plugin-customsign目录结构如下:
image.png
  • 调整pom, install 本地仓库,待引用

三、设置插件执行顺序

在PluginEnum类中创建,自定义插件的执行顺序,名字等信息。

ps:1.枚举中code定义相对松散,这个间隔目前怀疑是为了便于“渗入”新插件

image.png

2.枚举类中的name一定要定义好且具有唯一性,后文配置中还会用到

四、设置异常

SoulResultEnum类中定义统一错误异常码,此处建议使用英文,此处用中文作以区分。

image.png

五、封装spring-starter

  • 在soul-spring-boot-starter-plugin项目下,创建子模块soul-spring-boot-starter-plugin-customsign
  • 引入自定义插件依赖
<dependency>
    <groupId>org.dromara</groupId>
    <artifactId>soul-plugin-customsign</artifactId>
    <version>${project.version}</version>
</dependency>
  • 此类只是对做一个简单的spring-starter封装,封装一个CustomSignPluginConfiguration
@Configuration
public class CustomSignPluginConfiguration {
    /**
     * init SoulPlugin.
     *
     * @return {@linkplain SoulPlugin}
     */
    @Bean
    public SoulPlugin customSignPlugin() {
        return new CustomSignPlugin();
    }
}
  • 当然不要忘记加上加载bean的配偶spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.dromara.soul.spring.boot.plugin.divide.DividePluginConfiguration
  • 整体目录结构如下
image.png

六、soul-bootstrap的配置

此处配置就“过于”简单,只需要引入maven依赖即可,体现出作者对代码的高内聚、低耦合了,nice!

<pre><dependency>
<groupId>org.dromara</groupId>
<artifactId>soul-spring-boot-starter-plugin-customsign</artifactId>
<version>${project.version}</version>
</dependency></pre>

七、配置插件信息

  • 整体项目mvn一下
mvn  clean package install -Dmaven.test.skip=true -Dmaven.javadoc.skip=true -Drat.skip=true -Dcheckstyle.skip=true
  • 插件管理中配置插件信息,此处插件名正式前文PluginEnum中定义name,一定保持一致否则插件链初始化将失败,惨痛浪费15分钟调试经验。
image.png

八、测试

  • 分别启动soul-bootstrap、soul-plugin-customsign测试一下
image.png

一发入魂,搞定! 收拾收拾可以再睡一会了。

九、小结

  • 知易行难:感觉自己捋清了调用链,实现一个自定义插件应该还算easy。实际操作起来,其实~~~~我还是很菜啊!
  • 回顾整个实现流程,确实很精巧。热插拔的插件链,确实很精巧,原有代码基本不需要改动,确实高内聚低耦合。确实很精巧!!!
  • 日拱一卒,每天进步一点点

相关文章

网友评论

      本文标题:soul从入门到放弃8--自定义单一职责插件

      本文链接:https://www.haomeiwen.com/subject/fmsyzktx.html