You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by wu...@apache.org on 2019/12/17 00:59:11 UTC

[skywalking] branch master updated: Enhance webflux plugin, related to Spring Gateway plugin too. (#3945)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new bc77fda  Enhance webflux plugin, related to Spring Gateway plugin too. (#3945)
bc77fda is described below

commit bc77fda5c120673e8b7a0a93eceb6e2074cba07c
Author: cyejing <ji...@qq.com>
AuthorDate: Tue Dec 17 08:58:57 2019 +0800

    Enhance webflux plugin, related to Spring Gateway plugin too. (#3945)
    
    * webflux-reactive
    
    * add support version comment, modify gateway
    
    * add test case, modify name
    
    * add docs
    
    * remove healthCheck
---
 .github/workflows/plugins-test.yaml                |   2 +-
 apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml  |   1 -
 .../AbstractServerResponseMethodInterceptor.java   |  79 ----------
 ...atcherHandlerHandleResultMethodInterceptor.java |  58 -------
 ...tcherHandlerInvokeHandlerMethodInterceptor.java |  83 ----------
 .../AbstractServerResponseInstrumentation.java     |  67 --------
 .../v21x/FilteringWebHandlerInterceptor.java       |  19 ++-
 .../HttpClientOperationsStatusInterceptor.java     |   2 -
 .../cloud/gateway/v21x/context/SWTransmitter.java  |  12 +-
 .../optional-spring-plugins/pom.xml                |   3 +-
 .../spring-webflux-5.x-plugin}/pom.xml             |  22 ++-
 .../DispatcherHandlerHandleMethodInterceptor.java  | 105 +++++++------
 .../ServerWebExchangeConstructorInterceptor.java   |   2 +-
 .../define/DispatcherHandlerInstrumentation.java   |  32 +---
 .../define/ServerWebExchangeInstrumentation.java   |   3 +-
 .../src/main/resources/skywalking-plugin.def       |   1 -
 docs/en/setup/service-agent/java-agent/README.md   |   3 +-
 .../service-agent/java-agent/Supported-list.md     |   2 +-
 .../gateway-scenario/config/expectedData.yaml      |  19 ++-
 .../scenarios/gateway-scenario/configuration.yml   |   2 +-
 .../gateway-projectA-scenario/pom.xml              |   3 +-
 .../src/main/resources/application.yml             |   2 +-
 .../webflux-scenario/config/expectedData.yaml      | 171 ++++++++++++++-------
 .../scenarios/webflux-scenario/configuration.yml   |   4 +-
 test/plugin/scenarios/webflux-scenario/pom.xml     |   2 +-
 .../webflux-scenario/support-version.list          |  15 +-
 .../webflux-projectA-scenario/pom.xml              |  12 +-
 .../projectA/controller/TestController.java        |   2 +
 .../controller/TestAnnotationController.java       |   6 +
 29 files changed, 244 insertions(+), 490 deletions(-)

diff --git a/.github/workflows/plugins-test.yaml b/.github/workflows/plugins-test.yaml
index 9cb28d5..99edb78 100644
--- a/.github/workflows/plugins-test.yaml
+++ b/.github/workflows/plugins-test.yaml
@@ -106,7 +106,7 @@ jobs:
         run: ./mvnw -f test/plugin/pom.xml clean package -DskipTests docker:build -DBUILD_NO=local >/dev/null
       - name: Run apm-toolkit-trace (1)
         run: bash test/plugin/run.sh apm-toolkit-trace-scenario
-      - name: Run spring-webflux 2.x (18)
+      - name: Run spring-webflux 2.x (7)
         run: bash test/plugin/run.sh webflux-scenario
       - name: Run netty-socketio 1.x (4)
         run: bash test/plugin/run.sh netty-socketio-scenario
diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml
index cbc1779..5eca222 100644
--- a/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml
+++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml
@@ -38,7 +38,6 @@
         <module>mvc-annotation-commons</module>
         <module>spring-commons</module>
         <module>mvc-annotation-5.x-plugin</module>
-        <module>webflux-5.x-plugin</module>
     </modules>
     <packaging>pom</packaging>
 
diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/AbstractServerResponseMethodInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/AbstractServerResponseMethodInterceptor.java
deleted file mode 100644
index 13162c7..0000000
--- a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/AbstractServerResponseMethodInterceptor.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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.skywalking.apm.plugin.spring.webflux.v5;
-
-/**
- * @author zhaoyuguang
- */
-
-import org.apache.skywalking.apm.agent.core.context.ContextManager;
-import org.apache.skywalking.apm.agent.core.context.tag.Tags;
-import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
-import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
-import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
-import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
-import org.springframework.http.HttpStatus;
-import org.springframework.web.server.ServerWebExchange;
-
-import java.lang.reflect.Method;
-
-public class AbstractServerResponseMethodInterceptor implements InstanceMethodsAroundInterceptor {
-
-    /**
-     * The error reason
-     * see more details org.springframework.boot.web.reactive.error.DefaultErrorAttributes#storeErrorInformation
-     */
-    private final static String ERROR_ATTRIBUTE = "org.springframework.boot.web.reactive.error.DefaultErrorAttributes.ERROR";
-
-    @Override
-    public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
-        EnhancedInstance instance = DispatcherHandlerHandleMethodInterceptor.getInstance(allArguments[0]);
-        if (instance != null) {
-            AbstractSpan span = (AbstractSpan) instance.getSkyWalkingDynamicField();
-            if (span == null) {
-                return;
-            }
-            ServerWebExchange exchange = (ServerWebExchange) allArguments[0];
-            HttpStatus status = exchange.getResponse().getStatusCode();
-            if (status != null && status.value() >= 400) {
-                span.errorOccurred();
-                if (exchange.getAttribute(ERROR_ATTRIBUTE) != null) {
-                    span.log((Throwable) exchange.getAttribute(ERROR_ATTRIBUTE));
-                }
-                Tags.STATUS_CODE.set(span, Integer.toString(status.value()));
-            }
-            if (ContextManager.isActive()) {
-                ContextManager.stopSpan(span);
-            } else {
-                span.asyncFinish();
-            }
-            ((EnhancedInstance) allArguments[0]).setSkyWalkingDynamicField(null);
-        }
-    }
-
-    @Override
-    public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object ret) throws Throwable {
-        return ret;
-    }
-
-    @Override
-    public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
-
-    }
-}
diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/DispatcherHandlerHandleResultMethodInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/DispatcherHandlerHandleResultMethodInterceptor.java
deleted file mode 100644
index 79a97e6..0000000
--- a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/DispatcherHandlerHandleResultMethodInterceptor.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.skywalking.apm.plugin.spring.webflux.v5;
-
-/**
- * @author zhaoyuguang
- */
-
-import org.apache.skywalking.apm.agent.core.context.ContextManager;
-import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
-import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
-import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
-import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
-
-import java.lang.reflect.Method;
-
-public class DispatcherHandlerHandleResultMethodInterceptor implements InstanceMethodsAroundInterceptor {
-
-    @Override
-    public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
-                             MethodInterceptResult result) throws Throwable {
-    }
-
-    @Override
-    public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
-                              Object ret) throws Throwable {
-        EnhancedInstance instance = DispatcherHandlerHandleMethodInterceptor.getInstance(allArguments[0]);
-        if (instance != null) {
-            AbstractSpan span = (AbstractSpan) instance.getSkyWalkingDynamicField();
-            if (span != null) {
-                ContextManager.stopSpan(span);
-                instance.setSkyWalkingDynamicField(null);
-            }
-        }
-        return ret;
-    }
-
-    @Override
-    public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
-                                      Class<?>[] argumentsTypes, Throwable t) {
-    }
-}
diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/DispatcherHandlerInvokeHandlerMethodInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/DispatcherHandlerInvokeHandlerMethodInterceptor.java
deleted file mode 100644
index 542e82a..0000000
--- a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/DispatcherHandlerInvokeHandlerMethodInterceptor.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * 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.skywalking.apm.plugin.spring.webflux.v5;
-
-/**
- * @author zhaoyuguang
- */
-
-import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
-import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
-import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
-import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
-import org.springframework.web.method.HandlerMethod;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-
-public class DispatcherHandlerInvokeHandlerMethodInterceptor implements InstanceMethodsAroundInterceptor {
-
-    private static final String ROUTER_SEARCH = "$$Lambda";
-    private static final String ROUTER_FIELD = "arg$1";
-    private static final String DOT = ".";
-
-
-    @Override
-    public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
-                             MethodInterceptResult result) throws Throwable {
-        EnhancedInstance instance = DispatcherHandlerHandleMethodInterceptor.getInstance(allArguments[0]);
-        if (instance != null) {
-            AbstractSpan span = (AbstractSpan) instance.getSkyWalkingDynamicField();
-            if (span == null) {
-                return;
-            }
-            String handleClassName = allArguments[1].getClass().getSimpleName();
-            int index = handleClassName.indexOf(ROUTER_SEARCH);
-            if (index != -1) {
-                String operationName = handleClassName.substring(0, index);
-                try {
-                    Field field = allArguments[1].getClass().getDeclaredField(ROUTER_FIELD);
-                    field.setAccessible(true);
-                    operationName = operationName + DOT + field.get(allArguments[1]).getClass().getName();
-                } catch (NoSuchFieldException ignore) {
-                }
-                span.setOperationName(operationName);
-            } else if (allArguments[1] instanceof HandlerMethod) {
-                HandlerMethod handler = (HandlerMethod) allArguments[1];
-                span.setOperationName(getHandlerMethodOperationName(handler));
-            }
-        }
-    }
-
-    @Override
-    public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
-                              Object ret) throws Throwable {
-        return ret;
-    }
-
-    @Override
-    public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
-                                      Class<?>[] argumentsTypes, Throwable t) {
-    }
-
-    private String getHandlerMethodOperationName(HandlerMethod handler) {
-        Method method = handler.getMethod();
-        return method.getDeclaringClass().getName() + DOT + method.getName();
-    }
-}
diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/define/AbstractServerResponseInstrumentation.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/define/AbstractServerResponseInstrumentation.java
deleted file mode 100644
index 686affb..0000000
--- a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/define/AbstractServerResponseInstrumentation.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.skywalking.apm.plugin.spring.webflux.v5.define;
-
-import net.bytebuddy.description.method.MethodDescription;
-import net.bytebuddy.matcher.ElementMatcher;
-import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
-import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
-import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
-import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
-
-import static net.bytebuddy.matcher.ElementMatchers.named;
-import static org.apache.skywalking.apm.agent.core.plugin.match.MultiClassNameMatch.byMultiClassMatch;
-
-/**
- * @author zhaoyuguang
- */
-
-public class AbstractServerResponseInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
-
-    @Override
-    protected ClassMatch enhanceClass() {
-        return byMultiClassMatch("org.springframework.web.reactive.function.server.DefaultServerResponseBuilder$BodyInserterResponse",
-                "org.springframework.web.reactive.function.server.DefaultServerResponseBuilder$BodyInserterServerResponse",
-                "org.springframework.web.reactive.function.server.DefaultEntityResponseBuilder$DefaultEntityResponse");
-    }
-
-    @Override
-    public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
-        return new ConstructorInterceptPoint[0];
-    }
-
-    @Override
-    public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
-        return new InstanceMethodsInterceptPoint[] {
-            new InstanceMethodsInterceptPoint() {
-                @Override public ElementMatcher<MethodDescription> getMethodsMatcher() {
-                    return named("writeToInternal");
-                }
-
-                @Override public String getMethodsInterceptor() {
-                    return "org.apache.skywalking.apm.plugin.spring.webflux.v5.AbstractServerResponseMethodInterceptor";
-                }
-
-                @Override public boolean isOverrideArgs() {
-                    return false;
-                }
-            }
-        };
-    }
-}
diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/FilteringWebHandlerInterceptor.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/FilteringWebHandlerInterceptor.java
index 9eb1bd0..427e982 100644
--- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/FilteringWebHandlerInterceptor.java
+++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/FilteringWebHandlerInterceptor.java
@@ -18,7 +18,11 @@
 
 package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v21x;
 
+import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR;
+
+import java.lang.reflect.Method;
 import org.apache.skywalking.apm.agent.core.context.ContextManager;
+import org.apache.skywalking.apm.agent.core.context.ContextSnapshot;
 import org.apache.skywalking.apm.agent.core.context.tag.Tags;
 import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
 import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
@@ -31,9 +35,6 @@ import org.springframework.cloud.gateway.route.Route;
 import org.springframework.http.HttpStatus;
 import org.springframework.web.server.ServerWebExchange;
 import reactor.core.publisher.Mono;
-import java.lang.reflect.Method;
-
-import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR;
 
 
 /**
@@ -42,6 +43,7 @@ import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.G
 public class FilteringWebHandlerInterceptor implements InstanceMethodsAroundInterceptor {
 
     private static final String SPRING_CLOUD_GATEWAY_ROUTE_PREFIX = "GATEWAY/";
+
     @Override
     public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
                              MethodInterceptResult result) throws Throwable {
@@ -49,18 +51,17 @@ public class FilteringWebHandlerInterceptor implements InstanceMethodsAroundInte
         if (instance == null) {
             return;
         }
-        AbstractSpan span = (AbstractSpan) instance.getSkyWalkingDynamicField();
-        if (span == null) {
+        ContextSnapshot contextSnapshot = (ContextSnapshot) instance.getSkyWalkingDynamicField();
+        if (contextSnapshot == null) {
             return;
         }
+
         ServerWebExchange exchange = (ServerWebExchange) allArguments[0];
         String operationName = SPRING_CLOUD_GATEWAY_ROUTE_PREFIX;
         Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);
         operationName = operationName + route.getId();
-        span.setOperationName(operationName);
-        SWTransmitter transmitter = new SWTransmitter(span.prepareForAsync(),ContextManager.capture(),operationName);
+        SWTransmitter transmitter = new SWTransmitter(contextSnapshot, operationName);
         instance.setSkyWalkingDynamicField(transmitter);
-        ContextManager.stopSpan(span);
     }
 
     @Override
@@ -85,8 +86,6 @@ public class FilteringWebHandlerInterceptor implements InstanceMethodsAroundInte
                 localSpan.setComponent(ComponentsDefine.SPRING_CLOUD_GATEWAY);
                 ContextManager.continued(swTransmitter.getSnapshot());
                 ContextManager.stopSpan(localSpan);
-                AbstractSpan spanWebflux = swTransmitter.getSpanWebflux();
-                spanWebflux.asyncFinish();
             }
         });
     }
diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/HttpClientOperationsStatusInterceptor.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/HttpClientOperationsStatusInterceptor.java
index 89ff180..6324308 100644
--- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/HttpClientOperationsStatusInterceptor.java
+++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/HttpClientOperationsStatusInterceptor.java
@@ -48,10 +48,8 @@ public class HttpClientOperationsStatusInterceptor implements InstanceMethodsAro
             HttpResponseStatus response = (HttpResponseStatus) ret;
             if (response.code() >= 400) {
                 Tags.STATUS_CODE.set(transmitter.getSpanGateway().errorOccurred(), String.valueOf(response.code()));
-                Tags.STATUS_CODE.set(transmitter.getSpanWebflux().errorOccurred(), String.valueOf(response.code()));
             }
             transmitter.getSpanGateway().asyncFinish();
-            transmitter.getSpanWebflux().asyncFinish();
             objInst.setSkyWalkingDynamicField(null);
         }
         return ret;
diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/context/SWTransmitter.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/context/SWTransmitter.java
index bedd489..216dd22 100644
--- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/context/SWTransmitter.java
+++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/context/SWTransmitter.java
@@ -27,25 +27,15 @@ import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
 
 public class SWTransmitter {
 
-    private AbstractSpan spanWebflux;
     private AbstractSpan spanGateway;
     private ContextSnapshot snapshot;
     private String operationName;
 
-    public SWTransmitter(AbstractSpan spanWebflux, ContextSnapshot snapshot, String operationName) {
-        this.spanWebflux = spanWebflux;
+    public SWTransmitter(ContextSnapshot snapshot, String operationName) {
         this.snapshot = snapshot;
         this.operationName = operationName;
     }
 
-    public AbstractSpan getSpanWebflux() {
-        return spanWebflux;
-    }
-
-    public void setSpanWebflux(AbstractSpan spanWebflux) {
-        this.spanWebflux = spanWebflux;
-    }
-
     public AbstractSpan getSpanGateway() {
         return spanGateway;
     }
diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml
index 3284106..f64764f 100644
--- a/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml
+++ b/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml
@@ -32,10 +32,11 @@
         <module>spring-annotation-plugin</module>
         <module>spring-tx-plugin</module>
         <module>optional-spring-cloud</module>
+        <module>spring-webflux-5.x-plugin</module>
     </modules>
 
     <properties>
         <sdk.plugin.related.dir>/..</sdk.plugin.related.dir>
     </properties>
 
-</project>
\ No newline at end of file
+</project>
diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/pom.xml
similarity index 64%
rename from apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/pom.xml
rename to apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/pom.xml
index 44edf24..b476937 100644
--- a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/pom.xml
+++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/pom.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
 <!--
   ~ Licensed to the Apache Software Foundation (ASF) under one or more
   ~ contributor license agreements.  See the NOTICE file distributed with
@@ -6,27 +7,28 @@
   ~ (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
+  ~     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.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
   -->
 
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
-        <artifactId>spring-plugins</artifactId>
+        <artifactId>optional-spring-plugins</artifactId>
         <groupId>org.apache.skywalking</groupId>
         <version>6.6.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
-    <artifactId>apm-webflux-5.x-plugin</artifactId>
-    <packaging>jar</packaging>
+    <artifactId>apm-spring-webflux-5.x-plugin</artifactId>
 
-    <name>webflux-5.x-plugin</name>
     <url>http://maven.apache.org</url>
 
     <dependencies>
@@ -37,4 +39,8 @@
             <scope>provided</scope>
         </dependency>
     </dependencies>
+
+    <properties>
+        <compiler.version>1.8</compiler.version>
+    </properties>
 </project>
diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/DispatcherHandlerHandleMethodInterceptor.java b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/DispatcherHandlerHandleMethodInterceptor.java
similarity index 55%
rename from apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/DispatcherHandlerHandleMethodInterceptor.java
rename to apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/DispatcherHandlerHandleMethodInterceptor.java
index 712ca65..26f94ce 100644
--- a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/DispatcherHandlerHandleMethodInterceptor.java
+++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/DispatcherHandlerHandleMethodInterceptor.java
@@ -18,14 +18,13 @@
 
 package org.apache.skywalking.apm.plugin.spring.webflux.v5;
 
-/**
- * @author zhaoyuguang
- */
-
+import java.lang.reflect.Method;
+import java.util.List;
 import org.apache.skywalking.apm.agent.core.context.CarrierItem;
 import org.apache.skywalking.apm.agent.core.context.ContextCarrier;
 import org.apache.skywalking.apm.agent.core.context.ContextManager;
 import org.apache.skywalking.apm.agent.core.context.tag.Tags;
+import org.apache.skywalking.apm.agent.core.context.tag.Tags.HTTP;
 import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
 import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
 import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
@@ -33,45 +32,72 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceM
 import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
 import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
 import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.reactive.HandlerMapping;
 import org.springframework.web.server.ServerWebExchange;
 import org.springframework.web.server.ServerWebExchangeDecorator;
 import org.springframework.web.server.adapter.DefaultServerWebExchange;
+import org.springframework.web.util.pattern.PathPattern;
+import reactor.core.publisher.Mono;
 
-import java.lang.reflect.Method;
-import java.util.List;
-
+/**
+ * @author zhaoyuguang, Born
+ */
 public class DispatcherHandlerHandleMethodInterceptor implements InstanceMethodsAroundInterceptor {
-
-    private static final String WIP_OPERATION_NAME = "WEBFLUX.handle";
+    private static final String DEFAULT_OPERATION_NAME = "WEBFLUX.handle";
 
     @Override
     public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
                              MethodInterceptResult result) throws Throwable {
-        EnhancedInstance instance = DispatcherHandlerHandleMethodInterceptor.getInstance(allArguments[0]);
-        if (instance != null) {
-            ContextCarrier contextCarrier = new ContextCarrier();
-            CarrierItem next = contextCarrier.items();
-            ServerWebExchange exchange = (ServerWebExchange) allArguments[0];
-            HttpHeaders headers = exchange.getRequest().getHeaders();
-            while (next.hasNext()) {
-                next = next.next();
-                List<String> header = headers.get(next.getHeadKey());
-                if (header != null && header.size() > 0) {
-                    next.setHeadValue(header.get(0));
-                }
-            }
-            AbstractSpan span = ContextManager.createEntrySpan(WIP_OPERATION_NAME, contextCarrier);
-            span.setComponent(ComponentsDefine.SPRING_WEBFLUX);
-            SpanLayer.asHttp(span);
-            Tags.URL.set(span, exchange.getRequest().getURI().toString());
-            instance.setSkyWalkingDynamicField(span);
-        }
+
     }
 
     @Override
     public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
                               Object ret) throws Throwable {
-        return ret;
+        EnhancedInstance instance = getInstance(allArguments[0]);
+
+        ServerWebExchange exchange = (ServerWebExchange) allArguments[0];
+
+        ContextCarrier carrier = new ContextCarrier();
+        CarrierItem next = carrier.items();
+        HttpHeaders headers = exchange.getRequest().getHeaders();
+        while (next.hasNext()) {
+            next = next.next();
+            List<String> header = headers.get(next.getHeadKey());
+            if (header != null && header.size() > 0) {
+                next.setHeadValue(header.get(0));
+            }
+        }
+
+        AbstractSpan span = ContextManager.createEntrySpan(DEFAULT_OPERATION_NAME, carrier);
+        span.setComponent(ComponentsDefine.SPRING_WEBFLUX);
+        SpanLayer.asHttp(span);
+        Tags.URL.set(span, exchange.getRequest().getURI().toString());
+        HTTP.METHOD.set(span, exchange.getRequest().getMethodValue());
+        instance.setSkyWalkingDynamicField(ContextManager.capture());
+        span.prepareForAsync();
+        ContextManager.stopSpan(span);
+
+        return ((Mono) ret).doFinally(s -> {
+            try {
+                Object pathPattern = exchange.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
+                if (pathPattern != null) {
+                    span.setOperationName(((PathPattern) pathPattern).getPatternString());
+                }
+                HttpStatus httpStatus = exchange.getResponse().getStatusCode();
+                // fix webflux-2.0.0-2.1.0 version have bug. httpStatus is null. not support
+                if (httpStatus != null) {
+                    Tags.STATUS_CODE.set(span, Integer.toString(httpStatus.value()));
+                    if (httpStatus.isError()) {
+                        span.errorOccurred();
+                    }
+                }
+            } finally {
+                span.asyncFinish();
+            }
+        });
+
     }
 
     @Override
@@ -81,26 +107,13 @@ public class DispatcherHandlerHandleMethodInterceptor implements InstanceMethods
 
     public static EnhancedInstance getInstance(Object o) {
         EnhancedInstance instance = null;
-        if (o instanceof ServerWebExchangeDecorator) {
-            instance = getEnhancedInstance((ServerWebExchangeDecorator) o);
-        } else if (o instanceof DefaultServerWebExchange) {
+        if (o instanceof DefaultServerWebExchange) {
             instance = (EnhancedInstance) o;
+        } else if (o instanceof ServerWebExchangeDecorator) {
+            ServerWebExchange delegate = ((ServerWebExchangeDecorator) o).getDelegate();
+            return getInstance(delegate);
         }
         return instance;
     }
 
-
-    private static EnhancedInstance getEnhancedInstance(ServerWebExchangeDecorator serverWebExchangeDecorator) {
-        Object o = serverWebExchangeDecorator.getDelegate();
-        if (o instanceof ServerWebExchangeDecorator) {
-            return getEnhancedInstance((ServerWebExchangeDecorator) o);
-        } else if (o instanceof DefaultServerWebExchange) {
-            return (EnhancedInstance) o;
-        } else if (o == null) {
-            throw new NullPointerException("The expected class DefaultServerWebExchange is null");
-        } else {
-            throw new RuntimeException("Unknown parameter types:" + o.getClass());
-        }
-    }
-
 }
diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/ServerWebExchangeConstructorInterceptor.java b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/ServerWebExchangeConstructorInterceptor.java
similarity index 97%
rename from apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/ServerWebExchangeConstructorInterceptor.java
rename to apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/ServerWebExchangeConstructorInterceptor.java
index f6b805f..6df67c8 100644
--- a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/ServerWebExchangeConstructorInterceptor.java
+++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/ServerWebExchangeConstructorInterceptor.java
@@ -23,7 +23,7 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceC
 
 /**
  *
- * @author zhaoyuguang
+ * @author zhaoyuguang, Born
  */
 public class ServerWebExchangeConstructorInterceptor implements InstanceConstructorInterceptor {
     @Override
diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/define/DispatcherHandlerInstrumentation.java b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/define/DispatcherHandlerInstrumentation.java
similarity index 68%
rename from apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/define/DispatcherHandlerInstrumentation.java
rename to apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/define/DispatcherHandlerInstrumentation.java
index 6113b8a..a645117 100644
--- a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/define/DispatcherHandlerInstrumentation.java
+++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/define/DispatcherHandlerInstrumentation.java
@@ -29,7 +29,7 @@ import static net.bytebuddy.matcher.ElementMatchers.named;
 import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
 
 /**
- * @author zhaoyuguang
+ * @author zhaoyuguang, Born
  */
 
 public class DispatcherHandlerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
@@ -56,36 +56,6 @@ public class DispatcherHandlerInstrumentation extends ClassInstanceMethodsEnhanc
                 public boolean isOverrideArgs() {
                     return false;
                 }
-            }, new InstanceMethodsInterceptPoint() {
-                @Override
-                public ElementMatcher<MethodDescription> getMethodsMatcher() {
-                    return named("invokeHandler");
-                }
-
-                @Override
-                public String getMethodsInterceptor() {
-                    return "org.apache.skywalking.apm.plugin.spring.webflux.v5.DispatcherHandlerInvokeHandlerMethodInterceptor";
-                }
-
-                @Override
-                public boolean isOverrideArgs() {
-                    return false;
-                }
-            }, new InstanceMethodsInterceptPoint() {
-                @Override
-                public ElementMatcher<MethodDescription> getMethodsMatcher() {
-                    return named("handleResult");
-                }
-
-                @Override
-                public String getMethodsInterceptor() {
-                    return "org.apache.skywalking.apm.plugin.spring.webflux.v5.DispatcherHandlerHandleResultMethodInterceptor";
-                }
-
-                @Override
-                public boolean isOverrideArgs() {
-                    return false;
-                }
             }
         };
     }
diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/define/ServerWebExchangeInstrumentation.java b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/define/ServerWebExchangeInstrumentation.java
similarity index 98%
rename from apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/define/ServerWebExchangeInstrumentation.java
rename to apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/define/ServerWebExchangeInstrumentation.java
index 0efe402..e4d0e30 100644
--- a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/define/ServerWebExchangeInstrumentation.java
+++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/define/ServerWebExchangeInstrumentation.java
@@ -29,9 +29,8 @@ import static net.bytebuddy.matcher.ElementMatchers.any;
 import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
 
 /**
- * @author zhaoyuguang
+ * @author zhaoyuguang, Born
  */
-
 public class ServerWebExchangeInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
     @Override
     public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/src/main/resources/skywalking-plugin.def
similarity index 89%
rename from apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/resources/skywalking-plugin.def
rename to apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/src/main/resources/skywalking-plugin.def
index f1752e3..278cd04 100644
--- a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/resources/skywalking-plugin.def
+++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/src/main/resources/skywalking-plugin.def
@@ -16,4 +16,3 @@
 
 spring-webflux-5.x=org.apache.skywalking.apm.plugin.spring.webflux.v5.define.DispatcherHandlerInstrumentation
 spring-webflux-5.x=org.apache.skywalking.apm.plugin.spring.webflux.v5.define.ServerWebExchangeInstrumentation
-spring-webflux-5.x=org.apache.skywalking.apm.plugin.spring.webflux.v5.define.AbstractServerResponseInstrumentation
\ No newline at end of file
diff --git a/docs/en/setup/service-agent/java-agent/README.md b/docs/en/setup/service-agent/java-agent/README.md
index c316651..bd03984 100755
--- a/docs/en/setup/service-agent/java-agent/README.md
+++ b/docs/en/setup/service-agent/java-agent/README.md
@@ -131,9 +131,10 @@ Now, we have the following known optional plugins.
 * Plugin of Lettuce 5.x(JRE 8+) in optional plugin folder. Agent is compatible in JDK 1.6+, this plugin could be used in JRE 8+, by matching the lib requirement.
 * Plugin of Zookeeper 3.4.x in optional plugin folder. The reason of being optional plugin is, many business irrelevant traces are generated, which cause extra payload to agents and backends. At the same time, those traces may be just heartbeat(s).
 * [Customize enhance](Customize-enhance-trace.md) Trace methods based on description files, rather than write plugin or change source codes.
-* Plugin of Spring Cloud Gateway 2.1.x in optional plugin folder. Please only active this plugin when you install agent in Spring Gateway.
+* Plugin of Spring Cloud Gateway 2.1.x in optional plugin folder. Please only active this plugin when you install agent in Spring Gateway. spring-cloud-gateway-2.x-plugin and spring-webflux-5.x-plugin are both required.
 * Plugin of [Play Framework](https://www.playframework.com/) 2.6+ (JDK 1.8 required & Scala 2.12/2.13) in optional plugin folder. Please only active this plugin when you install agent in [Play Framework](https://www.playframework.com/). 
 * Plugin of Spring Transaction in optional plugin folder. The reason of being optional plugin is, many local span are generated, which also spend more CPU, memory and network.
+* Plugin of Spring Webflux 5.x in the optional plugin folder. Because the plugin requires JDK 1.8+.
 
 ## Bootstrap class plugins
 All bootstrap plugins are optional, due to unexpected risk. Bootstrap plugins are provided in `bootstrap-plugins` folder.
diff --git a/docs/en/setup/service-agent/java-agent/Supported-list.md b/docs/en/setup/service-agent/java-agent/Supported-list.md
index a9c12b4..2e1ad4c 100644
--- a/docs/en/setup/service-agent/java-agent/Supported-list.md
+++ b/docs/en/setup/service-agent/java-agent/Supported-list.md
@@ -9,7 +9,7 @@
   * [Resin](http://www.caucho.com/resin-4.0/) 3 (Optional¹)
   * [Resin](http://www.caucho.com/resin-4.0/) 4 (Optional¹)
   * [Jetty Server](http://www.eclipse.org/jetty/) 9
-  * [Spring Webflux](https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html) 5.x
+  * [Spring Webflux](https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html) 5.x (Optional²)
   * [Undertow](http://undertow.io/)  1.3.0.Final -> 2.0.27.Final
   * [RESTEasy](https://resteasy.github.io/)  3.1.0.Final -> 3.7.0.Final
   * [Play Framework](https://www.playframework.com/) 2.6.x -> 2.7.x (Optional²)
diff --git a/test/plugin/scenarios/gateway-scenario/config/expectedData.yaml b/test/plugin/scenarios/gateway-scenario/config/expectedData.yaml
index 6d8e834..395be6d 100644
--- a/test/plugin/scenarios/gateway-scenario/config/expectedData.yaml
+++ b/test/plugin/scenarios/gateway-scenario/config/expectedData.yaml
@@ -22,8 +22,8 @@ registryItems:
     - {gateway-projectB-scenario: 1}
     - {gateway-projectA-scenario: 1}
   operationNames:
-    - gateway-projectB-scenario: [/provider/b/healthCheck, /provider/b/testcase]
-    - gateway-projectA-scenario: [GATEWAY/provider_route]
+    - gateway-projectB-scenario: [/provider/b/testcase]
+    - gateway-projectA-scenario: [WEBFLUX.handle]
   heartbeat: []
 segmentItems:
   - applicationCode: gateway-projectB-scenario
@@ -47,6 +47,11 @@ segmentItems:
             tags:
               - {key: url, value: not null}
               - {key: http.method, value: GET}
+            refs:
+              - {parentEndpointId: -1, parentEndpoint: '', networkAddressId: 0,
+                 entryEndpointId: 0, refType: CrossProcess, parentSpanId: 0, parentTraceSegmentId: not null,
+                 parentServiceInstanceId: not null, networkAddress: 'localhost:18070', entryEndpoint: WEBFLUX.handle,
+                 entryServiceInstanceId: not null}
   - applicationCode: gateway-projectA-scenario
     segmentSize: nq 0
     segments:
@@ -69,13 +74,13 @@ segmentItems:
               - {key: url, value: not null}
               - {key: http.method, value: GET}
             refs:
-              - {parentEndpointId: 0, parentEndpoint: GATEWAY/provider_route, networkAddressId: 0,
+              - {parentEndpointId: 0, parentEndpoint: WEBFLUX.handle, networkAddressId: 0,
                  entryEndpointId: 0, refType: CrossThread, parentSpanId: 0, parentTraceSegmentId: not null,
-                 parentServiceInstanceId: not null, networkAddress: '', entryEndpoint: GATEWAY/provider_route,
+                 parentServiceInstanceId: not null, networkAddress: '', entryEndpoint: WEBFLUX.handle,
                  entryServiceInstanceId: not null}
       - segmentId: not null
         spans:
-          - operationName: GATEWAY/provider_route
+          - operationName: WEBFLUX.handle
             operationId: 0
             parentSpanId: -1
             spanId: 0
@@ -89,4 +94,6 @@ segmentItems:
             peer: ''
             peerId: 0
             tags:
-              - {key: url, value: not null}
\ No newline at end of file
+              - {key: url, value: 'http://localhost:8080/provider/b/testcase'}
+              - {key: http.method, value: GET}
+              - {key: status_code, value: '200'}
diff --git a/test/plugin/scenarios/gateway-scenario/configuration.yml b/test/plugin/scenarios/gateway-scenario/configuration.yml
index 40409eb..4aa0945 100644
--- a/test/plugin/scenarios/gateway-scenario/configuration.yml
+++ b/test/plugin/scenarios/gateway-scenario/configuration.yml
@@ -20,4 +20,4 @@ healthCheck: http://localhost:8080/provider/b/healthCheck
 startScript: ./bin/startup.sh
 framework: spring-cloud-gateway
 runningMode: with_optional
-withPlugins: apm-spring-cloud-gateway-2.x-plugin-*.jar
+withPlugins: apm-spring-cloud-gateway-2.x-plugin-*.jar;apm-spring-webflux-5.x-plugin-*.jar
diff --git a/test/plugin/scenarios/gateway-scenario/gateway-projectA-scenario/pom.xml b/test/plugin/scenarios/gateway-scenario/gateway-projectA-scenario/pom.xml
index 99654a6..23935da 100644
--- a/test/plugin/scenarios/gateway-scenario/gateway-projectA-scenario/pom.xml
+++ b/test/plugin/scenarios/gateway-scenario/gateway-projectA-scenario/pom.xml
@@ -39,6 +39,7 @@
             <artifactId>spring-boot-starter-data-redis</artifactId>
             <version>2.1.2.RELEASE</version>
         </dependency>
+
     </dependencies>
 
     <build>
@@ -69,4 +70,4 @@
             <url>http://repo.spring.io/milestone</url>
         </pluginRepository>
     </pluginRepositories>
-</project>
\ No newline at end of file
+</project>
diff --git a/test/plugin/scenarios/gateway-scenario/gateway-projectA-scenario/src/main/resources/application.yml b/test/plugin/scenarios/gateway-scenario/gateway-projectA-scenario/src/main/resources/application.yml
index 00e8ee3..ad477dc 100644
--- a/test/plugin/scenarios/gateway-scenario/gateway-projectA-scenario/src/main/resources/application.yml
+++ b/test/plugin/scenarios/gateway-scenario/gateway-projectA-scenario/src/main/resources/application.yml
@@ -33,4 +33,4 @@ spring:
             key-resolver: "#{@apiKeyResolver}"
   redis:
     host: 127.0.0.1
-    port:  6379
\ No newline at end of file
+    port:  6379
diff --git a/test/plugin/scenarios/webflux-scenario/config/expectedData.yaml b/test/plugin/scenarios/webflux-scenario/config/expectedData.yaml
index 9c29c6d..e84b03b 100644
--- a/test/plugin/scenarios/webflux-scenario/config/expectedData.yaml
+++ b/test/plugin/scenarios/webflux-scenario/config/expectedData.yaml
@@ -22,11 +22,7 @@ registryItems:
     - {webflux-projectB-scenario: 1}
     - {webflux-projectA-scenario: 1}
   operationNames:
-    - webflux-projectB-scenario: [org.apache.skywalking.apm.testcase.sc.webflux.projectB.controller.TestAnnotationController.success,
-                                  org.apache.skywalking.apm.testcase.sc.webflux.projectB.controller.TestAnnotationController.hello,
-                                  WEBFLUX.handle, org.apache.skywalking.apm.testcase.sc.webflux.projectB.controller.TestAnnotationController.error,
-                                  org.apache.skywalking.apm.testcase.sc.webflux.projectB.controller.TestAnnotationController.healthCheck,
-                                  RoutingConfiguration.org.apache.skywalking.apm.testcase.sc.webflux.projectB.route.TestHandler]
+    - webflux-projectB-scenario: [WEBFLUX.handle]
     - webflux-projectA-scenario: [/projectA/testcase]
   heartbeat: []
 segmentItems:
@@ -35,7 +31,7 @@ segmentItems:
     segments:
       - segmentId: not null
         spans:
-          - operationName: org.apache.skywalking.apm.testcase.sc.webflux.projectB.controller.TestAnnotationController.success
+          - operationName: /testcase/annotation/success
             operationId: 0
             parentSpanId: -1
             spanId: 0
@@ -49,15 +45,17 @@ segmentItems:
             peer: ''
             peerId: 0
             tags:
-              - {key: url, value: not null}
+              - {key: url, value: 'http://localhost:18080/testcase/annotation/success'}
+              - {key: http.method, value: GET}
+              - {key: status_code, value: '200'}
             refs:
               - {parentEndpointId: 0, parentEndpoint: /projectA/testcase, networkAddressId: 0,
-                 entryEndpointId: 0, refType: CrossProcess, parentSpanId: not null, parentTraceSegmentId: not null,
-                 parentServiceInstanceId: not null, networkAddress: not null, entryEndpoint: /projectA/testcase,
+                 entryEndpointId: 0, refType: CrossProcess, parentSpanId: 1, parentTraceSegmentId: not null,
+                 parentServiceInstanceId: not null, networkAddress: 'localhost:18080', entryEndpoint: /projectA/testcase,
                  entryServiceInstanceId: not null}
       - segmentId: not null
         spans:
-          - operationName: org.apache.skywalking.apm.testcase.sc.webflux.projectB.controller.TestAnnotationController.error
+          - operationName: /testcase/annotation/error
             operationId: 0
             parentSpanId: -1
             spanId: 0
@@ -71,22 +69,17 @@ segmentItems:
             peer: ''
             peerId: 0
             tags:
-              - {key: url, value: not null}
+              - {key: url, value: 'http://localhost:18080/testcase/annotation/error'}
+              - {key: http.method, value: GET}
               - {key: status_code, value: '500'}
-            logs:
-              - logEvent:
-                  - {key: event, value: error}
-                  - {key: error.kind, value: java.lang.RuntimeException}
-                  - {key: message, value: test_error}
-                  - {key: stack, value: not null}
             refs:
               - {parentEndpointId: 0, parentEndpoint: /projectA/testcase, networkAddressId: 0,
-                 entryEndpointId: 0, refType: CrossProcess, parentSpanId: not null, parentTraceSegmentId: not null,
-                 parentServiceInstanceId: not null, networkAddress: not null, entryEndpoint: /projectA/testcase,
+                 entryEndpointId: 0, refType: CrossProcess, parentSpanId: 2, parentTraceSegmentId: not null,
+                 parentServiceInstanceId: not null, networkAddress: 'localhost:18080', entryEndpoint: /projectA/testcase,
                  entryServiceInstanceId: not null}
       - segmentId: not null
         spans:
-          - operationName: RoutingConfiguration.org.apache.skywalking.apm.testcase.sc.webflux.projectB.route.TestHandler
+          - operationName: /testcase/annotation/{test}
             operationId: 0
             parentSpanId: -1
             spanId: 0
@@ -100,15 +93,65 @@ segmentItems:
             peer: ''
             peerId: 0
             tags:
-              - {key: url, value: not null}
+              - {key: url, value: 'http://localhost:18080/testcase/annotation/foo'}
+              - {key: http.method, value: GET}
+              - {key: status_code, value: '200'}
+            refs:
+              - {parentEndpointId: 0, parentEndpoint: /projectA/testcase, networkAddressId: 0,
+                 entryEndpointId: 0, refType: CrossProcess, parentSpanId: 3, parentTraceSegmentId: not null,
+                 parentServiceInstanceId: not null, networkAddress: 'localhost:18080', entryEndpoint: /projectA/testcase,
+                 entryServiceInstanceId: not null}
+      - segmentId: not null
+        spans:
+          - operationName: /testcase/annotation/{test}
+            operationId: 0
+            parentSpanId: -1
+            spanId: 0
+            spanLayer: Http
+            startTime: not null
+            endTime: not null
+            componentId: 67
+            componentName: ''
+            isError: false
+            spanType: Entry
+            peer: ''
+            peerId: 0
+            tags:
+              - {key: url, value: 'http://localhost:18080/testcase/annotation/loo'}
+              - {key: http.method, value: GET}
+              - {key: status_code, value: '200'}
+            refs:
+              - {parentEndpointId: 0, parentEndpoint: /projectA/testcase, networkAddressId: 0,
+                 entryEndpointId: 0, refType: CrossProcess, parentSpanId: 4, parentTraceSegmentId: not null,
+                 parentServiceInstanceId: not null, networkAddress: 'localhost:18080', entryEndpoint: /projectA/testcase,
+                 entryServiceInstanceId: not null}
+      - segmentId: not null
+        spans:
+          - operationName: /testcase/route/{test}
+            operationId: 0
+            parentSpanId: -1
+            spanId: 0
+            spanLayer: Http
+            startTime: not null
+            endTime: not null
+            componentId: 67
+            componentName: ''
+            isError: false
+            spanType: Entry
+            peer: ''
+            peerId: 0
+            tags:
+              - {key: url, value: 'http://localhost:18080/testcase/route/success'}
+              - {key: http.method, value: GET}
+              - {key: status_code, value: '200'}
             refs:
               - {parentEndpointId: 0, parentEndpoint: /projectA/testcase, networkAddressId: 0,
-                 entryEndpointId: 0, refType: CrossProcess, parentSpanId: not null, parentTraceSegmentId: not null,
-                 parentServiceInstanceId: not null, networkAddress: not null, entryEndpoint: /projectA/testcase,
+                 entryEndpointId: 0, refType: CrossProcess, parentSpanId: 5, parentTraceSegmentId: not null,
+                 parentServiceInstanceId: not null, networkAddress: 'localhost:18080', entryEndpoint: /projectA/testcase,
                  entryServiceInstanceId: not null}
       - segmentId: not null
         spans:
-          - operationName: RoutingConfiguration.org.apache.skywalking.apm.testcase.sc.webflux.projectB.route.TestHandler
+          - operationName: /testcase/route/{test}
             operationId: 0
             parentSpanId: -1
             spanId: 0
@@ -122,22 +165,17 @@ segmentItems:
             peer: ''
             peerId: 0
             tags:
-              - {key: url, value: not null}
+              - {key: url, value: 'http://localhost:18080/testcase/route/error'}
+              - {key: http.method, value: GET}
               - {key: status_code, value: '500'}
-            logs:
-              - logEvent:
-                  - {key: event, value: error}
-                  - {key: error.kind, value: java.lang.RuntimeException}
-                  - {key: message, value: test_error}
-                  - {key: stack, value: not null}
             refs:
               - {parentEndpointId: 0, parentEndpoint: /projectA/testcase, networkAddressId: 0,
-                 entryEndpointId: 0, refType: CrossProcess, parentSpanId: not null, parentTraceSegmentId: not null,
-                 parentServiceInstanceId: not null, networkAddress: not null, entryEndpoint: /projectA/testcase,
+                 entryEndpointId: 0, refType: CrossProcess, parentSpanId: 6, parentTraceSegmentId: not null,
+                 parentServiceInstanceId: not null, networkAddress: 'localhost:18080', entryEndpoint: /projectA/testcase,
                  entryServiceInstanceId: not null}
       - segmentId: not null
         spans:
-          - operationName: WEBFLUX.handle
+          - operationName: /**
             operationId: 0
             parentSpanId: -1
             spanId: 0
@@ -151,22 +189,17 @@ segmentItems:
             peer: ''
             peerId: 0
             tags:
-              - {key: url, value: not null}
+              - {key: url, value: 'http://localhost:18080/notFound'}
+              - {key: http.method, value: GET}
               - {key: status_code, value: '404'}
-            logs:
-              - logEvent:
-                  - {key: event, value: error}
-                  - {key: error.kind, value: org.springframework.web.server.ResponseStatusException}
-                  - {key: message, value: not null}
-                  - {key: stack, value: not null}
             refs:
               - {parentEndpointId: 0, parentEndpoint: /projectA/testcase, networkAddressId: 0,
-                 entryEndpointId: 0, refType: CrossProcess, parentSpanId: not null, parentTraceSegmentId: not null,
-                 parentServiceInstanceId: not null, networkAddress: not null, entryEndpoint: /projectA/testcase,
+                 entryEndpointId: 0, refType: CrossProcess, parentSpanId: 7, parentTraceSegmentId: not null,
+                 parentServiceInstanceId: not null, networkAddress: 'localhost:18080', entryEndpoint: /projectA/testcase,
                  entryServiceInstanceId: not null}
       - segmentId: not null
         spans:
-          - operationName: org.apache.skywalking.apm.testcase.sc.webflux.projectB.controller.TestAnnotationController.hello
+          - operationName: /testcase/annotation/mono/hello
             operationId: 0
             parentSpanId: -1
             spanId: 0
@@ -180,11 +213,13 @@ segmentItems:
             peer: ''
             peerId: 0
             tags:
-              - {key: url, value: not null}
+              - {key: url, value: 'http://localhost:18080/testcase/annotation/mono/hello'}
+              - {key: http.method, value: GET}
+              - {key: status_code, value: '200'}
             refs:
               - {parentEndpointId: 0, parentEndpoint: /projectA/testcase, networkAddressId: 0,
-                 entryEndpointId: 0, refType: CrossProcess, parentSpanId: not null, parentTraceSegmentId: not null,
-                 parentServiceInstanceId: not null, networkAddress: not null, entryEndpoint: /projectA/testcase,
+                 entryEndpointId: 0, refType: CrossProcess, parentSpanId: 8, parentTraceSegmentId: not null,
+                 parentServiceInstanceId: not null, networkAddress: 'localhost:18080', entryEndpoint: /projectA/testcase,
                  entryServiceInstanceId: not null}
   - applicationCode: webflux-projectA-scenario
     segmentSize: nq 0
@@ -224,7 +259,7 @@ segmentItems:
               - {key: url, value: not null}
               - {key: http.method, value: GET}
               - {key: status_code, value: '500'}
-          - operationName: /testcase/route/success
+          - operationName: /testcase/annotation/foo
             operationId: 0
             parentSpanId: 0
             spanId: 3
@@ -235,6 +270,38 @@ segmentItems:
             componentName: ''
             isError: false
             spanType: Exit
+            peer: localhost:18080
+            peerId: 0
+            tags:
+              - {key: url, value: 'http://localhost:18080/testcase/annotation/foo'}
+              - {key: http.method, value: GET}
+          - operationName: /testcase/annotation/loo
+            operationId: 0
+            parentSpanId: 0
+            spanId: 4
+            spanLayer: Http
+            startTime: not null
+            endTime: not null
+            componentId: 2
+            componentName: ''
+            isError: false
+            spanType: Exit
+            peer: localhost:18080
+            peerId: 0
+            tags:
+              - {key: url, value: 'http://localhost:18080/testcase/annotation/loo'}
+              - {key: http.method, value: GET}
+          - operationName: /testcase/route/success
+            operationId: 0
+            parentSpanId: 0
+            spanId: 5
+            spanLayer: Http
+            startTime: not null
+            endTime: not null
+            componentId: 2
+            componentName: ''
+            isError: false
+            spanType: Exit
             peer: not null
             peerId: 0
             tags:
@@ -243,7 +310,7 @@ segmentItems:
           - operationName: /testcase/route/error
             operationId: 0
             parentSpanId: 0
-            spanId: 4
+            spanId: 6
             spanLayer: Http
             startTime: not null
             endTime: not null
@@ -260,7 +327,7 @@ segmentItems:
           - operationName: /notFound
             operationId: 0
             parentSpanId: 0
-            spanId: 5
+            spanId: 7
             spanLayer: Http
             startTime: not null
             endTime: not null
@@ -277,7 +344,7 @@ segmentItems:
           - operationName: /testcase/annotation/mono/hello
             operationId: 0
             parentSpanId: 0
-            spanId: 6
+            spanId: 8
             spanLayer: Http
             startTime: not null
             endTime: not null
@@ -305,4 +372,4 @@ segmentItems:
             peerId: 0
             tags:
               - {key: url, value: not null}
-              - {key: http.method, value: GET}
\ No newline at end of file
+              - {key: http.method, value: GET}
diff --git a/test/plugin/scenarios/webflux-scenario/configuration.yml b/test/plugin/scenarios/webflux-scenario/configuration.yml
index 37b70f9..8a507cd 100644
--- a/test/plugin/scenarios/webflux-scenario/configuration.yml
+++ b/test/plugin/scenarios/webflux-scenario/configuration.yml
@@ -18,4 +18,6 @@ type: jvm
 entryService: http://localhost:8080/projectA/testcase
 healthCheck: http://localhost:8080/projectA/healthCheck
 startScript: ./bin/startup.sh
-framework: spring-webflux
\ No newline at end of file
+framework: spring-webflux
+runningMode: with_optional
+withPlugins: apm-spring-webflux-5.x-plugin-*.jar
diff --git a/test/plugin/scenarios/webflux-scenario/pom.xml b/test/plugin/scenarios/webflux-scenario/pom.xml
index 8502b98..dac1d59 100644
--- a/test/plugin/scenarios/webflux-scenario/pom.xml
+++ b/test/plugin/scenarios/webflux-scenario/pom.xml
@@ -35,7 +35,7 @@
 
     <properties>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-        <test.framework.version>2.0.0.RELEASE</test.framework.version>
+        <test.framework.version>2.1.1.RELEASE</test.framework.version>
         <docker.image.version>${test.framework.version}</docker.image.version>
     </properties>
 
diff --git a/test/plugin/scenarios/webflux-scenario/support-version.list b/test/plugin/scenarios/webflux-scenario/support-version.list
index 13e43a5..553ef8e 100644
--- a/test/plugin/scenarios/webflux-scenario/support-version.list
+++ b/test/plugin/scenarios/webflux-scenario/support-version.list
@@ -14,21 +14,12 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-2.0.0.RELEASE
-2.0.1.RELEASE
-2.0.2.RELEASE
-2.0.3.RELEASE
-2.0.4.RELEASE
-2.0.5.RELEASE
-2.0.6.RELEASE
-2.0.7.RELEASE
-2.0.8.RELEASE
-2.0.9.RELEASE
-2.1.0.RELEASE
+# 2.0.0-2.1.0 are supported, but due to the status code bug(https://github.com/spring-projects/spring-framework/issues/21901)
+# we don’t test them
 2.1.1.RELEASE
 2.1.2.RELEASE
 2.1.3.RELEASE
 2.1.4.RELEASE
 2.1.5.RELEASE
 2.1.6.RELEASE
-2.1.7.RELEASE
\ No newline at end of file
+2.1.7.RELEASE
diff --git a/test/plugin/scenarios/webflux-scenario/webflux-projectA-scenario/pom.xml b/test/plugin/scenarios/webflux-scenario/webflux-projectA-scenario/pom.xml
index 0d1389a..b8fecfd 100644
--- a/test/plugin/scenarios/webflux-scenario/webflux-projectA-scenario/pom.xml
+++ b/test/plugin/scenarios/webflux-scenario/webflux-projectA-scenario/pom.xml
@@ -59,14 +59,4 @@
         </plugins>
     </build>
 
-    <pluginRepositories>
-        <pluginRepository>
-            <id>spring-snapshots</id>
-            <url>http://repo.spring.io/snapshot</url>
-        </pluginRepository>
-        <pluginRepository>
-            <id>spring-milestones</id>
-            <url>http://repo.spring.io/milestone</url>
-        </pluginRepository>
-    </pluginRepositories>
-</project>
\ No newline at end of file
+</project>
diff --git a/test/plugin/scenarios/webflux-scenario/webflux-projectA-scenario/src/main/java/org/apache/skywalking/apm/testcase/sc/webflux/projectA/controller/TestController.java b/test/plugin/scenarios/webflux-scenario/webflux-projectA-scenario/src/main/java/org/apache/skywalking/apm/testcase/sc/webflux/projectA/controller/TestController.java
index 85cbffc..eff3593 100644
--- a/test/plugin/scenarios/webflux-scenario/webflux-projectA-scenario/src/main/java/org/apache/skywalking/apm/testcase/sc/webflux/projectA/controller/TestController.java
+++ b/test/plugin/scenarios/webflux-scenario/webflux-projectA-scenario/src/main/java/org/apache/skywalking/apm/testcase/sc/webflux/projectA/controller/TestController.java
@@ -38,6 +38,8 @@ public class TestController {
     public String testcase() throws IOException {
         visit("http://" + hostBAddress + "/testcase/annotation/success");
         visit("http://" + hostBAddress + "/testcase/annotation/error");
+        visit("http://" + hostBAddress + "/testcase/annotation/foo");
+        visit("http://" + hostBAddress + "/testcase/annotation/loo");
         visit("http://" + hostBAddress + "/testcase/route/success");
         visit("http://" + hostBAddress + "/testcase/route/error");
         visit("http://" + hostBAddress + "/notFound");
diff --git a/test/plugin/scenarios/webflux-scenario/webflux-projectB-scenario/src/main/java/org/apache/skywalking/apm/testcase/sc/webflux/projectB/controller/TestAnnotationController.java b/test/plugin/scenarios/webflux-scenario/webflux-projectB-scenario/src/main/java/org/apache/skywalking/apm/testcase/sc/webflux/projectB/controller/TestAnnotationController.java
index a9afbb5..2b45fe9 100644
--- a/test/plugin/scenarios/webflux-scenario/webflux-projectB-scenario/src/main/java/org/apache/skywalking/apm/testcase/sc/webflux/projectB/controller/TestAnnotationController.java
+++ b/test/plugin/scenarios/webflux-scenario/webflux-projectB-scenario/src/main/java/org/apache/skywalking/apm/testcase/sc/webflux/projectB/controller/TestAnnotationController.java
@@ -18,6 +18,7 @@
 package org.apache.skywalking.apm.testcase.sc.webflux.projectB.controller;
 
 import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
@@ -44,6 +45,11 @@ public class TestAnnotationController {
         return "1";
     }
 
+    @GetMapping("/testcase/annotation/{test}")
+    public Mono<String> urlPattern(@PathVariable("test") String var) {
+        return Mono.just(var);
+    }
+
     @GetMapping("/testcase/annotation/mono/hello")
     public Mono<String> hello(@RequestBody(required = false) String body) {
         return Mono.just("Hello World");