Compare commits

...

2 Commits

Author SHA1 Message Date
ovo 8b8e5fa497 更新.gitignore 2025-03-05 23:14:47 +08:00
ovo e1a782fc44 fix: [mongo测试文件存储] 2025-02-27 22:00:01 +08:00
19 changed files with 765 additions and 0 deletions

10
pom.xml
View File

@ -370,7 +370,17 @@
</dependency>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.10.2</version>
</dependency>
<dependency>
<groupId>io.swagger.parser.v3</groupId>
<artifactId>swagger-parser</artifactId>
<version>2.1.25</version>
</dependency>
</dependencies>

View File

@ -4,20 +4,25 @@ import cn.easyes.core.conditions.LambdaEsQueryWrapper;
import com.guwan.backend.common.Result;
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
@ -40,6 +45,11 @@ public class DemoController {
private final FileStorageService fileStorageService;
private final CategoryService categoryService;
private final RestTemplate restTemplate;
private final SwaggerAutoFillService swaggerAutoFillService;
@PostMapping("/uploadFile")
public Result<String> uploadFile(String bucketName, MultipartFile file){
return Result.success(minioUtil.getUrl(minioUtil.getFileUrl
@ -113,4 +123,28 @@ public class DemoController {
}
@GetMapping("/saveCategories")
public void saveCategories(String fileId) throws IOException {
categoryService.saveCategories();
}
@GetMapping("/getAllCategories")
public void getAllCategories() {
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();
}
}

View File

@ -0,0 +1,18 @@
package com.guwan.backend.mongodb;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import java.util.List;
@Document(collection = "categories")
@Data
public class Category {
@Id
private String id;
private String name;
private List<Category> children;
}

View File

@ -0,0 +1,7 @@
package com.guwan.backend.mongodb;
import org.springframework.data.mongodb.repository.MongoRepository;
public interface CategoryRepository extends MongoRepository<Category, String> {
// 可以定义一些自定义查询方法
}

View File

@ -0,0 +1,37 @@
package com.guwan.backend.mongodb;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class CategoryService {
@Autowired
private MongoTemplate mongoTemplate;
public void saveCategories() {
// 创建子类 B C
Category subCategory1 = new Category();
subCategory1.setName("B");
Category subCategory2 = new Category();
subCategory2.setName("C");
// 创建根类 A包含子类 B C
Category rootCategory = new Category();
rootCategory.setName("A");
rootCategory.setChildren(List.of(subCategory1, subCategory2));
// 保存根类 A MongoDB
mongoTemplate.save(rootCategory);
System.out.println("Inserted Category: " + rootCategory);
}
public List<Category> getAllCategories() {
return mongoTemplate.findAll(Category.class);
}
}

View File

@ -64,4 +64,8 @@ public class FileStorageService {
// 根据文件 ID 删除文件
gridFsTemplate.delete(new Query(Criteria.where("_id").is(fileId)));
}
}

View File

@ -0,0 +1,25 @@
package com.guwan.backend.parse;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
public class Demo {
public static void main(String[] args) {
List<Integer> list1 = Arrays.asList(1, 2, 3, 4);
List<Integer> list2 = Arrays.asList(1, 2, 3, 4);
for (Integer i : list1) {
for (Integer integer : list2) {
if (Objects.equals(i, integer)){
System.out.println("integer = " + integer);
}
}
}
list1.stream()
.flatMap(i -> list2.stream().filter(integer -> Objects.equals(i, integer)))
.forEach(integer -> System.out.println("integer = " + integer));
}
}

View File

@ -0,0 +1,78 @@
package com.guwan.backend.parse;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
public class MethodLister {
public static void listMethodsByClassPrefix(String packageName, String classPrefix) throws Exception {
// 获取包路径
String packagePath = packageName.replace('.', '/');
// 获取类加载器
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
// 获取包路径下所有文件
URL url = classLoader.getResource(packagePath);
if (url == null) {
System.out.println("Package not found: " + packageName);
return;
}
File directory = new File(url.toURI());
System.out.println("directory = " + directory);
if (!directory.exists()) {
System.out.println("Directory not found: " + directory.getAbsolutePath());
return;
}
// 获取包下所有类
List<Class<?>> classes = getClassesFromDirectory(directory, packageName, classPrefix);
// 输出每个符合条件的类及其方法
for (Class<?> clazz : classes) {
System.out.println("Class: " + clazz.getName());
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
System.out.println(" Method: " + method.getName());
}
}
}
private static List<Class<?>> getClassesFromDirectory(File directory, String packageName, String classPrefix) throws ClassNotFoundException {
List<Class<?>> classes = new ArrayList<>();
// 获取目录下的所有文件
File[] files = directory.listFiles(file -> file.getName().endsWith(".class"));
if (files == null) return classes;
// 遍历文件
for (File file : files) {
// 获取类名去掉 .class 后缀
String className = file.getName().substring(0, file.getName().length() - 6);
// 判断类名是否以指定的前缀开始
if (className.startsWith(classPrefix)) {
// 动态加载类
Class<?> clazz = Class.forName(packageName + "." + className);
classes.add(clazz);
}
}
return classes;
}
public static void main(String[] args) {
try {
// 指定包名和类名前缀
listMethodsByClassPrefix("com.guwan.backend.parse", "Parse");
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,58 @@
package com.guwan.backend.parse;
import org.reflections.Reflections;
import org.reflections.scanners.Scanners;
import org.reflections.util.ConfigurationBuilder;
import java.lang.reflect.Method;
import java.util.Set;
public class MethodLister2 {
public static void listMethodsByClassPrefix(String packageName, String classPrefix) {
try {
// 使用 Reflections 库扫描指定包下的类
// Reflections reflections = new Reflections(packageName);
/**
* 要重写过滤条件 默认情况下Reflections 会排除 Object 类的扫描结果因为它是所有类的根基类
*/
Reflections reflections = new Reflections(
new ConfigurationBuilder()
.addScanners(Scanners.SubTypes.filterResultsBy(s -> true)/*Override the default behavior which exclude Object class*/)
.forPackages(packageName)
);
// 获取某类的所有子类
Set<Class<?>> classes = reflections.getSubTypesOf(Object.class);
//获取使用某注解的所有类
// Set<Class<?>> classes = reflections.getTypesAnnotatedWith(SCAN.class);
// System.out.println("classes = " + classes);
// 过滤以 classPrefix 开头的类
for (Class<?> clazz : classes) {
if (clazz.getSimpleName().startsWith(classPrefix)) {
System.out.println("Class: " + clazz.getName());
// 获取类的所有方法
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
System.out.println(" Method: " + method.getName());
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// 指定包名和类名前缀
listMethodsByClassPrefix("com.guwan.backend.parse", "Parse");
}
}

View File

@ -0,0 +1,7 @@
package com.guwan.backend.parse;
public class ParseHandler1 extends Object{
public void parseData1() {}
public void parseFile2() {}
}

View File

@ -0,0 +1,7 @@
package com.guwan.backend.parse;
public class ParseHandler2 extends Object{
public void parseString3() {}
public void processData3() {}
}

View File

@ -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<RequestHeader> headers;
@TableField(typeHandler = JacksonTypeHandler.class)
private List<RequestParameter> queryParams;
private String bodyType;
@TableField(typeHandler = JacksonTypeHandler.class)
private List<RequestParameter> 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;
}*/

View File

@ -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<String, Schema> 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 + "[]");
}
}
}
}

View File

@ -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<Api> importFromSwagger(String swaggerJson) {
List<Api> 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<RequestParameter> 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<RequestParameter> parseFormParameters(JsonNode schema) {
List<RequestParameter> 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<String> 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;
}
}*/

View File

@ -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<String, Object> getPreConditionData(String apiUrl) {
return restTemplate.getForObject(apiUrl, Map.class);
}
/**
* 自动填充接口的入参
*/
public Map<String, Object> autoFillTestCase(String apiUrl, Map<String, Object> inputParams) {
Map<String, Object> preData = getPreConditionData(apiUrl);
// 遍历 API 参数自动填充依赖字段
for (String key : inputParams.keySet()) {
if (preData.containsKey(key)) {
inputParams.put(key, preData.get(key));
}
}
return inputParams;
}
}

View File

@ -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<String, String> 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();
}
}

View File

@ -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<String, String> extractQueryParameters(List<Parameter> parameters) {
Map<String, String> 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;
}
}

View File

@ -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<String, MediaType> 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;
}
}

View File

@ -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<String, io.swagger.v3.oas.models.media.MediaType> 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;
}
}