You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by ch...@apache.org on 2019/12/30 08:29:24 UTC

[servicecomb-toolkit] 01/03: [SCB-1673] parse the remaining information of RequestMapping

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

chanjarster pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-toolkit.git

commit 7ad21eedcbd22c028be3704e63a05b905a49b8cc
Author: kakulisen <18...@163.com>
AuthorDate: Thu Dec 19 16:26:10 2019 +0800

    [SCB-1673] parse the remaining information of RequestMapping
    
    Signed-off-by: kakulisen <18...@163.com>
---
 .../toolkit/generator/context/OasContext.java      | 40 +++++++++++
 .../generator/context/OperationContext.java        | 81 +++++++++++++++++++++-
 ...stractHttpMethodMappingAnnotationProcessor.java | 36 +++-------
 .../RequestMappingClassAnnotationProcessor.java    | 41 +++++++++++
 .../RequestMappingMethodAnnotationProcessor.java   | 25 ++++---
 .../generator/SpringAnnotationProcessorTest.java   | 25 ++++++-
 6 files changed, 207 insertions(+), 41 deletions(-)

diff --git a/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/context/OasContext.java b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/context/OasContext.java
index d1a80ff..90e1c47 100644
--- a/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/context/OasContext.java
+++ b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/context/OasContext.java
@@ -47,6 +47,14 @@ public class OasContext implements IExtensionsContext {
 
   private List<ISchemaContext> schemaCtxList = new ArrayList<>();
 
+  private String httpMethod;
+
+  private String[] consumers;
+
+  private String[] produces;
+
+  private String[] headers;
+
   public OasContext(OpenApiAnnotationParser parser) {
     this(new OpenAPI(), parser);
   }
@@ -162,4 +170,36 @@ public class OasContext implements IExtensionsContext {
   public Map<String, Object> getExtensions() {
     return openAPI.getExtensions();
   }
+
+  public String getHttpMethod() {
+    return httpMethod;
+  }
+
+  public void setHttpMethod(String httpMethod) {
+    this.httpMethod = httpMethod;
+  }
+
+  public String[] getConsumers() {
+    return consumers;
+  }
+
+  public void setConsumers(String[] consumers) {
+    this.consumers = consumers;
+  }
+
+  public String[] getProduces() {
+    return produces;
+  }
+
+  public void setProduces(String[] produces) {
+    this.produces = produces;
+  }
+
+  public String[] getHeaders() {
+    return headers;
+  }
+
+  public void setHeaders(String[] headers) {
+    this.headers = headers;
+  }
 }
diff --git a/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/context/OperationContext.java b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/context/OperationContext.java
index 6d36ccb..7941e54 100644
--- a/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/context/OperationContext.java
+++ b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/context/OperationContext.java
@@ -19,8 +19,10 @@ package org.apache.servicecomb.toolkit.generator.context;
 
 import java.lang.reflect.Method;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.stream.Collectors;
 
 import org.apache.commons.lang3.StringUtils;
@@ -37,6 +39,8 @@ import io.swagger.v3.oas.models.media.Content;
 import io.swagger.v3.oas.models.media.MediaType;
 import io.swagger.v3.oas.models.media.ObjectSchema;
 import io.swagger.v3.oas.models.media.Schema;
+import io.swagger.v3.oas.models.media.StringSchema;
+import io.swagger.v3.oas.models.parameters.HeaderParameter;
 import io.swagger.v3.oas.models.parameters.Parameter;
 import io.swagger.v3.oas.models.parameters.RequestBody;
 import io.swagger.v3.oas.models.responses.ApiResponse;
@@ -74,6 +78,10 @@ public class OperationContext implements IExtensionsContext {
 
   private String[] consumers;
 
+  private String[] produces;
+
+  private String[] headers;
+
   public OperationContext(Method method, OasContext parentContext) {
     this.parentContext = parentContext;
     this.method = method;
@@ -87,7 +95,7 @@ public class OperationContext implements IExtensionsContext {
   }
 
   public boolean hasOperation() {
-    return httpMethod != null && method != null;
+    return getHttpMethod() != null && method != null;
   }
 
   public Operation toOperation() {
@@ -101,6 +109,8 @@ public class OperationContext implements IExtensionsContext {
     }
 
     operation.operationId(operationId);
+    processHeaders();
+    processProduces();
     correctResponse(apiResponses);
     operation.setResponses(apiResponses);
 
@@ -156,6 +166,57 @@ public class OperationContext implements IExtensionsContext {
     return operation;
   }
 
+  private void processHeaders() {
+
+    if (headers == null) {
+      headers = parentContext.getHeaders();
+    }
+
+    if (headers == null) {
+      return;
+    }
+
+    Arrays.stream(headers).forEach(header -> {
+      String[] headMap = header.split("=");
+      if (headMap.length == 2) {
+        HeaderParameter headerParameter = new HeaderParameter();
+        headerParameter.setName(headMap[0]);
+        StringSchema value = new StringSchema();
+        value.setDefault(headMap[1]);
+        headerParameter.setSchema(value);
+        operation.addParametersItem(headerParameter);
+      }
+    });
+  }
+
+  private void processProduces() {
+
+    if (produces == null) {
+      produces = parentContext.getProduces();
+    }
+
+    if (produces == null) {
+      return;
+    }
+
+    List<String> produceList = Arrays.stream(produces).filter(s -> !StringUtils.isEmpty(s))
+        .collect(Collectors.toList());
+
+    if (!produceList.isEmpty()) {
+      ApiResponse apiResponse = new ApiResponse();
+      Content content = new Content();
+      MediaType mediaType = new MediaType();
+      Schema schema = ModelConverter
+          .getSchema(getMethod().getReturnType(), getComponents(), RequestResponse.RESPONSE);
+      mediaType.schema(schema);
+      for (String produce : produceList) {
+        content.addMediaType(produce, mediaType);
+      }
+      apiResponse.setContent(content);
+      addResponse(HttpStatuses.OK, apiResponse);
+    }
+  }
+
   public void setRequestBody(RequestBody requestBody) {
     operation.requestBody(requestBody);
   }
@@ -238,7 +299,7 @@ public class OperationContext implements IExtensionsContext {
   }
 
   public String getHttpMethod() {
-    return httpMethod;
+    return Optional.ofNullable(httpMethod).orElse(parentContext.getHttpMethod());
   }
 
   public void setHttpMethod(String httpMethod) {
@@ -308,4 +369,20 @@ public class OperationContext implements IExtensionsContext {
   public void addParamCtx(ParameterContext ctx) {
     this.parameterContexts.add(ctx);
   }
+
+  public String[] getProduces() {
+    return produces;
+  }
+
+  public void setProduces(String[] produces) {
+    this.produces = produces;
+  }
+
+  public String[] getHeaders() {
+    return headers;
+  }
+
+  public void setHeaders(String[] headers) {
+    this.headers = headers;
+  }
 }
diff --git a/oas-generator/oas-generator-spring/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/AbstractHttpMethodMappingAnnotationProcessor.java b/oas-generator/oas-generator-spring/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/AbstractHttpMethodMappingAnnotationProcessor.java
index 526b3c6..4205b70 100644
--- a/oas-generator/oas-generator-spring/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/AbstractHttpMethodMappingAnnotationProcessor.java
+++ b/oas-generator/oas-generator-spring/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/AbstractHttpMethodMappingAnnotationProcessor.java
@@ -17,22 +17,9 @@
 
 package org.apache.servicecomb.toolkit.generator.annotation;
 
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Collectors;
-
-import org.apache.servicecomb.toolkit.generator.HttpStatuses;
 import org.apache.servicecomb.toolkit.generator.context.OperationContext;
-import org.apache.servicecomb.toolkit.generator.util.ModelConverter;
-import org.apache.servicecomb.toolkit.generator.util.RequestResponse;
-import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.RequestMethod;
 
-import io.swagger.v3.oas.models.media.Content;
-import io.swagger.v3.oas.models.media.MediaType;
-import io.swagger.v3.oas.models.media.Schema;
-import io.swagger.v3.oas.models.responses.ApiResponse;
-
 public abstract class AbstractHttpMethodMappingAnnotationProcessor<Annotation, Context> implements
     MethodAnnotationProcessor<Annotation, Context> {
 
@@ -58,6 +45,8 @@ public abstract class AbstractHttpMethodMappingAnnotationProcessor<Annotation, C
     if (null == consumes || consumes.length == 0) {
       return;
     }
+
+    operationContext.setConsumers(consumes);
   }
 
   protected void processProduces(String[] produces, OperationContext operationContext) {
@@ -65,22 +54,13 @@ public abstract class AbstractHttpMethodMappingAnnotationProcessor<Annotation, C
       return;
     }
 
-    List<String> produceList = Arrays.stream(produces).filter(s -> !StringUtils.isEmpty(s))
-        .collect(Collectors.toList());
+    operationContext.setProduces(produces);
+  }
 
-    if (!produceList.isEmpty()) {
-      ApiResponse apiResponse = new ApiResponse();
-      Content content = new Content();
-      MediaType mediaType = new MediaType();
-      Schema schema = ModelConverter
-          .getSchema(operationContext.getMethod().getReturnType(), operationContext.getComponents(),
-              RequestResponse.RESPONSE);
-      mediaType.schema(schema);
-      for (String produce : produceList) {
-        content.addMediaType(produce, mediaType);
-      }
-      apiResponse.setContent(content);
-      operationContext.addResponse(HttpStatuses.OK, apiResponse);
+  protected void processHeaders(String[] headers, OperationContext operationContext) {
+    if (null == headers || headers.length == 0) {
+      return;
     }
+    operationContext.setHeaders(headers);
   }
 }
diff --git a/oas-generator/oas-generator-spring/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/RequestMappingClassAnnotationProcessor.java b/oas-generator/oas-generator-spring/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/RequestMappingClassAnnotationProcessor.java
index ad01f16..860a11b 100644
--- a/oas-generator/oas-generator-spring/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/RequestMappingClassAnnotationProcessor.java
+++ b/oas-generator/oas-generator-spring/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/RequestMappingClassAnnotationProcessor.java
@@ -19,6 +19,7 @@ package org.apache.servicecomb.toolkit.generator.annotation;
 
 import org.apache.servicecomb.toolkit.generator.context.OasContext;
 import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
 
 public class RequestMappingClassAnnotationProcessor implements
     ClassAnnotationProcessor<RequestMapping, OasContext> {
@@ -37,5 +38,45 @@ public class RequestMappingClassAnnotationProcessor implements
     }
 
     oasContext.setBasePath(paths[0]);
+
+    processMethod(requestMapping.method(), oasContext);
+    processConsumes(requestMapping.consumes(), oasContext);
+    processProduces(requestMapping.produces(), oasContext);
+    processHeaders(requestMapping.headers(), oasContext);
+  }
+
+  protected void processMethod(RequestMethod[] requestMethods, OasContext oasContext) {
+    if (null == requestMethods || requestMethods.length == 0) {
+      return;
+    }
+
+    if (requestMethods.length > 1) {
+      throw new Error(
+          "not allowed multi http method for " + oasContext.getCls().getName());
+    }
+
+    oasContext.setHttpMethod(requestMethods[0].name());
+  }
+
+  protected void processConsumes(String[] consumes, OasContext oasContext) {
+    if (null == consumes || consumes.length == 0) {
+      return;
+    }
+    oasContext.setConsumers(consumes);
+  }
+
+  protected void processProduces(String[] produces, OasContext oasContext) {
+    if (null == produces || produces.length == 0) {
+      return;
+    }
+    oasContext.setProduces(produces);
+  }
+
+  protected void processHeaders(String[] headers, OasContext oasContext) {
+    if (null == headers || headers.length == 0) {
+      return;
+    }
+    oasContext.setHeaders(headers);
   }
 }
+
diff --git a/oas-generator/oas-generator-spring/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/RequestMappingMethodAnnotationProcessor.java b/oas-generator/oas-generator-spring/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/RequestMappingMethodAnnotationProcessor.java
index 040f559..06b6e65 100644
--- a/oas-generator/oas-generator-spring/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/RequestMappingMethodAnnotationProcessor.java
+++ b/oas-generator/oas-generator-spring/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/RequestMappingMethodAnnotationProcessor.java
@@ -19,23 +19,32 @@ package org.apache.servicecomb.toolkit.generator.annotation;
 
 import org.apache.servicecomb.toolkit.generator.context.OperationContext;
 import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
 
-public class RequestMappingMethodAnnotationProcessor implements
-    MethodAnnotationProcessor<RequestMapping, OperationContext> {
+public class RequestMappingMethodAnnotationProcessor extends
+    AbstractHttpMethodMappingAnnotationProcessor<RequestMapping, OperationContext> {
 
   @Override
   public void process(RequestMapping requestMapping, OperationContext operationContext) {
 
-    String[] paths = requestMapping.value();
-    if (null == paths || paths.length == 0) {
+    this.processPath(requestMapping.path(), operationContext);
+    this.processPath(requestMapping.value(), operationContext);
+    this.processMethod(requestMapping.method(), operationContext);
+    this.processConsumes(requestMapping.consumes(), operationContext);
+    this.processProduces(requestMapping.produces(), operationContext);
+    this.processHeaders(requestMapping.headers(), operationContext);
+  }
+
+  protected void processMethod(RequestMethod[] requestMethods, OperationContext operationContext) {
+    if (null == requestMethods || requestMethods.length == 0) {
       return;
     }
 
-    // swagger only support one basePath
-    if (paths.length > 1) {
-      throw new Error("not support multi path for " + operationContext.getMethod().getName());
+    if (requestMethods.length > 1) {
+      throw new Error(
+          "not allowed multi http method for " + operationContext.getMethod().getName());
     }
 
-    operationContext.setPath(paths[0]);
+    this.processMethod(requestMethods[0], operationContext);
   }
 }
diff --git a/oas-generator/oas-generator-spring/src/test/java/org/apache/servicecomb/toolkit/generator/SpringAnnotationProcessorTest.java b/oas-generator/oas-generator-spring/src/test/java/org/apache/servicecomb/toolkit/generator/SpringAnnotationProcessorTest.java
index adfd48a..3cad49b 100644
--- a/oas-generator/oas-generator-spring/src/test/java/org/apache/servicecomb/toolkit/generator/SpringAnnotationProcessorTest.java
+++ b/oas-generator/oas-generator-spring/src/test/java/org/apache/servicecomb/toolkit/generator/SpringAnnotationProcessorTest.java
@@ -34,6 +34,7 @@ import org.apache.servicecomb.toolkit.generator.annotation.RequestPartAnnotation
 import org.apache.servicecomb.toolkit.generator.context.OasContext;
 import org.apache.servicecomb.toolkit.generator.context.OperationContext;
 import org.apache.servicecomb.toolkit.generator.context.ParameterContext;
+import org.apache.servicecomb.toolkit.generator.parser.SpringmvcAnnotationParser;
 import org.junit.Assert;
 import org.junit.Test;
 import org.springframework.web.bind.annotation.DeleteMapping;
@@ -44,6 +45,7 @@ import org.springframework.web.bind.annotation.PutMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestHeader;
 import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RequestPart;
 import org.springframework.web.bind.annotation.RestController;
@@ -55,13 +57,15 @@ public class SpringAnnotationProcessorTest {
 
   @Test
   public void getHttpMethod() throws NoSuchMethodException {
+    SpringmvcAnnotationParser parser = new SpringmvcAnnotationParser();
 
-    OasContext oasContext = new OasContext(null);
+    OasContext oasContext = new OasContext(parser);
     Class<HttpMethodResource> httpMethodResourceClass = HttpMethodResource.class;
     RequestMapping requestMappingClassAnnotation = httpMethodResourceClass.getAnnotation(RequestMapping.class);
     RequestMappingClassAnnotationProcessor requestMappingClassAnnotationProcessor = new RequestMappingClassAnnotationProcessor();
     requestMappingClassAnnotationProcessor.process(requestMappingClassAnnotation, oasContext);
     Assert.assertEquals(requestMappingClassAnnotation.value()[0], oasContext.getBasePath());
+    Assert.assertEquals(RequestMethod.GET.name(), oasContext.getHttpMethod());
 
     RequestMappingMethodAnnotationProcessor requestMappingMethodAnnotationProcessor = new RequestMappingMethodAnnotationProcessor();
     Method requestMethod = httpMethodResourceClass.getMethod("request");
@@ -71,6 +75,16 @@ public class SpringAnnotationProcessorTest {
     Assert
         .assertEquals(requestMappingMethodAnnotation.value()[0],
             requestOperationContext.getPath());
+    Assert.assertEquals(RequestMethod.POST.name(), requestOperationContext.getHttpMethod());
+
+    Method getRequestMethod = httpMethodResourceClass.getMethod("getRequest");
+    RequestMapping getRequestMappingMethodAnnotation = getRequestMethod.getAnnotation(RequestMapping.class);
+    OperationContext getRequestOperationContext = new OperationContext(getRequestMethod, oasContext);
+    requestMappingMethodAnnotationProcessor.process(getRequestMappingMethodAnnotation, getRequestOperationContext);
+    Assert
+        .assertEquals(getRequestMappingMethodAnnotation.value()[0],
+            getRequestOperationContext.getPath());
+    Assert.assertEquals(RequestMethod.GET.name(), getRequestOperationContext.getHttpMethod());
 
     GetMappingMethodAnnotationProcessor getMappingMethodAnnotationProcessor = new GetMappingMethodAnnotationProcessor();
     Method getMethod = httpMethodResourceClass.getMethod("get");
@@ -178,14 +192,19 @@ public class SpringAnnotationProcessorTest {
   }
 
   @RestController
-  @RequestMapping("/path")
+  @RequestMapping(value = "/path", method = RequestMethod.GET)
   class HttpMethodResource {
 
-    @RequestMapping("/request")
+    @RequestMapping(value = "/request", method = RequestMethod.POST, headers = "cookie=1")
     public String request() {
       return "request";
     }
 
+    @RequestMapping(value = "/getRequest")
+    public String getRequest() {
+      return "getRequest";
+    }
+
     @GetMapping(value = "/get", consumes = {"application/json"}, produces = {"application/json"})
     public String get() {
       return "get";