diff --git a/pom.xml b/pom.xml
index 4a5895f..a4d41a9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -376,6 +376,11 @@
0.10.2
+
+ io.swagger.parser.v3
+ swagger-parser
+ 2.1.25
+
diff --git a/src/main/java/com/guwan/backend/controller/DemoController.java b/src/main/java/com/guwan/backend/controller/DemoController.java
index 24a82fb..d5b054b 100644
--- a/src/main/java/com/guwan/backend/controller/DemoController.java
+++ b/src/main/java/com/guwan/backend/controller/DemoController.java
@@ -6,19 +6,23 @@ import com.guwan.backend.elasticsearch.document.ProductDocument;
import com.guwan.backend.elasticsearch.mapper.ProductEsMapper;
import com.guwan.backend.mongodb.CategoryService;
import com.guwan.backend.mongodb.FileStorageService;
+import com.guwan.backend.service.SwaggerAutoFillService;
import com.guwan.backend.util.MinioUtil;
import com.mongodb.client.gridfs.model.GridFSFile;
import io.minio.MinioClient;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
+import org.apache.hadoop.thirdparty.protobuf.Api;
import org.elasticsearch.search.SearchHit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
+import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
+import java.util.ArrayList;
import java.util.List;
@Slf4j
@@ -42,6 +46,10 @@ public class DemoController {
private final FileStorageService fileStorageService;
private final CategoryService categoryService;
+
+ private final RestTemplate restTemplate;
+
+ private final SwaggerAutoFillService swaggerAutoFillService;
@PostMapping("/uploadFile")
public Result uploadFile(String bucketName, MultipartFile file){
return Result.success(minioUtil.getUrl(minioUtil.getFileUrl
@@ -126,5 +134,17 @@ public class DemoController {
System.out.println("categoryService.getAllCategories() = " + categoryService.getAllCategories());
}
+ @GetMapping("/testSwagger")
+ public void testSwagger(){
+ Object forObject = restTemplate.getForObject("http://localhost:8084/v3/api-docs", Object.class);
+ System.out.println("forObject = " + forObject);
+ }
+
+
+ @GetMapping("/parseSwagger")
+ public void parseSwagger(){
+ swaggerAutoFillService.parseSwagger();
+ }
+
}
diff --git a/src/main/java/com/guwan/backend/pojo/dto/Api.java b/src/main/java/com/guwan/backend/pojo/dto/Api.java
new file mode 100644
index 0000000..fd75db3
--- /dev/null
+++ b/src/main/java/com/guwan/backend/pojo/dto/Api.java
@@ -0,0 +1,46 @@
+/*
+package com.guwan.backend.pojo.dto;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Data
+@TableName("apis")
+public class Api {
+ @TableId(type = IdType.AUTO)
+ private Long id;
+
+ private String name;
+ private String method;
+ private String url;
+ private Long projectId;
+
+ @TableField(typeHandler = JacksonTypeHandler.class)
+ private List headers;
+
+ @TableField(typeHandler = JacksonTypeHandler.class)
+ private List queryParams;
+
+ private String bodyType;
+
+ @TableField(typeHandler = JacksonTypeHandler.class)
+ private List formParams;
+
+ @TableField(columnDefinition = "text")
+ private String requestSchema;
+
+ @TableField(columnDefinition = "text")
+ private String responseSchema;
+
+ @TableField(typeHandler = JacksonTypeHandler.class)
+ private TestCaseGenerationRules generationRules;
+
+ @TableField(fill = FieldFill.INSERT)
+ private LocalDateTime createTime;
+
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private LocalDateTime updateTime;
+}*/
diff --git a/src/main/java/com/guwan/backend/service/SwaggerAutoFillService.java b/src/main/java/com/guwan/backend/service/SwaggerAutoFillService.java
new file mode 100644
index 0000000..26a6593
--- /dev/null
+++ b/src/main/java/com/guwan/backend/service/SwaggerAutoFillService.java
@@ -0,0 +1,82 @@
+package com.guwan.backend.service;
+
+
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.PathItem;
+import io.swagger.v3.oas.models.media.Schema;
+import io.swagger.v3.oas.models.responses.ApiResponse;
+import io.swagger.v3.oas.models.responses.ApiResponses;
+import io.swagger.v3.oas.models.Operation;
+import io.swagger.v3.parser.OpenAPIV3Parser;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Service
+public class SwaggerAutoFillService {
+
+ private static final String SWAGGER_URL = "http://127.0.0.1:8084/v3/api-docs";
+ private final RestTemplate restTemplate = new RestTemplate();
+
+ /**
+ * 解析 Swagger,自动提取接口字段
+ */
+ public void parseSwagger() {
+ OpenAPI openAPI = new OpenAPIV3Parser().read(SWAGGER_URL);
+
+ // 遍历所有 API 接口
+ openAPI.getPaths().forEach((path, pathItem) -> {
+ System.out.println("解析接口: " + path);
+
+ // 处理不同类型的 HTTP 方法
+ for (PathItem.HttpMethod method : pathItem.readOperationsMap().keySet()) {
+ Operation operation = pathItem.readOperationsMap().get(method);
+ ApiResponses responses = operation.getResponses();
+
+ // 解析返回字段
+ responses.forEach((code, response) -> extractResponseFields(response, path));
+ }
+ });
+ }
+
+
+ private void extractResponseFields(ApiResponse response, String path) {
+ if (response.getContent() != null) {
+ for (String contentType : response.getContent().keySet()) {
+ Schema> schema = response.getContent().get(contentType).getSchema();
+
+ if (schema != null) {
+ System.out.println("接口 " + path + " (" + contentType + ") 返回字段: ");
+ parseSchema(schema, "");
+ }
+ }
+ }
+ }
+
+ /**
+ * 提取 API 返回字段
+ */
+ /**
+ * 递归解析 Schema,支持复杂对象和嵌套结构
+ */
+ private void parseSchema(Schema> schema, String parentKey) {
+ if (schema.getProperties() != null) {
+ for (Map.Entry entry : schema.getProperties().entrySet()) {
+ String fieldName = parentKey.isEmpty() ? entry.getKey() : parentKey + "." + entry.getKey();
+ System.out.println(" - " + fieldName + " : " + entry.getValue().getType());
+
+ // 递归解析子对象
+ parseSchema(entry.getValue(), fieldName);
+ }
+ } else if (schema.getType() != null && schema.getType().equals("array")) {
+ // 处理数组类型
+ Schema> itemsSchema = schema.getItems();
+ System.out.println(" - " + parentKey + "[] : " + (itemsSchema != null ? itemsSchema.getType() : "Unknown"));
+ if (itemsSchema != null) {
+ parseSchema(itemsSchema, parentKey + "[]");
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/guwan/backend/service/SwaggerImportService.java b/src/main/java/com/guwan/backend/service/SwaggerImportService.java
new file mode 100644
index 0000000..82c5824
--- /dev/null
+++ b/src/main/java/com/guwan/backend/service/SwaggerImportService.java
@@ -0,0 +1,179 @@
+/*
+package com.guwan.backend.service;
+
+import org.apache.hadoop.thirdparty.protobuf.Api;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+@Service
+@Slf4j
+public class SwaggerImportService {
+
+ @Autowired
+ private ApiRepository apiRepository;
+
+ public List importFromSwagger(String swaggerJson) {
+ List apis = new ArrayList<>();
+ try {
+ ObjectMapper mapper = new ObjectMapper();
+ JsonNode root = mapper.readTree(swaggerJson);
+
+ // 获取所有路径
+ JsonNode paths = root.get("paths");
+ if (paths != null) {
+ paths.fields().forEachRemaining(path -> {
+ String url = path.getKey();
+ JsonNode methods = path.getValue();
+
+ methods.fields().forEachRemaining(method -> {
+ Api api = parseApiFromSwagger(url, method.getKey(), method.getValue());
+ apis.add(api);
+ });
+ });
+ }
+ } catch (Exception e) {
+ log.error("解析Swagger文档失败", e);
+ throw new RuntimeException("解析Swagger文档失败", e);
+ }
+ return apis;
+ }
+
+ private Api parseApiFromSwagger(String url, String method, JsonNode operation) {
+ Api api = new Api();
+ api.setUrl(url);
+ api.setMethod(HttpMethod.valueOf(method.toUpperCase()));
+ api.setName(operation.get("summary").asText());
+
+ // 解析请求参数
+ List parameters = new ArrayList<>();
+ JsonNode params = operation.get("parameters");
+ if (params != null) {
+ params.forEach(param -> {
+ RequestParameter parameter = new RequestParameter();
+ parameter.setName(param.get("name").asText());
+ parameter.setDescription(param.get("description").asText());
+ parameter.setRequired(param.get("required").asBoolean());
+ parameter.setType(parseParameterType(param.get("schema")));
+
+ String in = param.get("in").asText();
+ if ("query".equals(in)) {
+ if (api.getQueryParams() == null) {
+ api.setQueryParams(new ArrayList<>());
+ }
+ api.getQueryParams().add(parameter);
+ } else if ("header".equals(in)) {
+ RequestHeader header = new RequestHeader();
+ header.setKey(parameter.getName());
+ header.setDescription(parameter.getDescription());
+ header.setRequired(parameter.isRequired());
+ if (api.getHeaders() == null) {
+ api.setHeaders(new ArrayList<>());
+ }
+ api.getHeaders().add(header);
+ }
+ });
+ }
+
+ // 解析请求体
+ JsonNode requestBody = operation.get("requestBody");
+ if (requestBody != null) {
+ JsonNode content = requestBody.get("content");
+ if (content.has("application/json")) {
+ api.setBodyType(BodyType.JSON);
+ api.setRequestSchema(content.get("application/json")
+ .get("schema").toString());
+ } else if (content.has("application/x-www-form-urlencoded")) {
+ api.setBodyType(BodyType.FORM);
+ JsonNode formSchema = content.get("application/x-www-form-urlencoded")
+ .get("schema");
+ api.setFormParams(parseFormParameters(formSchema));
+ }
+ }
+
+ // 解析响应
+ JsonNode responses = operation.get("responses");
+ if (responses != null && responses.has("200")) {
+ JsonNode okResponse = responses.get("200");
+ if (okResponse.has("content") &&
+ okResponse.get("content").has("application/json")) {
+ api.setResponseSchema(okResponse.get("content")
+ .get("application/json")
+ .get("schema").toString());
+ }
+ }
+
+ // 设置自动生成测试用例的规则
+ api.setGenerationRules(createDefaultGenerationRules());
+
+ return api;
+ }
+
+ private ParamType parseParameterType(JsonNode schema) {
+ String type = schema.get("type").asText();
+ switch (type) {
+ case "integer":
+ case "number":
+ return ParamType.NUMBER;
+ case "boolean":
+ return ParamType.BOOLEAN;
+ case "array":
+ return ParamType.ARRAY;
+ case "object":
+ return ParamType.OBJECT;
+ default:
+ return ParamType.STRING;
+ }
+ }
+
+ private List parseFormParameters(JsonNode schema) {
+ List params = new ArrayList<>();
+ JsonNode properties = schema.get("properties");
+ JsonNode required = schema.get("required");
+
+ properties.fields().forEachRemaining(field -> {
+ RequestParameter param = new RequestParameter();
+ param.setName(field.getKey());
+ JsonNode property = field.getValue();
+ param.setType(parseParameterType(property));
+ param.setDescription(property.get("description").asText());
+ param.setRequired(required != null && required.toString()
+ .contains(field.getKey()));
+
+ if (property.has("format")) {
+ param.setFormat(property.get("format").asText());
+ }
+ if (property.has("pattern")) {
+ param.setPattern(property.get("pattern").asText());
+ }
+ if (property.has("minimum")) {
+ param.setMinimum(property.get("minimum").asText());
+ }
+ if (property.has("maximum")) {
+ param.setMaximum(property.get("maximum").asText());
+ }
+ if (property.has("enum")) {
+ List enumValues = new ArrayList<>();
+ property.get("enum").forEach(v -> enumValues.add(v.asText()));
+ param.setEnumValues(enumValues);
+ }
+
+ params.add(param);
+ });
+
+ return params;
+ }
+
+ private TestCaseGenerationRules createDefaultGenerationRules() {
+ TestCaseGenerationRules rules = new TestCaseGenerationRules();
+ rules.setEnabled(true);
+ rules.setStrategies(Arrays.asList(
+ GenerationStrategy.REQUIRED_ONLY,
+ GenerationStrategy.ALL_PARAMS,
+ GenerationStrategy.NULL_EMPTY_VALUES
+ ));
+ return rules;
+ }
+}*/
diff --git a/src/main/java/com/guwan/backend/service/TestDataAutoFillService.java b/src/main/java/com/guwan/backend/service/TestDataAutoFillService.java
new file mode 100644
index 0000000..4a88c51
--- /dev/null
+++ b/src/main/java/com/guwan/backend/service/TestDataAutoFillService.java
@@ -0,0 +1,34 @@
+package com.guwan.backend.service;
+
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Map;
+
+@Service
+public class TestDataAutoFillService {
+ private final RestTemplate restTemplate = new RestTemplate();
+
+ /**
+ * 自动获取前置 API 数据
+ */
+ public Map getPreConditionData(String apiUrl) {
+ return restTemplate.getForObject(apiUrl, Map.class);
+ }
+
+ /**
+ * 自动填充接口的入参
+ */
+ public Map autoFillTestCase(String apiUrl, Map inputParams) {
+ Map preData = getPreConditionData(apiUrl);
+
+ // 遍历 API 参数,自动填充依赖字段
+ for (String key : inputParams.keySet()) {
+ if (preData.containsKey(key)) {
+ inputParams.put(key, preData.get(key));
+ }
+ }
+
+ return inputParams;
+ }
+}
diff --git a/src/main/java/com/guwan/backend/swagger/SwaggerAPIParser.java b/src/main/java/com/guwan/backend/swagger/SwaggerAPIParser.java
new file mode 100644
index 0000000..1178f40
--- /dev/null
+++ b/src/main/java/com/guwan/backend/swagger/SwaggerAPIParser.java
@@ -0,0 +1,51 @@
+package com.guwan.backend.swagger;
+
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.PathItem;
+import io.swagger.v3.oas.models.Operation;
+import io.swagger.v3.oas.models.media.Schema;
+import io.swagger.v3.parser.OpenAPIV3Parser;
+
+import java.util.Map;
+
+public class SwaggerAPIParser {
+
+ private static final String SWAGGER_URL = "http://127.0.0.1:8084/v3/api-docs";
+
+ public static void parseAPI() {
+ OpenAPI openAPI = new OpenAPIV3Parser().read(SWAGGER_URL);
+
+
+ System.out.println("openAPI = " + openAPI);
+
+ /* openAPI.getPaths().forEach((path, pathItem) -> {
+ for (PathItem.HttpMethod method : pathItem.readOperationsMap().keySet()) {
+ Operation operation = pathItem.readOperationsMap().get(method);
+
+ System.out.println("接口:" + method + " " + path);
+
+ // 解析 Query & Path 参数
+ Map queryParams = SwaggerQueryParamParser.extractQueryParameters(operation.getParameters());
+ queryParams.forEach((key, value) -> System.out.println(" - 参数:" + key + " 类型:" + value));
+
+ // 解析请求体
+ if (operation.getRequestBody() != null) {
+ Schema> bodySchema = SwaggerRequestBodyParser.extractRequestBodySchema(operation.getRequestBody(), openAPI);
+ System.out.println(" - 请求体:" + bodySchema.getProperties());
+ }
+
+ // 解析响应体
+ Schema> responseSchema = SwaggerResponseParser.extractResponseSchema(operation.getResponses(), openAPI);
+ if (responseSchema != null) {
+ System.out.println(" - 响应数据:" + responseSchema.getProperties());
+ }
+
+ System.out.println("=================================");
+ }
+ });*/
+ }
+
+ public static void main(String[] args) {
+ parseAPI();
+ }
+}
diff --git a/src/main/java/com/guwan/backend/swagger/SwaggerQueryParamParser.java b/src/main/java/com/guwan/backend/swagger/SwaggerQueryParamParser.java
new file mode 100644
index 0000000..4c32d06
--- /dev/null
+++ b/src/main/java/com/guwan/backend/swagger/SwaggerQueryParamParser.java
@@ -0,0 +1,25 @@
+package com.guwan.backend.swagger;
+
+import io.swagger.v3.oas.models.parameters.Parameter;
+import io.swagger.v3.oas.models.media.Schema;
+import io.swagger.v3.oas.models.OpenAPI;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class SwaggerQueryParamParser {
+
+ public static Map extractQueryParameters(List parameters) {
+ Map paramMap = new HashMap<>();
+ if (parameters != null) {
+ for (Parameter param : parameters) {
+ String name = param.getName();
+ Schema> schema = param.getSchema();
+ String type = (schema != null) ? schema.getType() : "unknown";
+ paramMap.put(name, type);
+ }
+ }
+ return paramMap;
+ }
+}
diff --git a/src/main/java/com/guwan/backend/swagger/SwaggerRequestBodyParser.java b/src/main/java/com/guwan/backend/swagger/SwaggerRequestBodyParser.java
new file mode 100644
index 0000000..a487c3c
--- /dev/null
+++ b/src/main/java/com/guwan/backend/swagger/SwaggerRequestBodyParser.java
@@ -0,0 +1,31 @@
+package com.guwan.backend.swagger;
+
+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.parameters.RequestBody;
+import io.swagger.v3.oas.models.OpenAPI;
+
+import java.util.Map;
+
+public class SwaggerRequestBodyParser {
+
+ public static Schema> extractRequestBodySchema(RequestBody requestBody, OpenAPI openAPI) {
+ if (requestBody != null) {
+ Content content = requestBody.getContent();
+ for (Map.Entry entry : content.entrySet()) {
+ Schema> schema = entry.getValue().getSchema();
+ return resolveSchema(schema, openAPI);
+ }
+ }
+ return null;
+ }
+
+ private static Schema> resolveSchema(Schema> schema, OpenAPI openAPI) {
+ if (schema != null && schema.get$ref() != null) {
+ String refName = schema.get$ref().replace("#/components/schemas/", "");
+ return openAPI.getComponents().getSchemas().get(refName);
+ }
+ return schema;
+ }
+}
diff --git a/src/main/java/com/guwan/backend/swagger/SwaggerResponseParser.java b/src/main/java/com/guwan/backend/swagger/SwaggerResponseParser.java
new file mode 100644
index 0000000..a6a7e22
--- /dev/null
+++ b/src/main/java/com/guwan/backend/swagger/SwaggerResponseParser.java
@@ -0,0 +1,32 @@
+package com.guwan.backend.swagger;
+
+import io.swagger.v3.oas.models.media.Schema;
+import io.swagger.v3.oas.models.responses.ApiResponse;
+import io.swagger.v3.oas.models.responses.ApiResponses;
+import io.swagger.v3.oas.models.OpenAPI;
+
+import java.util.Map;
+
+public class SwaggerResponseParser {
+
+ public static Schema> extractResponseSchema(ApiResponses responses, OpenAPI openAPI) {
+ if (responses != null && responses.containsKey("200")) {
+ ApiResponse response = responses.get("200");
+ if (response.getContent() != null) {
+ for (Map.Entry entry : response.getContent().entrySet()) {
+ Schema> schema = entry.getValue().getSchema();
+ return resolveSchema(schema, openAPI);
+ }
+ }
+ }
+ return null;
+ }
+
+ private static Schema> resolveSchema(Schema> schema, OpenAPI openAPI) {
+ if (schema != null && schema.get$ref() != null) {
+ String refName = schema.get$ref().replace("#/components/schemas/", "");
+ return openAPI.getComponents().getSchemas().get(refName);
+ }
+ return schema;
+ }
+}