完善OpenApi模块文档

pull/7564/head
EightMonth 2025-02-10 15:51:17 +08:00
parent 2b0bedd263
commit 1acb773adf
12 changed files with 327 additions and 250 deletions

View File

@ -1,9 +1,9 @@
package org.jeecg.modules.openapi.controller;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.classmate.ResolvedType;
import com.fasterxml.classmate.TypeResolver;
import com.google.common.collect.Lists;
import org.jeecg.common.api.vo.Result;
@ -20,21 +20,17 @@ import org.jeecg.modules.openapi.service.OpenApiAuthService;
import org.jeecg.modules.openapi.service.OpenApiHeaderService;
import org.jeecg.modules.openapi.service.OpenApiParamService;
import org.jeecg.modules.openapi.service.OpenApiService;
import org.jeecg.modules.openapi.swagger.*;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import springfox.documentation.schema.Model;
import springfox.documentation.schema.ModelProperty;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.schema.ModelReference;
import springfox.documentation.service.*;
import springfox.documentation.spring.web.DocumentationCache;
import javax.servlet.http.HttpServletRequest;
@ -45,7 +41,7 @@ import java.util.*;
*/
@RestController
@RequestMapping("/openapi")
public class OpenApiController extends JeecgController<OpenApi, OpenApiService> implements CommandLineRunner {
public class OpenApiController extends JeecgController<OpenApi, OpenApiService> {
@Autowired
private RestTemplate restTemplate;
@ -201,138 +197,184 @@ public class OpenApiController extends JeecgController<OpenApi, OpenApiService>
return restTemplate.exchange(url, HttpMethod.resolve(method), httpEntity, Result.class, request.getParameterMap()).getBody();
}
@GetMapping("/call/add")
public void addSwagger() {
Documentation documentation = documentationCache.documentationByGroup("default");
@GetMapping("/json")
public SwaggerModel swaggerModel() {
List<ApiListing> apis = new ArrayList<>();
SwaggerModel swaggerModel = new SwaggerModel();
swaggerModel.setSwagger("2.0");
swaggerModel.setInfo(swaggerInfo());
swaggerModel.setHost("jeecg.com");
swaggerModel.setBasePath("/jeecg-boot");
swaggerModel.setSchemes(Lists.newArrayList("http", "https"));
Set<String> produces = new HashSet<>();
produces.add("application/json");
Set<String> consumes = new HashSet<>();
consumes.add("application/json");
SwaggerTag swaggerTag = new SwaggerTag();
swaggerTag.setName("openapi");
swaggerModel.setTags(Lists.newArrayList(swaggerTag));
Set<String> tags = new HashSet<>();
Tag tag = new Tag("openapi", "openapi");
tags.add("openapi");
Set<Tag> apiTags = new HashSet<>();
apiTags.add(tag);
documentation.getTags().add(tag);
pathsAndDefinitions(swaggerModel);
Model resultModel = documentation.getApiListings().get("login-controller").get(0).getModels().get("接口返回对象«JSONObject»");
return swaggerModel;
}
ModelRef stringModelRef = new ModelRef("string");
private void pathsAndDefinitions(SwaggerModel swaggerModel) {
Map<String, Map<String, SwaggerOperation>> paths = new HashMap<>();
Map<String, SwaggerDefinition> definitions = new HashMap<>();
List<OpenApi> openapis = service.list();
for (OpenApi openApi : openapis) {
Map<String, SwaggerOperation> operations = new HashMap<>();
SwaggerOperation operation = new SwaggerOperation();
operation.setTags(Lists.newArrayList("openapi"));
operation.setSummary(openApi.getName());
operation.setDescription(openApi.getName());
operation.setOperationId(openApi.getRequestUrl()+"Using"+openApi.getRequestMethod());
operation.setProduces(Lists.newArrayList("application/json"));
parameters(operation, openApi);
ResolvedType stringResolvedType = typeResolver.resolve(String.class);
// body入参
if (StringUtils.hasText(openApi.getBody())) {
SwaggerDefinition definition = new SwaggerDefinition();
definition.setType("object");
Map<String, SwaggerDefinitionProperties> definitionProperties = new HashMap<>();
definition.setProperties(definitionProperties);
JSONObject jsonObject = JSONObject.parseObject(openApi.getBody());
for (Map.Entry<String, Object> properties : jsonObject.entrySet()) {
SwaggerDefinitionProperties swaggerDefinitionProperties = new SwaggerDefinitionProperties();
swaggerDefinitionProperties.setType("string");
swaggerDefinitionProperties.setDescription(properties.getValue()+"");
definitionProperties.put(properties.getKey(), swaggerDefinitionProperties);
}
// body的definition构建完成
definitions.put(openApi.getRequestUrl()+"Using"+openApi.getRequestMethod()+"body", definition);
SwaggerOperationParameter bodyParameter = new SwaggerOperationParameter();
bodyParameter.setDescription(openApi.getName() + " body");
bodyParameter.setIn("body");
bodyParameter.setName(openApi.getName() + " body");
bodyParameter.setRequired(true);
Map<String, String> bodySchema = new HashMap<>();
bodySchema.put("$ref", "#/definitions/" + openApi.getRequestUrl()+"Using"+openApi.getRequestMethod()+"body");
bodyParameter.setSchema(bodySchema);
// 构建参数构建完成
operation.getParameters().add(bodyParameter);
}
// 响应
Map<String, SwaggerOperationResponse> responses = new HashMap<>();
SwaggerOperationResponse resp200 = new SwaggerOperationResponse();
resp200.setDescription("OK");
Map<String, String> respSchema = new HashMap<>();
respSchema.put("$ref", "#/definitions/OpenApiResult");
resp200.setSchema(respSchema);
responses.put("200", resp200);
Map<String, String> emptySchema = new HashMap<>();
SwaggerOperationResponse resp201 = new SwaggerOperationResponse();
resp201.setDescription("Created");
resp201.setSchema(emptySchema);
responses.put("201", resp201);
SwaggerOperationResponse resp401 = new SwaggerOperationResponse();
resp401.setDescription("Unauthorized");
resp401.setSchema(emptySchema);
responses.put("401", resp401);
SwaggerOperationResponse resp403 = new SwaggerOperationResponse();
resp403.setDescription("Forbidden");
resp403.setSchema(emptySchema);
responses.put("403", resp403);
SwaggerOperationResponse resp404 = new SwaggerOperationResponse();
resp404.setDescription("Not Found");
resp404.setSchema(emptySchema);
responses.put("404", resp404);
// 构建响应definition
SwaggerDefinition respDefinition = new SwaggerDefinition();
respDefinition.setType("object");
Map<String, SwaggerDefinitionProperties> definitionProperties = new HashMap<>();
respDefinition.setProperties(definitionProperties);
SwaggerDefinitionProperties codeProperties = new SwaggerDefinitionProperties();
codeProperties.setType("integer");
codeProperties.setDescription("返回代码");
definitionProperties.put("code", codeProperties);
SwaggerDefinitionProperties messageProperties = new SwaggerDefinitionProperties();
messageProperties.setType("string");
messageProperties.setDescription("返回处理消息");
definitionProperties.put("message", messageProperties);
SwaggerDefinitionProperties resultProperties = new SwaggerDefinitionProperties();
resultProperties.setType("object");
resultProperties.setDescription("返回数据对象");
definitionProperties.put("result", resultProperties);
SwaggerDefinitionProperties successProperties = new SwaggerDefinitionProperties();
successProperties.setType("boolean");
successProperties.setDescription("成功标志");
definitionProperties.put("success", successProperties);
SwaggerDefinitionProperties timestampProperties = new SwaggerDefinitionProperties();
timestampProperties.setType("integer");
timestampProperties.setDescription("时间戳");
definitionProperties.put("timestamp", timestampProperties);
definitions.put("OpenApiResult", respDefinition);
HashMap<String, ModelProperty> propertyMap = new HashMap<>();
ModelProperty modelProperty = new ModelProperty("abc", stringResolvedType, "java.lang.String", 0, true, false, false, false, "姓名", null, null, null, null, null, new ArrayList<>());
propertyMap.put("abc", modelProperty);
ModelProperty modelProperty1 = new ModelProperty("bcd", stringResolvedType, "java.lang.String", 0, true, false, false, false, "姓名", null, null, null, null, null, new ArrayList<>());
propertyMap.put("bcd", modelProperty1);
operation.setResponses(responses);
operations.put(openApi.getRequestMethod().toLowerCase(), operation);
paths.put("/openapi/call/"+openApi.getRequestUrl(), operations);
}
ResolvedType mapResolvedType = typeResolver.resolve(HashMap.class);
swaggerModel.setDefinitions(definitions);
swaggerModel.setPaths(paths);
List<ModelReference> subTypes = new ArrayList<>();
subTypes.add(stringModelRef);
}
Model bodyModel = new Model("path_body", "bodyModel", mapResolvedType, "java.util.HashMap", propertyMap, "请求体结构", "", "", subTypes, null, null);
ModelRef bodyRef = new ModelRef("bodyModel", "path_body", null, null,true, "path_body");
private void parameters(SwaggerOperation operation, OpenApi openApi) {
List<SwaggerOperationParameter> parameters = new ArrayList<>();
Set<ResponseMessage> responseMessages = documentation.getApiListings().get("login-controller").get(0).getApis().get(2).getOperations().get(0).getResponseMessages();
for (OpenApiParam openApiParam : openApiParamService.findByApiId(openApi.getId())) {
SwaggerOperationParameter parameter = new SwaggerOperationParameter();
parameter.setIn("path");
parameter.setName(openApiParam.getParamKey());
parameter.setRequired(openApiParam.getRequired() == 1);
parameter.setDescription(openApiParam.getNote());
parameters.add(parameter);
}
List<Parameter> parameters = new ArrayList<>();
// header-->请求参数的获取:@RequestHeader()
// query-->请求参数的获取:@RequestParam()
// path-->请求参数的获取:@PathVariable()
// body-->请求参数的获取:@RequestBody()
// form不常用
Parameter body = new Parameter("bodyModel",
"请求体",
"",
true,
false,
true,
bodyRef,
Optional.of(mapResolvedType),
null,
"body",
null,
false,
null,
null,
2147483647,
null,
new HashMap<>(),
new ArrayList<>());
for (OpenApiHeader openApiHeader : openApiHeaderService.findByApiId(openApi.getId())) {
SwaggerOperationParameter parameter = new SwaggerOperationParameter();
parameter.setIn("header");
parameter.setName(openApiHeader.getHeaderKey());
parameter.setRequired(openApiHeader.getRequired() == 1);
parameter.setDescription(openApiHeader.getNote());
parameters.add(parameter);
}
parameters.add(body);
operation.setParameters(parameters);
}
Parameter parameter = new Parameter("name",
"姓名",
"张三",
false,
false,
true,
stringModelRef,
Optional.empty(),
null,
"query",
null,
false,
null,
null,
2147483647,
null,
new HashMap<>(),
new ArrayList<>());
private SwaggerInfo swaggerInfo() {
SwaggerInfo info = new SwaggerInfo();
parameters.add(parameter);
info.setDescription("OpenAPI 接口列表");
info.setVersion("3.7.1");
info.setTitle("OpenAPI 接口列表");
info.setTermsOfService("https://jeecg.com");
ModelRef modelRef = new ModelRef(resultModel.getType().getTypeName(),
resultModel.getQualifiedType(),
null,
null,
false,
resultModel.getId());
SwaggerInfoContact contact = new SwaggerInfoContact();
contact.setName("jeecg@qq.com");
Operation operation = new Operation(HttpMethod.resolve("GET"),
"模拟第一个openapi接口",
"模拟第一个openapi接口",
modelRef,
"abcUsingGET",
0, tags, produces, consumes,
new LinkedHashSet<>(),
new ArrayList<>(),
parameters,
responseMessages,
"false",
false,
new ArrayList<>());
info.setContact(contact);
List<Operation> operations = new ArrayList<>();
operations.add(operation);
SwaggerInfoLicense license = new SwaggerInfoLicense();
license.setName("Apache 2.0");
license.setUrl("http://www.apache.org/licenses/LICENSE-2.0.html");
ApiDescription apiDescription = new ApiDescription("openapi",
"/jeecg-boot/openapi/call/abc", "openapi", operations, false);
info.setLicense(license);
List<ApiDescription> apiList = new ArrayList<>();
apiList.add(apiDescription);
Map<String, Model> responseModel = new HashMap<>();
responseModel.put("接口返回对象«JSONObject»", resultModel);
responseModel.put("bodyModel", bodyModel);
ApiListing api = new ApiListing("1.0",
"/",
"/openapi/call/abc",
produces, consumes,
"", new HashSet<>(), new ArrayList<>(), apiList, responseModel, "abc", 0, apiTags);
apis.add(api);
documentation.getApiListings().put("openapi", apis);
return info;
}
/**
@ -347,135 +389,4 @@ public class OpenApiController extends JeecgController<OpenApi, OpenApiService>
r.setResult(PathGenerator.genPath());
return r;
}
/**
* resetOpenapiSwagger
*/
@Override
public void run(String... args) throws Exception {
List<OpenApi> openapis = service.list();
Documentation documentation = documentationCache.documentationByGroup("default");
List<ApiListing> apis = new ArrayList<>();
// --------------------- swagger common --------------
// http参数
Set<String> produces = new HashSet<>();
produces.add("application/json");
Set<String> consumes = new HashSet<>();
consumes.add("application/json");
// 标题栏
Set<String> tags = new HashSet<>();
Tag tag = new Tag("openapi", "openapi");
tags.add("openapi");
Set<Tag> apiTags = new HashSet<>();
apiTags.add(tag);
documentation.getTags().add(tag);
ModelRef stringModelRef = new ModelRef("string", null, false);
// 响应文档
Model resultModel = documentation.getApiListings().get("login-controller").get(0).getModels().get("接口返回对象«JSONObject»");
Set<ResponseMessage> responseMessages = documentation.getApiListings().get("login-controller").get(0).getApis().get(2).getOperations().get(0).getResponseMessages();
ModelRef modelRef = new ModelRef(resultModel.getType().getTypeName(),
resultModel.getQualifiedType(),
null,
null,
false,
resultModel.getId());
// --------------------- swagger common --------------
for (OpenApi openapi : openapis) {
openapi.setParams(openApiParamService.findByApiId(openapi.getId()));
openapi.setHeaders(openApiHeaderService.findByApiId(openapi.getId()));
// 参数包含header\query\path\body\form 五类数据
List<Parameter> parameters = new ArrayList<>();
// header-->请求参数的获取:@RequestHeader()
// query-->请求参数的获取:@RequestParam()
// path-->请求参数的获取:@PathVariable()
// body-->请求参数的获取:@RequestBody()
// form不常用
for (OpenApiHeader openApiHeader : openapi.getHeaders()) {
Parameter parameter = new Parameter(openApiHeader.getHeaderKey(),
openApiHeader.getNote(),
openApiHeader.getDefaultValue(),
openApiHeader.getRequired() == 1,
false,
true,
stringModelRef,
Optional.empty(),
null,
"header",
null,
false,
null,
null,
2147483647,
null,
new HashMap<>(),
new ArrayList<>());
parameters.add(parameter);
}
for (OpenApiParam openApiParam : openapi.getParams()) {
Parameter parameter = new Parameter(openApiParam.getParamKey(),
openApiParam.getNote(),
openApiParam.getDefaultValue(),
openApiParam.getRequired() == 1,
false,
true,
stringModelRef,
Optional.empty(),
null,
"query",
null,
false,
null,
null,
2147483647,
null,
new HashMap<>(),
new ArrayList<>());
parameters.add(parameter);
}
Operation operation = new Operation(HttpMethod.resolve(openapi.getRequestMethod()),
openapi.getName(),
openapi.getName(),
modelRef,
openapi.getName()+"Using"+openapi.getRequestMethod(),
0, tags, produces, consumes,
new LinkedHashSet<>(),
new ArrayList<>(),
parameters,
responseMessages,
"false",
false,
new ArrayList<>());
List<Operation> operations = new ArrayList<>();
operations.add(operation);
ApiDescription apiDescription = new ApiDescription("openapi",
"/jeecg-boot/openapi/call/"+openapi.getRequestUrl(), openapi.getName(), operations, false);
List<ApiDescription> apiList = new ArrayList<>();
apiList.add(apiDescription);
Map<String, Model> responseModel = new HashMap<>();
responseModel.put("接口返回对象«JSONObject»", resultModel);
ApiListing api = new ApiListing("1.0",
"/",
"/openapi/call/"+openapi.getRequestUrl(),
produces, consumes,
"", new HashSet<>(), new ArrayList<>(), apiList, responseModel, "abc", 0, apiTags);
apis.add(api);
}
documentation.getApiListings().put("openapi", apis);
}
}

View File

@ -0,0 +1,14 @@
package org.jeecg.modules.openapi.swagger;
import lombok.Data;
import java.util.Map;
/**
* @date 2025/1/26 11:17
*/
@Data
public class SwaggerDefinition {
private String type;
private Map<String, SwaggerDefinitionProperties> properties;
}

View File

@ -0,0 +1,13 @@
package org.jeecg.modules.openapi.swagger;
import lombok.Data;
/**
* @date 2025/1/26 13:54
*/
@Data
public class SwaggerDefinitionProperties {
private String type;
private String example;
private String description;
}

View File

@ -0,0 +1,16 @@
package org.jeecg.modules.openapi.swagger;
import lombok.Data;
/**
* @date 2025/1/26 11:05
*/
@Data
public class SwaggerInfo {
private String description;
private String version;
private String title;
private String termsOfService;
private SwaggerInfoContact contact;
private SwaggerInfoLicense license;
}

View File

@ -0,0 +1,11 @@
package org.jeecg.modules.openapi.swagger;
import lombok.Data;
/**
* @date 2025/1/26 11:08
*/
@Data
public class SwaggerInfoContact {
private String name;
}

View File

@ -0,0 +1,12 @@
package org.jeecg.modules.openapi.swagger;
import lombok.Data;
/**
* @date 2025/1/26 11:09
*/
@Data
public class SwaggerInfoLicense {
private String name;
private String url;
}

View File

@ -0,0 +1,21 @@
package org.jeecg.modules.openapi.swagger;
import lombok.Data;
import java.util.List;
import java.util.Map;
/**
* @date 2025/1/26 11:05
*/
@Data
public class SwaggerModel {
private String swagger;
private SwaggerInfo info;
private String host;
private String basePath;
private List<SwaggerTag> tags;
private List<String> schemes;
private Map<String, Map<String, SwaggerOperation>> paths;
private Map<String, SwaggerDefinition> definitions;
}

View File

@ -0,0 +1,20 @@
package org.jeecg.modules.openapi.swagger;
import lombok.Data;
import java.util.List;
import java.util.Map;
/**
* @date 2025/1/26 11:16
*/
@Data
public class SwaggerOperation {
private List<String> tags;
private String summary;
private String description;
private String operationId;
private List<String> produces;
private List<SwaggerOperationParameter> parameters;
private Map<String, SwaggerOperationResponse> responses;
}

View File

@ -0,0 +1,18 @@
package org.jeecg.modules.openapi.swagger;
import lombok.Data;
import java.util.List;
import java.util.Map;
/**
* @date 2025/1/26 11:43
*/
@Data
public class SwaggerOperationParameter {
private String name;
private String in;
private String description;
private Boolean required;
private Map<String, String> schema;
}

View File

@ -0,0 +1,14 @@
package org.jeecg.modules.openapi.swagger;
import lombok.Data;
import java.util.Map;
/**
* @date 2025/1/26 11:47
*/
@Data
public class SwaggerOperationResponse {
private String description;
private Map<String, String> schema;
}

View File

@ -0,0 +1,16 @@
package org.jeecg.modules.openapi.swagger;
/**
* @date 2025/1/26 11:51
*/
public class SwaggerSchema {
private String $ref;
public String get$ref() {
return $ref;
}
public void set$ref(String $ref) {
this.$ref = $ref;
}
}

View File

@ -0,0 +1,11 @@
package org.jeecg.modules.openapi.swagger;
import lombok.Data;
/**
* @date 2025/1/26 11:15
*/
@Data
public class SwaggerTag {
private String name;
}