soul從入門到放棄8--自定義單一職責插件

一、前戲-- 功能需求

通過上一篇對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。實際操作起來,其實~~~~我還是很菜啊!
  • 回顧整個實現流程,確實很精巧。熱插拔的插件鏈,確實很精巧,原有代碼基本不需要改動,確實高內聚低耦合。確實很精巧!!!
  • 日拱一卒,每天進步一點點
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容