This is an automated email from the ASF dual-hosted git repository.

xiaoyu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git


The following commit(s) were added to refs/heads/master by this push:
     new ab1275326 [type:refactor] refactor logging plugin (#4032)
ab1275326 is described below

commit ab12753267ce6f9f979464181f6909bb693e2873
Author: moremind <[email protected]>
AuthorDate: Mon Oct 3 19:09:20 2022 +0800

    [type:refactor] refactor logging plugin (#4032)
    
    * [ISSUE #3964] fix logging module sql error
    
    * refactor log module
    
    * refactor log module
    
    * refactor log module
    
    * refactor log module
    
    * refactor log module
    
    * fix check style
    
    * fix check style
    
    * fix check style
    
    * fix check style
    
    * rename module
---
 shenyu-plugin/shenyu-plugin-logging/pom.xml        |  1 +
 .../shenyu-plugin-logging-aliyun-sls/pom.xml       |  2 -
 .../shenyu-plugin-logging-common/pom.xml           |  2 +-
 .../logging/common/AbstractLoggingPlugin.java      | 47 ++++++-----
 .../common/body/LoggingServerHttpResponse.java     | 46 ++++-------
 .../common/constant/GenericLoggingConstant.java    |  2 +-
 .../common/entity/CommonLoggingRuleHandle.java     | 94 ++++++++++++++++++++++
 .../handler/AbstractLogPluginDataHandler.java      | 22 +++++
 .../common/body/LoggingServerHttpResponseTest.java |  5 +-
 .../logging/console/LoggingConsolePlugin.java      | 94 ++++++++++------------
 .../handler/LoggingConsolePluginDataHandler.java   | 56 +++++++++++++
 .../pom.xml                                        | 19 ++---
 .../plugin/logging/mask/enums/DataMaskEnums.java}  | 36 ++++-----
 .../logging/mask/factory/DataMaskFactory.java}     | 22 +++--
 .../plugin/logging/mask/matcher}/KeyWordMatch.java |  6 +-
 .../logging/mask/spi/AbstractShenyuDataMask.java}  | 22 +++--
 .../mask/spi/CharacterReplaceDataMask.java}        | 23 +++---
 .../logging/mask/spi/Md5EncryptDataMask.java}      | 21 +++--
 .../plugin/logging/mask/spi/ShenyuDataMask.java}   | 13 +--
 .../plugin/logging/mask/utils/DataMaskUtils.java   | 94 ++++++++++++++++++++++
 ...e.shenyu.plugin.logging.mask.spi.ShenyuDataMask | 18 +++++
 .../logging/mask/factory/DataMaskFactoryTest.java} | 39 ++++-----
 .../logging/mask/matcher}/KeyWordMatchTest.java    | 11 +--
 .../mask/spi/CharacterReplaceDataMaskTest.java}    | 35 ++++----
 .../logging/mask/spi/Md5EncryptDataMaskTest.java}  | 26 ++----
 .../logging/mask/utils/DataMaskUtilsTest.java      | 84 +++++++++++++++++++
 .../console/LoggingConsolePluginConfiguration.java | 12 +++
 27 files changed, 600 insertions(+), 252 deletions(-)

diff --git a/shenyu-plugin/shenyu-plugin-logging/pom.xml 
b/shenyu-plugin/shenyu-plugin-logging/pom.xml
index 9307776bd..527acb086 100644
--- a/shenyu-plugin/shenyu-plugin-logging/pom.xml
+++ b/shenyu-plugin/shenyu-plugin-logging/pom.xml
@@ -36,5 +36,6 @@
         <module>shenyu-plugin-logging-pulsar</module>
         <module>shenyu-plugin-logging-tencent-cls</module>
         <module>shenyu-plugin-logging-clickhouse</module>
+        <module>shenyu-plugin-logging-mask-api</module>
     </modules>
 </project>
\ No newline at end of file
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-aliyun-sls/pom.xml 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-aliyun-sls/pom.xml
index 1cc66e1db..8eef76a6b 100644
--- 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-aliyun-sls/pom.xml
+++ 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-aliyun-sls/pom.xml
@@ -26,8 +26,6 @@
     <artifactId>shenyu-plugin-logging-aliyun-sls</artifactId>
 
     <properties>
-        <maven.compiler.source>8</maven.compiler.source>
-        <maven.compiler.target>8</maven.compiler.target>
         <aliyun-log.version>0.6.70</aliyun-log.version>
         <protobuf-java.version>3.19.2</protobuf-java.version>
         <aliyun-log-producer.version>0.3.10</aliyun-log-producer.version>
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/pom.xml 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/pom.xml
index fbf927ea1..eec42ffd2 100644
--- a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/pom.xml
+++ b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/pom.xml
@@ -29,7 +29,7 @@
     <dependencies>
         <dependency>
             <groupId>org.apache.shenyu</groupId>
-            <artifactId>shenyu-plugin-base</artifactId>
+            <artifactId>shenyu-plugin-logging-mask-api</artifactId>
             <version>${project.version}</version>
         </dependency>
         <dependency>
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/AbstractLoggingPlugin.java
 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/AbstractLoggingPlugin.java
index 801c3d302..b2ea44b04 100644
--- 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/AbstractLoggingPlugin.java
+++ 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/AbstractLoggingPlugin.java
@@ -17,45 +17,45 @@
 
 package org.apache.shenyu.plugin.logging.common;
 
+import com.google.common.collect.Sets;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.shenyu.common.dto.RuleData;
 import org.apache.shenyu.common.dto.SelectorData;
 import org.apache.shenyu.common.enums.PluginEnum;
-import org.apache.shenyu.common.utils.JsonUtils;
 import org.apache.shenyu.plugin.api.ShenyuPluginChain;
-import org.apache.shenyu.plugin.api.utils.SpringBeanUtils;
 import org.apache.shenyu.plugin.base.AbstractShenyuPlugin;
+import org.apache.shenyu.plugin.base.utils.CacheKeyUtils;
 import org.apache.shenyu.plugin.base.utils.HostAddressUtils;
 import org.apache.shenyu.plugin.logging.common.body.LoggingServerHttpRequest;
 import org.apache.shenyu.plugin.logging.common.body.LoggingServerHttpResponse;
 import org.apache.shenyu.plugin.logging.common.collector.LogCollector;
-import org.apache.shenyu.plugin.logging.common.datamask.DataMaskInterface;
+import org.apache.shenyu.plugin.logging.common.entity.CommonLoggingRuleHandle;
 import org.apache.shenyu.plugin.logging.common.entity.ShenyuRequestLog;
+import 
org.apache.shenyu.plugin.logging.common.handler.AbstractLogPluginDataHandler;
 import org.apache.shenyu.plugin.logging.common.utils.LogCollectConfigUtils;
 import org.apache.shenyu.plugin.logging.common.utils.LogCollectUtils;
+import org.apache.shenyu.plugin.logging.mask.enums.DataMaskEnums;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.http.server.reactive.ServerHttpRequest;
 import org.springframework.web.server.ServerWebExchange;
 import reactor.core.publisher.Mono;
 
 import java.util.Collections;
-import java.util.HashSet;
-import java.util.Map;
+import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
 
-import static 
org.apache.shenyu.plugin.logging.common.constant.GenericLoggingConstant.HOST;
-import static 
org.apache.shenyu.plugin.logging.common.constant.GenericLoggingConstant.USER_AGENT;
+import org.apache.shenyu.plugin.logging.common.constant.GenericLoggingConstant;
 
 /**
  * abstract logging plugin.
  */
 public abstract class AbstractLoggingPlugin extends AbstractShenyuPlugin {
 
-    private static boolean maskFlag;
+    private static final Logger LOG = 
LoggerFactory.getLogger(AbstractLoggingPlugin.class);
 
-    private static Set<String> keyWordSet = new HashSet<>();
-
-    private static DataMaskInterface dataMaskInterface;
+    private static String dataMaskAlg;
 
     /**
      * LogCollector.
@@ -74,14 +74,17 @@ public abstract class AbstractLoggingPlugin extends 
AbstractShenyuPlugin {
     @Override
     public Mono<Void> doExecute(final ServerWebExchange exchange, final 
ShenyuPluginChain chain,
                                 final SelectorData selector, final RuleData 
rule) {
-
-        Map<String, String> handleMap = JsonUtils.jsonToMap(
-                Optional.ofNullable(rule).map(RuleData::getHandle).orElse(""), 
String.class);
-        String keyWords = handleMap.get("keyword");
-        maskFlag = StringUtils.isNotBlank(keyWords) && 
"true".equals(handleMap.get("maskStatus")) ? true : false;
-        if (maskFlag) {
-            Collections.addAll(keyWordSet, keyWords.split(";"));
-            dataMaskInterface = 
SpringBeanUtils.getInstance().getBean(handleMap.get("maskType"));
+        CommonLoggingRuleHandle commonLoggingRuleHandle = 
AbstractLogPluginDataHandler.CACHED_HANDLE.get().obtainHandle(CacheKeyUtils.INST.getKey(rule));
+        boolean masked = false;
+        Set<String> keywordSets = Sets.newHashSet();
+        if (Objects.nonNull(commonLoggingRuleHandle)) {
+            String keywords = commonLoggingRuleHandle.getKeyword();
+            masked = StringUtils.isNotBlank(keywords) && 
commonLoggingRuleHandle.getMaskStatus();
+            if (masked) {
+                Collections.addAll(keywordSets, keywords.split(";"));
+                dataMaskAlg = 
Optional.ofNullable(commonLoggingRuleHandle.getMaskType()).orElse(DataMaskEnums.MD5_ENCRYPT.getDataMaskAlg());
+                LOG.info("current plugin:{}, keyword:{}, dataMaskAlg:{}", 
pluginEnum().getName(), keywords, dataMaskAlg);
+            }
         }
         ServerHttpRequest request = exchange.getRequest();
         // control sampling
@@ -94,12 +97,12 @@ public abstract class AbstractLoggingPlugin extends 
AbstractShenyuPlugin {
         
requestInfo.setRequestHeader(LogCollectUtils.getHeaders(request.getHeaders()));
         requestInfo.setQueryParams(request.getURI().getQuery());
         requestInfo.setClientIp(HostAddressUtils.acquireIp(exchange));
-        requestInfo.setUserAgent(request.getHeaders().getFirst(USER_AGENT));
-        requestInfo.setHost(request.getHeaders().getFirst(HOST));
+        
requestInfo.setUserAgent(request.getHeaders().getFirst(GenericLoggingConstant.USER_AGENT));
+        
requestInfo.setHost(request.getHeaders().getFirst(GenericLoggingConstant.HOST));
         requestInfo.setPath(request.getURI().getPath());
         LoggingServerHttpRequest loggingServerHttpRequest = new 
LoggingServerHttpRequest(request, requestInfo);
         LoggingServerHttpResponse loggingServerHttpResponse = new 
LoggingServerHttpResponse(exchange.getResponse(),
-                requestInfo, this.logCollector(), maskFlag, keyWordSet, 
dataMaskInterface);
+                requestInfo, this.logCollector(), masked, keywordSets, 
dataMaskAlg);
         ServerWebExchange webExchange = 
exchange.mutate().request(loggingServerHttpRequest)
                 .response(loggingServerHttpResponse).build();
         loggingServerHttpResponse.setExchange(webExchange);
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/body/LoggingServerHttpResponse.java
 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/body/LoggingServerHttpResponse.java
index 97a99083c..8e70113c8 100644
--- 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/body/LoggingServerHttpResponse.java
+++ 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/body/LoggingServerHttpResponse.java
@@ -21,15 +21,14 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.shenyu.common.constant.Constants;
 import org.apache.shenyu.common.enums.RpcTypeEnum;
 import org.apache.shenyu.common.utils.DateUtils;
-import org.apache.shenyu.common.utils.JsonUtils;
 import org.apache.shenyu.plugin.api.context.ShenyuContext;
 import org.apache.shenyu.plugin.api.result.ShenyuResult;
 import org.apache.shenyu.plugin.api.result.ShenyuResultWrap;
 import org.apache.shenyu.plugin.logging.common.collector.LogCollector;
 import org.apache.shenyu.plugin.logging.common.constant.GenericLoggingConstant;
-import org.apache.shenyu.plugin.logging.common.datamask.DataMaskInterface;
-import org.apache.shenyu.plugin.logging.common.datamask.KeyWordMatch;
+import org.apache.shenyu.plugin.logging.mask.matcher.KeyWordMatch;
 import org.apache.shenyu.plugin.logging.common.entity.ShenyuRequestLog;
+import org.apache.shenyu.plugin.logging.mask.utils.DataMaskUtils;
 import org.apache.shenyu.plugin.logging.common.utils.LogCollectConfigUtils;
 import org.apache.shenyu.plugin.logging.common.utils.LogCollectUtils;
 import org.reactivestreams.Publisher;
@@ -51,7 +50,6 @@ import java.net.URL;
 import java.nio.charset.StandardCharsets;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
-import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 
@@ -72,29 +70,28 @@ public class LoggingServerHttpResponse extends 
ServerHttpResponseDecorator {
 
     private final boolean maskFlag;
 
-    private final DataMaskInterface dataMaskInterface;
+    private final String dataMaskAlg;
 
     private final KeyWordMatch keyWordMatch;
 
     /**
      * Constructor LoggingServerHttpResponse.
      *
-     * @param delegate          delegate ServerHttpResponse
-     * @param logInfo           access log
-     * @param logCollector      LogCollector  instance
-     * @param maskFlag          mask flag
-     * @param keyWordSet        user keyWord set
-     * @param dataMaskInterface mask function
+     * @param delegate delegate ServerHttpResponse
+     * @param logInfo access log
+     * @param logCollector LogCollector instance
+     * @param maskFlag mask flag
+     * @param keyWordSet user keyWord set
+     * @param dataMaskAlg mask function
      */
     public LoggingServerHttpResponse(final ServerHttpResponse delegate, final 
ShenyuRequestLog logInfo,
                                      final LogCollector logCollector, final 
boolean maskFlag,
-                                     final Set<String> keyWordSet, final 
DataMaskInterface dataMaskInterface) {
-
+                                     final Set<String> keyWordSet, final 
String dataMaskAlg) {
         super(delegate);
         this.logInfo = logInfo;
         this.logCollector = logCollector;
         this.maskFlag = maskFlag;
-        this.dataMaskInterface = dataMaskInterface;
+        this.dataMaskAlg = dataMaskAlg;
         this.keyWordMatch = new KeyWordMatch(keyWordSet);
     }
 
@@ -170,7 +167,7 @@ public class LoggingServerHttpResponse extends 
ServerHttpResponseDecorator {
             logInfo.setResponseBody(body);
         }
         if (maskFlag) {
-            mask(logInfo);
+            this.mask(logInfo);
         }
         // collect log
         if (Objects.nonNull(logCollector)) {
@@ -255,7 +252,7 @@ public class LoggingServerHttpResponse extends 
ServerHttpResponseDecorator {
             logInfo.setResponseBody(body);
         }
         if (maskFlag) {
-            mask(logInfo);
+            this.mask(logInfo);
         }
         // collect log
         if (Objects.nonNull(logCollector)) {
@@ -277,7 +274,6 @@ public class LoggingServerHttpResponse extends 
ServerHttpResponseDecorator {
     }
 
     private void mask(final ShenyuRequestLog logInfo) {
-
         logInfo.setClientIp(maskForSingle(GenericLoggingConstant.CLIENT_IP, 
logInfo.getClientIp()));
         logInfo.setTimeLocal(maskForSingle(GenericLoggingConstant.TIME_LOCAL, 
logInfo.getTimeLocal()));
         logInfo.setMethod(maskForSingle(GenericLoggingConstant.METHOD, 
logInfo.getMethod()));
@@ -308,22 +304,10 @@ public class LoggingServerHttpResponse extends 
ServerHttpResponseDecorator {
     }
 
     private String maskForSingle(final String keyWord, final String val) {
-
-        return StringUtils.isNotBlank(val) && keyWordMatch.matches(keyWord) ? 
dataMaskInterface.mask(val) : val;
+        return DataMaskUtils.maskSingleKeyword(maskFlag, keyWord, val, 
keyWordMatch, dataMaskAlg);
     }
 
     private String maskForBody(final String body) {
-
-        if (StringUtils.isNotBlank(body)) {
-            Map<String, String> bodyMap = JsonUtils.jsonToMap(body, 
String.class);
-            bodyMap.forEach((key, value) -> {
-                if (keyWordMatch.matches(key)) {
-                    bodyMap.put(key, dataMaskInterface.mask(value));
-                }
-            });
-            return bodyMap.toString();
-        } else {
-            return body;
-        }
+        return DataMaskUtils.maskBody(maskFlag, body, keyWordMatch, 
dataMaskAlg);
     }
 }
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/constant/GenericLoggingConstant.java
 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/constant/GenericLoggingConstant.java
index 47dfd3888..da5182700 100644
--- 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/constant/GenericLoggingConstant.java
+++ 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/constant/GenericLoggingConstant.java
@@ -75,7 +75,7 @@ public class GenericLoggingConstant {
     /**
      * logging request method.
      */
-    public static final String REQUEST_METHOD = "request method";
+    public static final String REQUEST_METHOD = "requestMethod";
 
     /**
      * logging request header.
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/entity/CommonLoggingRuleHandle.java
 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/entity/CommonLoggingRuleHandle.java
new file mode 100644
index 000000000..bb80c5305
--- /dev/null
+++ 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/entity/CommonLoggingRuleHandle.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.plugin.logging.common.entity;
+
+import org.apache.shenyu.common.dto.convert.rule.RuleHandle;
+
+/**
+ * common logging rule handle.
+ */
+public class CommonLoggingRuleHandle implements RuleHandle {
+
+    /**
+     * mask keyword.
+     */
+    private String keyword;
+
+    /**
+     * mask type, include md5 and character replacement.
+     */
+    private String maskType;
+
+    /**
+     * mask status, include true and false.
+     */
+    private Boolean maskStatus;
+
+    /**
+     * get keyword.
+     *
+     * @return keyword
+     */
+    public String getKeyword() {
+        return keyword;
+    }
+
+    /**
+     * set keyword.
+     * @param keyword keyword
+     */
+    public void setKeyword(final String keyword) {
+        this.keyword = keyword;
+    }
+
+    /**
+     * get mask type.
+     *
+     * @return mask type
+     */
+    public String getMaskType() {
+        return maskType;
+    }
+
+    /**
+     * set mask type.
+     *
+     * @param maskType mask type
+     */
+    public void setMaskType(final String maskType) {
+        this.maskType = maskType;
+    }
+
+    /**
+     * get mask status.
+     *
+     * @return mask status
+     */
+    public Boolean getMaskStatus() {
+        return maskStatus;
+    }
+
+    /**
+     * set mask status.
+     *
+     * @param maskStatus mask status
+     */
+    public void setMaskStatus(final Boolean maskStatus) {
+        this.maskStatus = maskStatus;
+    }
+}
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/handler/AbstractLogPluginDataHandler.java
 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/handler/AbstractLogPluginDataHandler.java
index 46c42b833..cd60f9024 100644
--- 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/handler/AbstractLogPluginDataHandler.java
+++ 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/handler/AbstractLogPluginDataHandler.java
@@ -21,14 +21,19 @@ import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.shenyu.common.dto.ConditionData;
 import org.apache.shenyu.common.dto.PluginData;
+import org.apache.shenyu.common.dto.RuleData;
 import org.apache.shenyu.common.dto.SelectorData;
 import org.apache.shenyu.common.enums.SelectorTypeEnum;
 import org.apache.shenyu.common.utils.GsonUtils;
 import org.apache.shenyu.common.utils.Singleton;
+import org.apache.shenyu.plugin.base.cache.CommonHandleCache;
 import org.apache.shenyu.plugin.base.handler.PluginDataHandler;
+import org.apache.shenyu.plugin.base.utils.BeanHolder;
+import org.apache.shenyu.plugin.base.utils.CacheKeyUtils;
 import org.apache.shenyu.plugin.logging.common.collector.LogCollector;
 import org.apache.shenyu.plugin.logging.common.config.GenericApiConfig;
 import org.apache.shenyu.plugin.logging.common.config.GenericGlobalConfig;
+import org.apache.shenyu.plugin.logging.common.entity.CommonLoggingRuleHandle;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -38,13 +43,17 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Supplier;
 
 /**
  * AbstractLogPluginDataHandler.
  */
 public abstract class AbstractLogPluginDataHandler<T extends 
GenericGlobalConfig, C extends GenericApiConfig> implements PluginDataHandler {
 
+    public static final Supplier<CommonHandleCache<String, 
CommonLoggingRuleHandle>> CACHED_HANDLE = new 
BeanHolder<>(CommonHandleCache::new);
+
     protected static final Logger LOG = 
LoggerFactory.getLogger(AbstractLogPluginDataHandler.class);
 
     private static final String EMPTY_JSON = "{}";
@@ -147,4 +156,17 @@ public abstract class AbstractLogPluginDataHandler<T 
extends GenericGlobalConfig
         SELECT_ID_URI_LIST_MAP.remove(selectorData.getId());
         SELECT_API_CONFIG_MAP.remove(selectorData.getId());
     }
+
+    @Override
+    public void handlerRule(final RuleData ruleData) {
+        Optional.ofNullable(ruleData.getHandle()).ifPresent(s -> {
+            CommonLoggingRuleHandle commonLoggingRuleHandle = 
GsonUtils.getInstance().fromJson(s, CommonLoggingRuleHandle.class);
+            
CACHED_HANDLE.get().cachedHandle(CacheKeyUtils.INST.getKey(ruleData), 
commonLoggingRuleHandle);
+        });
+    }
+
+    @Override
+    public void removeRule(final RuleData ruleData) {
+        Optional.ofNullable(ruleData.getHandle()).ifPresent(s -> 
CACHED_HANDLE.get().removeHandle(CacheKeyUtils.INST.getKey(ruleData)));
+    }
 }
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/test/java/org/apache/shenyu/plugin/logging/common/body/LoggingServerHttpResponseTest.java
 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/test/java/org/apache/shenyu/plugin/logging/common/body/LoggingServerHttpResponseTest.java
index 2bd07ddc3..b33a6b2e0 100644
--- 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/test/java/org/apache/shenyu/plugin/logging/common/body/LoggingServerHttpResponseTest.java
+++ 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/test/java/org/apache/shenyu/plugin/logging/common/body/LoggingServerHttpResponseTest.java
@@ -25,8 +25,6 @@ import org.apache.shenyu.plugin.api.utils.SpringBeanUtils;
 import org.apache.shenyu.plugin.base.utils.HostAddressUtils;
 import org.apache.shenyu.plugin.logging.common.collector.LogCollector;
 import org.apache.shenyu.plugin.logging.common.constant.GenericLoggingConstant;
-import org.apache.shenyu.plugin.logging.common.datamask.DataMaskByMD5;
-import org.apache.shenyu.plugin.logging.common.datamask.DataMaskInterface;
 import org.apache.shenyu.plugin.logging.common.entity.ShenyuRequestLog;
 import org.apache.shenyu.plugin.logging.common.utils.LogCollectUtils;
 import org.junit.jupiter.api.Assertions;
@@ -99,9 +97,8 @@ public class LoggingServerHttpResponseTest {
         
requestInfo.setHost(serverHttpRequest.getHeaders().getFirst(GenericLoggingConstant.HOST));
         requestInfo.setPath(serverHttpRequest.getURI().getPath());
         Set<String> keyWordSet = new HashSet<>();
-        DataMaskInterface dataMaskInterface = new DataMaskByMD5();
         this.loggingServerHttpResponse = new 
LoggingServerHttpResponse(exchange.getResponse(), requestInfo,
-                logCollector, false, keyWordSet, dataMaskInterface);
+                logCollector, false, keyWordSet, "dataMaskByCharReplace");
     }
 
     @Test
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-console/src/main/java/org/apache/shenyu/plugin/logging/console/LoggingConsolePlugin.java
 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-console/src/main/java/org/apache/shenyu/plugin/logging/console/LoggingConsolePlugin.java
index ac89c9195..10955569b 100644
--- 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-console/src/main/java/org/apache/shenyu/plugin/logging/console/LoggingConsolePlugin.java
+++ 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-console/src/main/java/org/apache/shenyu/plugin/logging/console/LoggingConsolePlugin.java
@@ -17,17 +17,21 @@
 
 package org.apache.shenyu.plugin.logging.console;
 
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.shenyu.common.dto.RuleData;
 import org.apache.shenyu.common.dto.SelectorData;
 import org.apache.shenyu.common.enums.PluginEnum;
-import org.apache.shenyu.common.utils.JsonUtils;
 import org.apache.shenyu.plugin.api.ShenyuPluginChain;
-import org.apache.shenyu.plugin.api.utils.SpringBeanUtils;
 import org.apache.shenyu.plugin.base.AbstractShenyuPlugin;
+import org.apache.shenyu.plugin.base.utils.CacheKeyUtils;
 import org.apache.shenyu.plugin.logging.common.constant.GenericLoggingConstant;
-import org.apache.shenyu.plugin.logging.common.datamask.DataMaskInterface;
-import org.apache.shenyu.plugin.logging.common.datamask.KeyWordMatch;
+import org.apache.shenyu.plugin.logging.common.entity.CommonLoggingRuleHandle;
+import 
org.apache.shenyu.plugin.logging.console.handler.LoggingConsolePluginDataHandler;
+import org.apache.shenyu.plugin.logging.mask.matcher.KeyWordMatch;
+import org.apache.shenyu.plugin.logging.mask.utils.DataMaskUtils;
+import org.apache.shenyu.plugin.logging.mask.enums.DataMaskEnums;
 import org.reactivestreams.Publisher;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -50,9 +54,9 @@ import java.nio.channels.Channels;
 import java.nio.channels.WritableByteChannel;
 import java.nio.charset.StandardCharsets;
 import java.util.Collections;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -65,25 +69,26 @@ public class LoggingConsolePlugin extends 
AbstractShenyuPlugin {
 
     private static final Logger LOG = 
LoggerFactory.getLogger(LoggingConsolePlugin.class);
 
-    private static boolean maskFlag;
-
-    private static Set<String> keyWordSet = new HashSet<>();
+    private static String dataMaskAlg = 
DataMaskEnums.CHARACTER_REPLACE.getDataMaskAlg();
 
-    private static DataMaskInterface dataMaskInterface;
+    private static boolean maskFlag;
 
     private static KeyWordMatch keyWordMatch;
 
     @Override
-    protected Mono<Void> doExecute(final ServerWebExchange exchange, final 
ShenyuPluginChain chain, final SelectorData selector, final RuleData rule) {
-
-        Map<String, String> handleMap = JsonUtils
-                
.jsonToMap(Optional.ofNullable(rule).map(RuleData::getHandle).orElse(""), 
String.class);
-        String keyWords = handleMap.get("keyword");
-        maskFlag = StringUtils.isNotBlank(keyWords) && 
"true".equals(handleMap.get("maskStatus")) ? true : false;
-        if (maskFlag) {
-            Collections.addAll(keyWordSet, keyWords.split(";"));
-            dataMaskInterface = 
SpringBeanUtils.getInstance().getBean(handleMap.get("maskType"));
-            keyWordMatch = new KeyWordMatch(keyWordSet);
+    protected Mono<Void> doExecute(final ServerWebExchange exchange, final 
ShenyuPluginChain chain,
+                                   final SelectorData selector, final RuleData 
rule) {
+        CommonLoggingRuleHandle commonLoggingRuleHandle = 
LoggingConsolePluginDataHandler.CACHED_HANDLE.get().obtainHandle(CacheKeyUtils.INST.getKey(rule));
+        Set<String> keywordSets = Sets.newHashSet();
+        if (Objects.nonNull(commonLoggingRuleHandle)) {
+            String keywords = commonLoggingRuleHandle.getKeyword();
+            maskFlag = StringUtils.isNotBlank(keywords) && 
commonLoggingRuleHandle.getMaskStatus();
+            if (maskFlag) {
+                Collections.addAll(keywordSets, keywords.split(";"));
+                dataMaskAlg = 
Optional.ofNullable(commonLoggingRuleHandle.getMaskType()).orElse(DataMaskEnums.MD5_ENCRYPT.getDataMaskAlg());
+                keyWordMatch = new KeyWordMatch(keywordSets);
+                LOG.info("current plugin:{}, keyword:{}, dataMaskAlg:{}", 
this.named(), keywords, dataMaskAlg);
+            }
         }
         ServerHttpRequest request = exchange.getRequest();
         //"Print Request Info: "
@@ -106,16 +111,19 @@ public class LoggingConsolePlugin extends 
AbstractShenyuPlugin {
     }
 
     private String getRequestMethod(final ServerHttpRequest request) {
-
-        String requestMethod = maskFlag && 
keyWordMatch.matches(GenericLoggingConstant.REQUEST_METHOD)
-                ? dataMaskInterface.mask(request.getMethod().toString()) : 
request.getMethod().toString();
+        // mask request method
+        String requestMethod = "";
+        if (Objects.nonNull(request.getMethod())) {
+            requestMethod = DataMaskUtils.maskSingleKeyword(maskFlag, 
GenericLoggingConstant.REQUEST_METHOD,
+                    request.getMethod().toString(), keyWordMatch, dataMaskAlg);
+        }
         return "Request Method: " + requestMethod + System.lineSeparator();
     }
 
     private String getRequestUri(final ServerHttpRequest request) {
-
-        String requestUri = maskFlag && 
keyWordMatch.matches(GenericLoggingConstant.REQUEST_URI)
-                ? dataMaskInterface.mask(request.getURI().toString()) : 
request.getURI().toString();
+        // mask request uri
+        String requestUri = DataMaskUtils.maskSingleKeyword(maskFlag, 
GenericLoggingConstant.REQUEST_URI,
+                request.getURI().toString(), keyWordMatch, dataMaskAlg);
         return "Request Uri: " + requestUri + System.lineSeparator();
     }
 
@@ -125,7 +133,9 @@ public class LoggingConsolePlugin extends 
AbstractShenyuPlugin {
         if (!params.isEmpty()) {
             logInfo.append("[Query Params 
Start]").append(System.lineSeparator());
             params.forEach((key, value) -> {
-                maskList(key, value);
+                // mask query parameters
+                value = Lists.newArrayList(value);
+                DataMaskUtils.maskList(maskFlag, key, value, keyWordMatch, 
dataMaskAlg);
                 logInfo.append(key).append(": ")
                         .append(StringUtils.join(value, 
",")).append(System.lineSeparator());
             });
@@ -155,34 +165,14 @@ public class LoggingConsolePlugin extends 
AbstractShenyuPlugin {
         entrySet.forEach(entry -> {
             String key = entry.getKey();
             List<String> value = entry.getValue();
-            maskList(key, value);
+            // mask headers
+            value = Lists.newArrayList(value);
+            DataMaskUtils.maskList(maskFlag, key, value, keyWordMatch, 
dataMaskAlg);
             logInfo.append(key).append(": ").append(StringUtils.join(value, 
",")).append(System.lineSeparator());
         });
         return logInfo.toString();
     }
 
-    private static String maskOutput(final String output) {
-
-        Map<String, String> body = JsonUtils.jsonToMap(output, String.class);
-        if (maskFlag) {
-            body.forEach((key, value) -> {
-                if (keyWordMatch.matches(key)) {
-                    body.put(key, dataMaskInterface.mask(value));
-                }
-            });
-        }
-        return JsonUtils.toJson(body);
-    }
-
-    private static void maskList(final String key, final List<String> value) {
-
-        if (maskFlag && keyWordMatch.matches(key)) {
-            for (int i = 0; i < value.size(); i++) {
-                value.set(i, dataMaskInterface.mask(value.get(i)));
-            }
-        }
-    }
-
     static class LoggingServerHttpRequest extends ServerHttpRequestDecorator {
 
         private final StringBuilder logInfo;
@@ -199,7 +189,8 @@ public class LoggingConsolePlugin extends 
AbstractShenyuPlugin {
             return super.getBody().doOnNext(dataBuffer -> 
writer.write(dataBuffer.asByteBuffer().asReadOnlyBuffer())).doFinally(signal -> 
{
                 if (!writer.isEmpty()) {
                     logInfo.append("[Request Body 
Start]").append(System.lineSeparator());
-                    String requestBody = maskOutput(writer.output());
+                    // mask data
+                    String requestBody = DataMaskUtils.maskBody(maskFlag, 
writer.output(), keyWordMatch, dataMaskAlg);
                     logInfo.append(requestBody).append(System.lineSeparator());
                     logInfo.append("[Request Body 
End]").append(System.lineSeparator());
                 } else {
@@ -237,7 +228,8 @@ public class LoggingConsolePlugin extends 
AbstractShenyuPlugin {
             BodyWriter writer = new BodyWriter();
             return Flux.from(body).doOnNext(buffer -> 
writer.write(buffer.asByteBuffer().asReadOnlyBuffer())).doFinally(signal -> {
                 logInfo.append("[Response Body 
Start]").append(System.lineSeparator());
-                String responseBody = maskOutput(writer.output());
+                // mask data
+                String responseBody = DataMaskUtils.maskBody(maskFlag, 
writer.output(), keyWordMatch, dataMaskAlg);
                 logInfo.append(responseBody).append(System.lineSeparator());
                 logInfo.append("[Response Body 
End]").append(System.lineSeparator());
                 // when response, print all request info.
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-console/src/main/java/org/apache/shenyu/plugin/logging/console/handler/LoggingConsolePluginDataHandler.java
 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-console/src/main/java/org/apache/shenyu/plugin/logging/console/handler/LoggingConsolePluginDataHandler.java
new file mode 100644
index 000000000..001a521ea
--- /dev/null
+++ 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-console/src/main/java/org/apache/shenyu/plugin/logging/console/handler/LoggingConsolePluginDataHandler.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.plugin.logging.console.handler;
+
+import org.apache.shenyu.common.dto.RuleData;
+import org.apache.shenyu.common.enums.PluginEnum;
+import org.apache.shenyu.common.utils.GsonUtils;
+import org.apache.shenyu.plugin.base.cache.CommonHandleCache;
+import org.apache.shenyu.plugin.base.handler.PluginDataHandler;
+import org.apache.shenyu.plugin.base.utils.BeanHolder;
+import org.apache.shenyu.plugin.base.utils.CacheKeyUtils;
+import org.apache.shenyu.plugin.logging.common.entity.CommonLoggingRuleHandle;
+
+import java.util.Optional;
+import java.util.function.Supplier;
+
+/**
+ * logging console plugin data handler.
+ */
+public class LoggingConsolePluginDataHandler implements PluginDataHandler {
+
+    public static final Supplier<CommonHandleCache<String, 
CommonLoggingRuleHandle>> CACHED_HANDLE = new 
BeanHolder<>(CommonHandleCache::new);
+
+    @Override
+    public void handlerRule(final RuleData ruleData) {
+        Optional.ofNullable(ruleData.getHandle()).ifPresent(s -> {
+            CommonLoggingRuleHandle commonLoggingRuleHandle = 
GsonUtils.getInstance().fromJson(s, CommonLoggingRuleHandle.class);
+            
CACHED_HANDLE.get().cachedHandle(CacheKeyUtils.INST.getKey(ruleData), 
commonLoggingRuleHandle);
+        });
+    }
+
+    @Override
+    public void removeRule(final RuleData ruleData) {
+        Optional.ofNullable(ruleData.getHandle()).ifPresent(s -> 
CACHED_HANDLE.get().removeHandle(CacheKeyUtils.INST.getKey(ruleData)));
+    }
+
+    @Override
+    public String pluginNamed() {
+        return PluginEnum.LOGGING_CONSOLE.getName();
+    }
+}
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/pom.xml 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/pom.xml
similarity index 80%
copy from 
shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/pom.xml
copy to 
shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/pom.xml
index fbf927ea1..c5d6bf58b 100644
--- a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/pom.xml
+++ b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/pom.xml
@@ -23,25 +23,20 @@
         <version>2.5.1-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>shenyu-plugin-logging-common</artifactId>
+    <artifactId>shenyu-plugin-logging-mask-api</artifactId>
 
     <dependencies>
         <dependency>
             <groupId>org.apache.shenyu</groupId>
-            <artifactId>shenyu-plugin-base</artifactId>
+            <artifactId>shenyu-spi</artifactId>
             <version>${project.version}</version>
         </dependency>
+
         <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-test</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>io.projectreactor</groupId>
-            <artifactId>reactor-test</artifactId>
-            <scope>test</scope>
+            <groupId>org.apache.shenyu</groupId>
+            <artifactId>shenyu-plugin-base</artifactId>
+            <version>${project.version}</version>
         </dependency>
     </dependencies>
 
-</project>
\ No newline at end of file
+</project>
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-console/src/main/java/org/apache/shenyu/plugin/logging/console/config/DataMaskConfig.java
 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/main/java/org/apache/shenyu/plugin/logging/mask/enums/DataMaskEnums.java
similarity index 54%
rename from 
shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-console/src/main/java/org/apache/shenyu/plugin/logging/console/config/DataMaskConfig.java
rename to 
shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/main/java/org/apache/shenyu/plugin/logging/mask/enums/DataMaskEnums.java
index a28e4a414..389095cf0 100644
--- 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-console/src/main/java/org/apache/shenyu/plugin/logging/console/config/DataMaskConfig.java
+++ 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/main/java/org/apache/shenyu/plugin/logging/mask/enums/DataMaskEnums.java
@@ -15,33 +15,29 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.plugin.logging.console.config;
+package org.apache.shenyu.plugin.logging.mask.enums;
 
-import org.apache.shenyu.plugin.logging.common.datamask.DataMaskByCharReplace;
-import org.apache.shenyu.plugin.logging.common.datamask.DataMaskByMD5;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
+/**
+ * data mask enums.
+ */
+public enum DataMaskEnums {
 
-@Configuration
-public class DataMaskConfig {
+    CHARACTER_REPLACE("dataMaskByCharReplace"),
 
-    /**
-     * config bean.
-     *
-     * @return dataMaskByCharReplace bean
-     */
-    @Bean
-    public DataMaskByCharReplace dataMaskByCharReplace() {
-        return new DataMaskByCharReplace();
+    MD5_ENCRYPT("dataMaskByMD5");
+
+    private final String dataMaskAlg;
+
+    DataMaskEnums(final String dataMaskAlg) {
+        this.dataMaskAlg = dataMaskAlg;
     }
 
     /**
-     * config bean.
+     * get mask algorithm.
      *
-     * @return dataMaskByMD5 bean
+     * @return mask algorithm
      */
-    @Bean
-    public DataMaskByMD5 dataMaskByMD5() {
-        return new DataMaskByMD5();
+    public String getDataMaskAlg() {
+        return dataMaskAlg;
     }
 }
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/datamask/DataMaskInterface.java
 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/main/java/org/apache/shenyu/plugin/logging/mask/factory/DataMaskFactory.java
similarity index 57%
copy from 
shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/datamask/DataMaskInterface.java
copy to 
shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/main/java/org/apache/shenyu/plugin/logging/mask/factory/DataMaskFactory.java
index b89c340a9..1ad01a470 100644
--- 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/datamask/DataMaskInterface.java
+++ 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/main/java/org/apache/shenyu/plugin/logging/mask/factory/DataMaskFactory.java
@@ -15,18 +15,28 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.plugin.logging.common.datamask;
+package org.apache.shenyu.plugin.logging.mask.factory;
+
+import org.apache.shenyu.plugin.logging.mask.spi.ShenyuDataMask;
+import org.apache.shenyu.spi.ExtensionLoader;
 
 /**
- * dataMask interface.
+ * shenyu logging mask factory.
  */
-public interface DataMaskInterface {
+public final class DataMaskFactory {
+
+    public DataMaskFactory() {
+    }
 
     /**
-     * mask data.
+     * shenyu logging mask algorithm selector.
      *
-     * @param data data
+     * @param source source data
+     * @param algorithm mask algorithm
      * @return masked data
      */
-    String mask(String data);
+    public static String selectMask(final String source, final String 
algorithm) {
+        ShenyuDataMask dataMask = 
ExtensionLoader.getExtensionLoader(ShenyuDataMask.class).getJoin(algorithm);
+        return dataMask.mask(source);
+    }
 }
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/datamask/KeyWordMatch.java
 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/main/java/org/apache/shenyu/plugin/logging/mask/matcher/KeyWordMatch.java
similarity index 95%
rename from 
shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/datamask/KeyWordMatch.java
rename to 
shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/main/java/org/apache/shenyu/plugin/logging/mask/matcher/KeyWordMatch.java
index bc3e8b737..88a72e213 100644
--- 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/datamask/KeyWordMatch.java
+++ 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/main/java/org/apache/shenyu/plugin/logging/mask/matcher/KeyWordMatch.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.plugin.logging.common.datamask;
+package org.apache.shenyu.plugin.logging.mask.matcher;
 
 import java.util.Set;
 import java.util.regex.Pattern;
@@ -25,7 +25,7 @@ import java.util.regex.Pattern;
  */
 public class KeyWordMatch {
 
-    private Pattern p;
+    private final Pattern p;
 
     /**
      * generate regex.
@@ -33,7 +33,6 @@ public class KeyWordMatch {
      * @param keyWordSet keyWord set
      */
     public KeyWordMatch(final Set<String> keyWordSet) {
-
         StringBuilder sb = new StringBuilder();
         keyWordSet.forEach(tempKeyWord -> {
             sb.append("(?i)");
@@ -54,7 +53,6 @@ public class KeyWordMatch {
      * @return isMatch
      */
     public boolean matches(final String keyWord) {
-
         return p.matcher(keyWord).matches();
     }
 }
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/datamask/DataMaskInterface.java
 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/main/java/org/apache/shenyu/plugin/logging/mask/spi/AbstractShenyuDataMask.java
similarity index 64%
copy from 
shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/datamask/DataMaskInterface.java
copy to 
shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/main/java/org/apache/shenyu/plugin/logging/mask/spi/AbstractShenyuDataMask.java
index b89c340a9..b1812450a 100644
--- 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/datamask/DataMaskInterface.java
+++ 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/main/java/org/apache/shenyu/plugin/logging/mask/spi/AbstractShenyuDataMask.java
@@ -15,18 +15,28 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.plugin.logging.common.datamask;
+package org.apache.shenyu.plugin.logging.mask.spi;
+
+import org.apache.commons.lang3.StringUtils;
 
 /**
- * dataMask interface.
+ * AbstractShenyuDataMask.
  */
-public interface DataMaskInterface {
+public abstract class AbstractShenyuDataMask implements ShenyuDataMask {
+    @Override
+    public String mask(final String source) {
+        if (StringUtils.isBlank(source)) {
+            return "";
+        }
+        return doMask(source);
+    }
 
     /**
-     * mask data.
+     * do mask data.
      *
-     * @param data data
+     * @param source source
      * @return masked data
      */
-    String mask(String data);
+    protected abstract String doMask(String source);
+
 }
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/datamask/DataMaskByCharReplace.java
 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/main/java/org/apache/shenyu/plugin/logging/mask/spi/CharacterReplaceDataMask.java
similarity index 78%
rename from 
shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/datamask/DataMaskByCharReplace.java
rename to 
shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/main/java/org/apache/shenyu/plugin/logging/mask/spi/CharacterReplaceDataMask.java
index a944a5ba0..ae9baabee 100644
--- 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/datamask/DataMaskByCharReplace.java
+++ 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/main/java/org/apache/shenyu/plugin/logging/mask/spi/CharacterReplaceDataMask.java
@@ -15,27 +15,24 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.plugin.logging.common.datamask;
+package org.apache.shenyu.plugin.logging.mask.spi;
 
-import org.springframework.stereotype.Service;
-import org.springframework.util.StringUtils;
+import org.apache.shenyu.spi.Join;
 
-@Service
-public class DataMaskByCharReplace implements DataMaskInterface {
+/**
+ * character replaces data mask.
+ */
+@Join
+public class CharacterReplaceDataMask extends AbstractShenyuDataMask {
 
     private static final Character MASK = '*';
 
     @Override
-    public String mask(final String data) {
-
-        if (!StringUtils.hasLength(data)) {
-            return "";
-        }
-        return doMask(data, data.length() / 2);
+    protected String doMask(final String source) {
+        return maskData(source, source.length() / 2);
     }
 
-    private String doMask(final String data, final int maskNum) {
-
+    private String maskData(final String data, final int maskNum) {
         if (data.length() == 1) {
             return "*";
         }
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/datamask/DataMaskByMD5.java
 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/main/java/org/apache/shenyu/plugin/logging/mask/spi/Md5EncryptDataMask.java
similarity index 70%
rename from 
shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/datamask/DataMaskByMD5.java
rename to 
shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/main/java/org/apache/shenyu/plugin/logging/mask/spi/Md5EncryptDataMask.java
index 97b63179e..43eb9bd09 100644
--- 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/datamask/DataMaskByMD5.java
+++ 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/main/java/org/apache/shenyu/plugin/logging/mask/spi/Md5EncryptDataMask.java
@@ -15,21 +15,18 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.plugin.logging.common.datamask;
+package org.apache.shenyu.plugin.logging.mask.spi;
 
 import org.apache.shenyu.common.utils.Md5Utils;
-import org.springframework.stereotype.Service;
-import org.springframework.util.StringUtils;
-
-@Service
-public class DataMaskByMD5 implements DataMaskInterface {
+import org.apache.shenyu.spi.Join;
 
+/**
+ * md5 encrypt data mask.
+ */
+@Join
+public class Md5EncryptDataMask extends AbstractShenyuDataMask {
     @Override
-    public String mask(final String data) {
-
-        if (!StringUtils.hasLength(data)) {
-            return "";
-        }
-        return Md5Utils.md5(data);
+    protected String doMask(final String source) {
+        return Md5Utils.md5(source);
     }
 }
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/datamask/DataMaskInterface.java
 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/main/java/org/apache/shenyu/plugin/logging/mask/spi/ShenyuDataMask.java
similarity index 80%
rename from 
shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/datamask/DataMaskInterface.java
rename to 
shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/main/java/org/apache/shenyu/plugin/logging/mask/spi/ShenyuDataMask.java
index b89c340a9..c01270d0a 100644
--- 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/datamask/DataMaskInterface.java
+++ 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/main/java/org/apache/shenyu/plugin/logging/mask/spi/ShenyuDataMask.java
@@ -15,18 +15,21 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.plugin.logging.common.datamask;
+package org.apache.shenyu.plugin.logging.mask.spi;
+
+import org.apache.shenyu.spi.SPI;
 
 /**
- * dataMask interface.
+ * shenyu logging data mask.
  */
-public interface DataMaskInterface {
+@SPI
+public interface ShenyuDataMask {
 
     /**
      * mask data.
      *
-     * @param data data
+     * @param source source data
      * @return masked data
      */
-    String mask(String data);
+    String mask(String source);
 }
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/main/java/org/apache/shenyu/plugin/logging/mask/utils/DataMaskUtils.java
 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/main/java/org/apache/shenyu/plugin/logging/mask/utils/DataMaskUtils.java
new file mode 100644
index 000000000..032762556
--- /dev/null
+++ 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/main/java/org/apache/shenyu/plugin/logging/mask/utils/DataMaskUtils.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.plugin.logging.mask.utils;
+
+import org.apache.shenyu.common.utils.JsonUtils;
+import org.apache.shenyu.plugin.logging.mask.factory.DataMaskFactory;
+import org.apache.shenyu.plugin.logging.mask.matcher.KeyWordMatch;
+import org.springframework.util.StringUtils;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * data mask utils.
+ */
+public final class DataMaskUtils {
+
+    /**
+     * mask single keyword.
+     *
+     * @param masked mask flag
+     * @param keyWord keyword
+     * @param source source data
+     * @param keyWordMatch keyWordMatch
+     * @param dataMaskAlg mask algorithm
+     * @return masked data
+     */
+    public static String maskSingleKeyword(final boolean masked, final String 
keyWord, final String source,
+                                           final KeyWordMatch keyWordMatch, 
final String dataMaskAlg) {
+        if (StringUtils.hasLength(source) && masked && 
keyWordMatch.matches(keyWord)) {
+            return DataMaskFactory.selectMask(source, dataMaskAlg);
+        } else {
+            return source;
+        }
+    }
+
+    /**
+     * mask for body.
+     *
+     * @param masked mask flag
+     * @param source source data
+     * @param keyWordMatch keyword match strategy
+     * @param dataMaskAlg mask algorithm
+     * @return masked data
+     */
+    public static String maskBody(final boolean masked, final String source,
+                                     final KeyWordMatch keyWordMatch, final 
String dataMaskAlg) {
+        if (StringUtils.hasLength(source) && masked) {
+            Map<String, String> bodyMap = JsonUtils.jsonToMap(source, 
String.class);
+            bodyMap.forEach((key, value) -> {
+                if (keyWordMatch.matches(key)) {
+                    bodyMap.put(key, DataMaskFactory.selectMask(value, 
dataMaskAlg));
+                }
+            });
+            return JsonUtils.toJson(bodyMap);
+        } else {
+            return source;
+        }
+    }
+
+    /**
+     * mask for list data.
+     *
+     * @param masked masked
+     * @param keyword keyword
+     * @param source source data
+     * @param keyWordMatch keyword match strategy
+     * @param dataMaskAlg mask algorithm
+     */
+    public static void maskList(final boolean masked, final String keyword, 
final List<String> source,
+                                   final KeyWordMatch keyWordMatch, final 
String dataMaskAlg) {
+        if (masked && keyWordMatch.matches(keyword)) {
+            for (int i = 0; i < source.size(); i++) {
+                String ret = DataMaskFactory.selectMask(source.get(i), 
dataMaskAlg);
+                source.set(i, ret);
+            }
+        }
+    }
+}
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/main/resources/META-INF/shenyu/org.apache.shenyu.plugin.logging.mask.spi.ShenyuDataMask
 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/main/resources/META-INF/shenyu/org.apache.shenyu.plugin.logging.mask.spi.ShenyuDataMask
new file mode 100644
index 000000000..ff7730e2c
--- /dev/null
+++ 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/main/resources/META-INF/shenyu/org.apache.shenyu.plugin.logging.mask.spi.ShenyuDataMask
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+dataMaskByMD5=org.apache.shenyu.plugin.logging.mask.spi.Md5EncryptDataMask
+dataMaskByCharReplace=org.apache.shenyu.plugin.logging.mask.spi.CharacterReplaceDataMask
\ No newline at end of file
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/test/java/org/apache/shenyu/plugin/logging/common/datamask/DataMaskByCharReplaceTest.java
 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/test/java/org/apache/shenyu/plugin/logging/mask/factory/DataMaskFactoryTest.java
similarity index 52%
copy from 
shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/test/java/org/apache/shenyu/plugin/logging/common/datamask/DataMaskByCharReplaceTest.java
copy to 
shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/test/java/org/apache/shenyu/plugin/logging/mask/factory/DataMaskFactoryTest.java
index 1af5968ea..f3065383c 100644
--- 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/test/java/org/apache/shenyu/plugin/logging/common/datamask/DataMaskByCharReplaceTest.java
+++ 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/test/java/org/apache/shenyu/plugin/logging/mask/factory/DataMaskFactoryTest.java
@@ -15,37 +15,38 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.plugin.logging.common.datamask;
+package org.apache.shenyu.plugin.logging.mask.factory;
 
+import org.apache.shenyu.common.utils.Md5Utils;
+import org.apache.shenyu.plugin.logging.mask.enums.DataMaskEnums;
 import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
 
-class DataMaskByCharReplaceTest {
-
-    private DataMaskByCharReplace dataMaskByCharReplace;
-
-    @BeforeEach
-    void setUp() {
-
-        dataMaskByCharReplace = new DataMaskByCharReplace();
-    }
+@ExtendWith(MockitoExtension.class)
+public class DataMaskFactoryTest {
 
     @Test
-    void mask() {
-
+    public void selectMask() {
+        // EMPTY_STRING
+        String emptyStr = DataMaskFactory.selectMask("", 
DataMaskEnums.MD5_ENCRYPT.getDataMaskAlg());
+        Assertions.assertEquals("", emptyStr);
+
+        // test for md5
+        String sourceData = "123456789";
+        String maskedData = DataMaskFactory.selectMask(sourceData, 
DataMaskEnums.MD5_ENCRYPT.getDataMaskAlg());
+        Assertions.assertEquals(Md5Utils.md5(sourceData), maskedData);
+
+        // test for replacement
+        String replaceText = DataMaskFactory.selectMask(sourceData, 
DataMaskEnums.CHARACTER_REPLACE.getDataMaskAlg());
         String maskData = "123456789";
-        String mask = dataMaskByCharReplace.mask(maskData);
         int maskNum = 0;
-        for (char c : mask.toCharArray()) {
+        for (char c : replaceText.toCharArray()) {
             if (c == '*') {
                 maskNum++;
             }
         }
         Assertions.assertEquals(maskData.length() / 2, maskNum);
-        String nullMask = dataMaskByCharReplace.mask("");
-        Assertions.assertEquals("", nullMask);
-        String oneMask = dataMaskByCharReplace.mask("1");
-        Assertions.assertEquals("*", oneMask);
     }
 }
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/test/java/org/apache/shenyu/plugin/logging/common/datamask/KeyWordMatchTest.java
 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/test/java/org/apache/shenyu/plugin/logging/mask/matcher/KeyWordMatchTest.java
similarity index 85%
rename from 
shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/test/java/org/apache/shenyu/plugin/logging/common/datamask/KeyWordMatchTest.java
rename to 
shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/test/java/org/apache/shenyu/plugin/logging/mask/matcher/KeyWordMatchTest.java
index 914673e33..d1a4f3569 100644
--- 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/test/java/org/apache/shenyu/plugin/logging/common/datamask/KeyWordMatchTest.java
+++ 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/test/java/org/apache/shenyu/plugin/logging/mask/matcher/KeyWordMatchTest.java
@@ -15,22 +15,24 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.plugin.logging.common.datamask;
+package org.apache.shenyu.plugin.logging.mask.matcher;
 
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
 
 import java.util.HashSet;
 import java.util.Set;
 
+@ExtendWith(MockitoExtension.class)
 class KeyWordMatchTest {
 
     private KeyWordMatch keyWordMatch;
 
     @BeforeEach
-    void setUp() {
-
+    public void setUp() {
         Set<String> set = new HashSet<>();
         set.add("name");
         set.add("TesT");
@@ -39,8 +41,7 @@ class KeyWordMatchTest {
     }
 
     @Test
-    void matches() {
-
+    public void matches() {
         Assertions.assertTrue(keyWordMatch.matches("name"));
         Assertions.assertTrue(keyWordMatch.matches("test"));
         Assertions.assertFalse(keyWordMatch.matches("dsaer"));
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/test/java/org/apache/shenyu/plugin/logging/common/datamask/DataMaskByCharReplaceTest.java
 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/test/java/org/apache/shenyu/plugin/logging/mask/spi/CharacterReplaceDataMaskTest.java
similarity index 53%
rename from 
shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/test/java/org/apache/shenyu/plugin/logging/common/datamask/DataMaskByCharReplaceTest.java
rename to 
shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/test/java/org/apache/shenyu/plugin/logging/mask/spi/CharacterReplaceDataMaskTest.java
index 1af5968ea..8c90ab1cc 100644
--- 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/test/java/org/apache/shenyu/plugin/logging/common/datamask/DataMaskByCharReplaceTest.java
+++ 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/test/java/org/apache/shenyu/plugin/logging/mask/spi/CharacterReplaceDataMaskTest.java
@@ -15,37 +15,32 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.plugin.logging.common.datamask;
+package org.apache.shenyu.plugin.logging.mask.spi;
 
+import org.apache.shenyu.plugin.logging.mask.enums.DataMaskEnums;
+import org.apache.shenyu.plugin.logging.mask.factory.DataMaskFactory;
 import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
 
-class DataMaskByCharReplaceTest {
-
-    private DataMaskByCharReplace dataMaskByCharReplace;
-
-    @BeforeEach
-    void setUp() {
-
-        dataMaskByCharReplace = new DataMaskByCharReplace();
-    }
+@ExtendWith(MockitoExtension.class)
+public class CharacterReplaceDataMaskTest {
 
     @Test
-    void mask() {
+    void doMask() {
+        CharacterReplaceDataMask characterReplaceDataMask = new 
CharacterReplaceDataMask();
+        String ret = characterReplaceDataMask.doMask("1");
+        Assertions.assertEquals("*", ret);
 
-        String maskData = "123456789";
-        String mask = dataMaskByCharReplace.mask(maskData);
+        String sourceData = "123456789";
+        String replaceText = DataMaskFactory.selectMask(sourceData, 
DataMaskEnums.CHARACTER_REPLACE.getDataMaskAlg());
         int maskNum = 0;
-        for (char c : mask.toCharArray()) {
+        for (char c : replaceText.toCharArray()) {
             if (c == '*') {
                 maskNum++;
             }
         }
-        Assertions.assertEquals(maskData.length() / 2, maskNum);
-        String nullMask = dataMaskByCharReplace.mask("");
-        Assertions.assertEquals("", nullMask);
-        String oneMask = dataMaskByCharReplace.mask("1");
-        Assertions.assertEquals("*", oneMask);
+        Assertions.assertEquals(sourceData.length() / 2, maskNum);
     }
 }
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/test/java/org/apache/shenyu/plugin/logging/common/datamask/DataMaskByMD5Test.java
 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/test/java/org/apache/shenyu/plugin/logging/mask/spi/Md5EncryptDataMaskTest.java
similarity index 64%
rename from 
shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/test/java/org/apache/shenyu/plugin/logging/common/datamask/DataMaskByMD5Test.java
rename to 
shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/test/java/org/apache/shenyu/plugin/logging/mask/spi/Md5EncryptDataMaskTest.java
index 7b96945bd..558854bef 100644
--- 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/test/java/org/apache/shenyu/plugin/logging/common/datamask/DataMaskByMD5Test.java
+++ 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/test/java/org/apache/shenyu/plugin/logging/mask/spi/Md5EncryptDataMaskTest.java
@@ -15,30 +15,20 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.plugin.logging.common.datamask;
+package org.apache.shenyu.plugin.logging.mask.spi;
 
 import org.apache.shenyu.common.utils.Md5Utils;
 import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
 
-class DataMaskByMD5Test {
-
-    private DataMaskByMD5 dataMaskByMD5;
-
-    @BeforeEach
-    void setUp() {
-
-        dataMaskByMD5 = new DataMaskByMD5();
-    }
+@ExtendWith(MockitoExtension.class)
+public class Md5EncryptDataMaskTest {
 
     @Test
-    void mask() {
-
-        String maskData = "123456789";
-        String mask = dataMaskByMD5.mask(maskData);
-        Assertions.assertEquals(Md5Utils.md5(maskData), mask);
-        String nullMask = dataMaskByMD5.mask("");
-        Assertions.assertEquals("", nullMask);
+    public void doMask() {
+        Md5EncryptDataMask md5EncryptDataMask = new Md5EncryptDataMask();
+        Assertions.assertEquals(Md5Utils.md5("test"), 
md5EncryptDataMask.doMask("test"));
     }
 }
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/test/java/org/apache/shenyu/plugin/logging/mask/utils/DataMaskUtilsTest.java
 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/test/java/org/apache/shenyu/plugin/logging/mask/utils/DataMaskUtilsTest.java
new file mode 100644
index 000000000..edf9ecf9b
--- /dev/null
+++ 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-mask-api/src/test/java/org/apache/shenyu/plugin/logging/mask/utils/DataMaskUtilsTest.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.plugin.logging.mask.utils;
+
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.shenyu.common.utils.JsonUtils;
+import org.apache.shenyu.common.utils.Md5Utils;
+import org.apache.shenyu.plugin.logging.mask.enums.DataMaskEnums;
+import org.apache.shenyu.plugin.logging.mask.matcher.KeyWordMatch;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+@ExtendWith(MockitoExtension.class)
+public class DataMaskUtilsTest {
+
+    private static final String JSON_TEXT = 
"{\"id\":\"123\",\"name\":\"jack\"}";
+
+    private KeyWordMatch keyWordMatch;
+
+    @BeforeEach
+    public void setup() {
+        Set<String> sets = new HashSet<>();
+        sets.add("name");
+        keyWordMatch = new KeyWordMatch(sets);
+    }
+
+    @Test
+    public void maskSingleKeyword() {
+        String noMaskedData = DataMaskUtils.maskSingleKeyword(false, "name", 
JSON_TEXT, keyWordMatch,
+                DataMaskEnums.MD5_ENCRYPT.getDataMaskAlg());
+        Assertions.assertEquals(JSON_TEXT, noMaskedData);
+
+        String maskedData = DataMaskUtils.maskSingleKeyword(true, "name", 
JSON_TEXT, keyWordMatch,
+                DataMaskEnums.MD5_ENCRYPT.getDataMaskAlg());
+        Assertions.assertEquals(Md5Utils.md5(JSON_TEXT), maskedData);
+    }
+
+    @Test
+    public void maskBody() {
+        String noMaskedData = DataMaskUtils.maskBody(false, JSON_TEXT, 
keyWordMatch, DataMaskEnums.MD5_ENCRYPT.getDataMaskAlg());
+        Assertions.assertEquals(JSON_TEXT, noMaskedData);
+
+        String maskedData = DataMaskUtils.maskBody(true, JSON_TEXT, 
keyWordMatch, DataMaskEnums.MD5_ENCRYPT.getDataMaskAlg());
+        Map<String, String> jsonMap = JsonUtils.jsonToMap(JSON_TEXT, 
String.class);
+        jsonMap.put("name", Md5Utils.md5(jsonMap.get("name")));
+        String jsonRet = JsonUtils.toJson(jsonMap);
+        Assertions.assertEquals(jsonRet, maskedData);
+
+    }
+
+    @Test
+    public void maskList() {
+        List<String> list = Arrays.asList("name", "test");
+        DataMaskUtils.maskList(false, "name", list, keyWordMatch, 
DataMaskEnums.MD5_ENCRYPT.getDataMaskAlg());
+        Assertions.assertTrue(CollectionUtils.isEqualCollection(list, list));
+        DataMaskUtils.maskList(true, "name", list, keyWordMatch, 
DataMaskEnums.MD5_ENCRYPT.getDataMaskAlg());
+        List<String> md5List = Arrays.asList(Md5Utils.md5("name"), 
Md5Utils.md5("test"));
+        Assertions.assertTrue(CollectionUtils.isEqualCollection(md5List, 
list));
+    }
+}
diff --git 
a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-logging-console/src/main/java/org/apache/shenyu/springboot/starter/plugin/logging/console/LoggingConsolePluginConfiguration.java
 
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-logging-console/src/main/java/org/apache/shenyu/springboot/starter/plugin/logging/console/LoggingConsolePluginConfiguration.java
index 190569062..3c8912bea 100644
--- 
a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-logging-console/src/main/java/org/apache/shenyu/springboot/starter/plugin/logging/console/LoggingConsolePluginConfiguration.java
+++ 
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-logging-console/src/main/java/org/apache/shenyu/springboot/starter/plugin/logging/console/LoggingConsolePluginConfiguration.java
@@ -18,7 +18,9 @@
 package org.apache.shenyu.springboot.starter.plugin.logging.console;
 
 import org.apache.shenyu.plugin.api.ShenyuPlugin;
+import org.apache.shenyu.plugin.base.handler.PluginDataHandler;
 import org.apache.shenyu.plugin.logging.console.LoggingConsolePlugin;
+import 
org.apache.shenyu.plugin.logging.console.handler.LoggingConsolePluginDataHandler;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
@@ -30,6 +32,16 @@ import org.springframework.context.annotation.Configuration;
 @ConditionalOnProperty(value = {"shenyu.plugins.logging-console.enabled"}, 
havingValue = "true", matchIfMissing = true)
 public class LoggingConsolePluginConfiguration {
 
+    /**
+     * logging console plugin data handler.
+     *
+     * @return LoggingConsolePluginDataHandler
+     */
+    @Bean
+    public PluginDataHandler loggingPluginDataHandler() {
+        return new LoggingConsolePluginDataHandler();
+    }
+
     /**
      * Logging console plugin.
      *

Reply via email to