提交 21c15a39 编写于 作者: J jmxd

添加springdoc插件,不支持spring boot 2.x 版本

上级 d4a3593f
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.ssssssss</groupId>
<artifactId>magic-api-plugins</artifactId>
<version>2.0.2</version>
</parent>
<artifactId>magic-api-plugin-springdoc</artifactId>
<packaging>jar</packaging>
<name>magic-api-plugin-springdoc</name>
<description>magic-api-plugin-springdoc</description>
<properties>
<springdoc.version>2.0.4</springdoc.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>${springdoc.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<source>17</source>
<target>17</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
package org.ssssssss.magicapi.springdoc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springdoc.core.properties.SwaggerUiConfigParameters;
import org.springdoc.core.properties.SwaggerUiConfigProperties;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Primary;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import org.ssssssss.magicapi.core.config.MagicAPIProperties;
import org.ssssssss.magicapi.core.config.MagicPluginConfiguration;
import org.ssssssss.magicapi.core.model.Plugin;
import org.ssssssss.magicapi.core.service.MagicResourceService;
import org.ssssssss.magicapi.core.service.impl.RequestMagicDynamicRegistry;
import org.ssssssss.magicapi.springdoc.entity.SwaggerEntity;
import org.ssssssss.magicapi.springdoc.entity.SwaggerProvider;
import org.ssssssss.magicapi.utils.Mapping;
import jakarta.servlet.ServletContext;
import java.util.*;
@Configuration
@EnableConfigurationProperties(SpringDocConfig.class)
@ConditionalOnProperty(
name = {"springdoc.api-docs.enabled"},
matchIfMissing = true
)
public class MagicSpringDocConfiguration implements MagicPluginConfiguration {
private final MagicAPIProperties properties;
private final SpringDocConfig springDocConfig;
@Autowired
@Lazy
private RequestMappingHandlerMapping requestMappingHandlerMapping;
private final ObjectProvider<RequestMagicDynamicRegistry> requestMagicDynamicRegistryObjectProvider;
private final MagicResourceService magicResourceService;
private final ServletContext servletContext;
private boolean createdMapping = false;
private static Logger logger = LoggerFactory.getLogger(MagicSpringDocConfiguration.class);
public MagicSpringDocConfiguration(MagicAPIProperties properties, SpringDocConfig springDocConfig, ObjectProvider<RequestMagicDynamicRegistry> requestMagicDynamicRegistryObjectProvider, MagicResourceService magicResourceService, ServletContext servletContext) {
this.properties = properties;
this.springDocConfig = springDocConfig;
this.requestMagicDynamicRegistryObjectProvider = requestMagicDynamicRegistryObjectProvider;
this.magicResourceService = magicResourceService;
this.servletContext = servletContext;
}
@Override
public Plugin plugin() {
return new Plugin("SpringDoc");
}
@Bean
@Primary
@Lazy
public SwaggerUiConfigParameters magicSwaggerUiConfigParameters(SwaggerUiConfigProperties swaggerUiConfigProperties) {
return new SwaggerUiConfigParameters(swaggerUiConfigProperties) {
@Override
public Map<String, Object> getConfigParameters() {
Map<String, Object> params = super.getConfigParameters();
if (!createdMapping) {
createdMapping = true;
try {
createSwaggerProvider(requestMagicDynamicRegistryObjectProvider, magicResourceService, servletContext);
} catch (NoSuchMethodException e) {
logger.error("注册springdoc接口失败", e);
return params;
}
}
Set<SwaggerUrl> urls = (Set<SwaggerUrl>) params.get("urls");
if (urls == null) {
urls = new HashSet<>();
SwaggerUrl url = new SwaggerUrl("default", (String) params.remove("url"), null);
urls.add(url);
} else {
urls = new HashSet<>(urls);
}
urls.add(new SwaggerUrl(springDocConfig.getGroupName(), springDocConfig.getLocation(), null));
params.put("urls", urls);
return params;
}
};
}
private void createSwaggerProvider(ObjectProvider<RequestMagicDynamicRegistry> requestMagicDynamicRegistryObjectProvider, MagicResourceService magicResourceService, ServletContext servletContext) throws NoSuchMethodException {
Mapping mapping = Mapping.create(requestMappingHandlerMapping);
RequestMappingInfo requestMappingInfo = mapping.paths(springDocConfig.getLocation()).build();
SwaggerEntity.License license = new SwaggerEntity.License("MIT", "https://gitee.com/ssssssss-team/magic-api/blob/master/LICENSE");
SwaggerEntity.Info info = new SwaggerEntity.Info(springDocConfig.getDescription(), springDocConfig.getVersion(), springDocConfig.getTitle(), license, springDocConfig.getConcat());
//具体参考:https://swagger.io/docs/specification/2-0/authentication/
Map<String, Object> securityDefinitionMap = new HashMap<>();
Map<String, Object> securityMap = new HashMap<>();
if (springDocConfig.getBasicAuth() != null) {
securityDefinitionMap.put(SwaggerEntity.BasicAuth.KEY_NAME, springDocConfig.getBasicAuth());
//the Basic and API key security items use an empty array instead.
securityMap.put(SwaggerEntity.BasicAuth.KEY_NAME, new String[]{});
}
if (springDocConfig.getApiKeyAuth() != null) {
securityDefinitionMap.put(SwaggerEntity.ApiKeyAuth.KEY_NAME, springDocConfig.getApiKeyAuth());
//the Basic and API key security items use an empty array instead.
securityMap.put(SwaggerEntity.ApiKeyAuth.KEY_NAME, new String[]{});
}
if (springDocConfig.getOauth2() != null) {
SwaggerEntity.OAuth2 oAuth2 = springDocConfig.getOauth2();
securityDefinitionMap.put(SwaggerEntity.OAuth2.KEY_NAME, oAuth2);
Map<String, String> scopes = oAuth2.getScopes();
if (scopes != null) {
Set<String> strings = scopes.keySet();
securityMap.put(SwaggerEntity.OAuth2.KEY_NAME, strings);
}
}
// 构建文档信息
SwaggerProvider swaggerProvider = new SwaggerProvider(requestMagicDynamicRegistryObjectProvider.getObject(), magicResourceService, servletContext.getContextPath(),
info, properties.isPersistenceResponseBody(), properties.getPrefix(), securityDefinitionMap, securityMap);
// 注册swagger.json
mapping.register(requestMappingInfo, swaggerProvider, SwaggerProvider.class.getDeclaredMethod("swaggerJson"));
}
}
package org.ssssssss.magicapi.springdoc;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.ssssssss.magicapi.springdoc.entity.SwaggerEntity;
/**
* Swagger 配置
*
* @author mxd
*/
@ConfigurationProperties(prefix = "magic-api.swagger")
public class SpringDocConfig {
/**
* 资源名称
*/
private String name = "MagicAPI接口";
/**
* 资源位置
*/
private String location = "/v2/api-docs/magic-api/swagger2.json";
/**
* 分组名称
*/
private String groupName = "magic-api";
/**
* 文档标题
*/
private String title = "MagicAPI Swagger Docs";
/**
* 文档描述
*/
private String description = "MagicAPI 接口信息";
@NestedConfigurationProperty
private SwaggerEntity.Concat concat = new SwaggerEntity.Concat();
/**
* 基本认证
*/
@NestedConfigurationProperty
private SwaggerEntity.BasicAuth basicAuth;
/**
* api密钥认证
*/
@NestedConfigurationProperty
private SwaggerEntity.ApiKeyAuth apiKeyAuth;
/**
* oauth2认证
*/
@NestedConfigurationProperty
private SwaggerEntity.OAuth2 oauth2;
/**
* 文档版本
*/
private String version = "1.0";
public String getGroupName() {
return groupName;
}
public void setGroupName(String groupName) {
this.groupName = groupName;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public SwaggerEntity.Concat getConcat() {
return concat;
}
public void setConcat(SwaggerEntity.Concat concat) {
this.concat = concat;
}
public SwaggerEntity.ApiKeyAuth getApiKeyAuth() {
return apiKeyAuth;
}
public void setApiKeyAuth(SwaggerEntity.ApiKeyAuth apiKeyAuth) {
this.apiKeyAuth = apiKeyAuth;
}
public SwaggerEntity.BasicAuth getBasicAuth() {
return basicAuth;
}
public void setBasicAuth(SwaggerEntity.BasicAuth basicAuth) {
this.basicAuth = basicAuth;
}
public SwaggerEntity.OAuth2 getOauth2() {
return oauth2;
}
public void setOauth2(SwaggerEntity.OAuth2 oauth2) {
this.oauth2 = oauth2;
}
}
package org.ssssssss.magicapi.springdoc.entity;
import java.util.*;
/**
* Swagger接口信息
*
* @author mxd
*/
public class SwaggerEntity {
private String swagger = "2.0";
private String host;
private String basePath;
private Info info;
private final Map<String, Object> securityDefinitions = new HashMap<>();
private final List<Map<String, Object>> security = new ArrayList<>();
private final Set<Tag> tags = new TreeSet<>(Comparator.comparing(Tag::getName));
private final Map<String, Object> definitions = new HashMap<>();
private final Map<String, Map<String, Path>> paths = new HashMap<>();
private static Map<String, Object> doProcessSchema(Object target) {
Map<String, Object> result = new HashMap<>(3);
result.put("type", getType(target));
if (target instanceof List) {
List<?> targetList = (List<?>) target;
if (targetList.size() > 0) {
result.put("items", doProcessSchema(targetList.get(0)));
} else {
result.put("items", Collections.emptyList());
}
} else if (target instanceof Map) {
Set<Map.Entry> entries = ((Map) target).entrySet();
Map<String, Map<String, Object>> properties = new HashMap<>(entries.size());
for (Map.Entry entry : entries) {
properties.put(Objects.toString(entry.getKey()), doProcessSchema(entry.getValue()));
}
result.put("properties", properties);
} else {
result.put("example", target == null ? "" : target);
result.put("description", target == null ? "" : target);
}
return result;
}
private static String getType(Object object) {
if (object instanceof Number) {
return "number";
}
if (object instanceof String) {
return "string";
}
if (object instanceof Boolean) {
return "boolean";
}
if (object instanceof List) {
return "array";
}
if (object instanceof Map) {
return "object";
}
return "string";
}
public static Map<String, Object> createParameter(boolean required, String name, String in, String type, String description, Object example) {
Map<String, Object> parameter = new HashMap<>();
parameter.put("required", required);
parameter.put("name", name);
parameter.put("in", in);
parameter.put("description", description);
if ("body".equalsIgnoreCase(in)) {
Map<String, Object> schema = new HashMap<>();
schema.put("type", type);
schema.put("example", example);
parameter.put("schema", schema);
} else {
parameter.put("x-example", example);
parameter.put("type", type);
}
return parameter;
}
public Info getInfo() {
return info;
}
public void setInfo(Info info) {
this.info = info;
}
public void addPath(String path, String method, Path pathInfo) {
Map<String, Path> map = paths.computeIfAbsent(path, k -> new HashMap<>());
map.put(method.toLowerCase(), pathInfo);
}
public void addTag(String name, String description) {
this.tags.add(new Tag(name, description));
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public String getSwagger() {
return swagger;
}
public void setSwagger(String swagger) {
this.swagger = swagger;
}
public String getBasePath() {
return basePath;
}
public void setBasePath(String basePath) {
this.basePath = basePath;
}
public Map<String, Object> getDefinitions() {
return definitions;
}
public void addDefinitions(String path, Object definition) {
definitions.put(path, definition);
}
public Set<Tag> getTags() {
return tags;
}
public Map<String, Map<String, Path>> getPaths() {
return paths;
}
public Map<String, Object> getSecurityDefinitions() {
return securityDefinitions;
}
public List<Map<String, Object>> getSecurity() {
return security;
}
public void addSecurityDefinitions(Map<String, Object> map) {
securityDefinitions.putAll(map);
}
public void addSecurity(Map<String, Object> map) {
security.add(map);
}
public static class Concat {
private String name;
private String url;
private String email;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
public static class Info {
private String description;
private String version;
private String title;
private License license;
private Concat concat;
public Info(String description, String version, String title, License license, Concat concat) {
this.description = description;
this.version = version;
this.title = title;
this.license = license;
this.concat = concat;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public License getLicense() {
return license;
}
public void setLicense(License license) {
this.license = license;
}
public Concat getConcat() {
return concat;
}
public void setConcat(Concat concat) {
this.concat = concat;
}
}
public static class Path {
private List<String> tags = new ArrayList<>();
private String summary;
private String description;
private final String operationId;
private List<String> produces = new ArrayList<>();
private List<String> consumes = new ArrayList<>();
private List<Map<String, Object>> parameters = new ArrayList<>();
private Map<String, Object> responses = new HashMap<>();
public Path(String operationId) {
this.operationId = operationId;
}
public void addProduce(String produce) {
this.produces.add(produce);
}
public void addConsume(String consume) {
this.consumes.add(consume);
}
public void addParameter(Map<String, Object> parameter) {
this.parameters.add(parameter);
}
public String getOperationId() {
return operationId;
}
public void addResponse(String status, Object object) {
Map<String, Object> response = new HashMap<>();
response.put("description", "OK");
response.put("schema", doProcessSchema(object));
response.put("example", object);
this.responses.put(status, response);
}
public List<String> getTags() {
return tags;
}
public void setTags(List<String> tags) {
this.tags = tags;
}
public void addTag(String tag) {
this.tags.add(tag);
}
public String getSummary() {
return summary;
}
public void setSummary(String summary) {
this.summary = summary;
}
public List<String> getProduces() {
return produces;
}
public void setProduces(List<String> produces) {
this.produces = produces;
}
public List<String> getConsumes() {
return consumes;
}
public void setConsumes(List<String> consumes) {
this.consumes = consumes;
}
public List<Map<String, Object>> getParameters() {
return parameters;
}
public void setParameters(List<Map<String, Object>> parameters) {
this.parameters = parameters;
}
public Map<String, Object> getResponses() {
return responses;
}
public void setResponses(Map<String, Object> responses) {
this.responses = responses;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
public static class Parameter {
private String name;
private String in;
private boolean required = false;
private String type;
private Object schema;
private String description;
private Object example;
public Parameter(boolean required, String name, String in, String type, String description, Object example) {
this.name = name;
this.in = in;
this.type = type;
this.description = description;
this.required = required;
if ("body".equalsIgnoreCase(in)) {
this.schema = "";
} else {
this.example = example;
/*
* fix swagger文档使用knife4j时无法显示接口详情的问题(query类型参数)
* schema 需设置为空字符串,否则请求参数中数据类型字段显示不正确
*/
this.schema = "";
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getIn() {
return in;
}
public void setIn(String in) {
this.in = in;
}
public boolean isRequired() {
return required;
}
public void setRequired(boolean required) {
this.required = required;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Object getSchema() {
return schema;
}
public void setSchema(Object schema) {
this.schema = schema;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Object getExample() {
return example;
}
public void setExample(Object example) {
this.example = example;
}
}
public static class Tag {
private String name;
private String description;
public Tag(String name, String description) {
this.name = name;
this.description = description;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Tag tag = (Tag) o;
return Objects.equals(name, tag.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
}
public static class License {
private String name;
private String url;
public License(String name, String url) {
this.name = name;
this.url = url;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
public static class BasicAuth {
public final static String KEY_NAME = "BasicAuth";
/**
* 类型,默认值
*/
private String type = "basic";
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
public static class ApiKeyAuth {
public final static String KEY_NAME = "ApiKeyAuth";
private String type = "apiKey";
private String name = "header";
private String in = "X-API-Key";
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getIn() {
return in;
}
public void setIn(String in) {
this.in = in;
}
}
public static class OAuth2 {
public final static String KEY_NAME = "OAuth2";
private String type = "oauth2";
private String flow;
private String authorizationUrl;
private String tokenUrl;
private Map<String, String> scopes;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getFlow() {
return flow;
}
public void setFlow(String flow) {
this.flow = flow;
}
public String getAuthorizationUrl() {
return authorizationUrl;
}
public void setAuthorizationUrl(String authorizationUrl) {
this.authorizationUrl = authorizationUrl;
}
public String getTokenUrl() {
return tokenUrl;
}
public void setTokenUrl(String tokenUrl) {
this.tokenUrl = tokenUrl;
}
public Map<String, String> getScopes() {
return scopes;
}
public void setScopes(Map<String, String> scopes) {
this.scopes = scopes;
}
}
}
package org.ssssssss.magicapi.springdoc.entity;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.ResponseBody;
import org.ssssssss.magicapi.core.config.MagicConfiguration;
import org.ssssssss.magicapi.core.model.ApiInfo;
import org.ssssssss.magicapi.core.model.BaseDefinition;
import org.ssssssss.magicapi.core.model.DataType;
import org.ssssssss.magicapi.core.model.Path;
import org.ssssssss.magicapi.core.service.MagicResourceService;
import org.ssssssss.magicapi.core.service.impl.RequestMagicDynamicRegistry;
import org.ssssssss.magicapi.utils.JsonUtils;
import org.ssssssss.magicapi.utils.PathUtils;
import org.ssssssss.script.parsing.ast.literal.BooleanLiteral;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import static org.ssssssss.magicapi.core.config.Constants.*;
/**
* 生成swagger用的json
*
* @author mxd
*/
public class SwaggerProvider {
/**
* swagger Model定义路径前缀
*/
private static final String DEFINITION = "#/definitions/";
/**
* body空对象
*/
private static final String BODY_EMPTY = "{}";
private final Map<String, Object> DEFINITION_MAP = new ConcurrentHashMap<>();
private final RequestMagicDynamicRegistry requestMagicDynamicRegistry;
private final MagicResourceService magicResourceService;
/**
* 基础路径
*/
private final String basePath;
private final SwaggerEntity.Info info;
private final boolean persistenceResponseBody;
private final String prefix;
private final Map<String, Object> securityDefinitionMap;
private final Map<String, Object> securityMap;
public SwaggerProvider(RequestMagicDynamicRegistry requestMagicDynamicRegistry, MagicResourceService magicResourceService,
String basePath, SwaggerEntity.Info info, boolean persistenceResponseBody, String prefix, Map<String, Object> securityDefinitionMap, Map<String, Object> securityMap) {
this.requestMagicDynamicRegistry = requestMagicDynamicRegistry;
this.magicResourceService = magicResourceService;
this.basePath = basePath;
this.info = info;
this.persistenceResponseBody = persistenceResponseBody;
this.prefix = StringUtils.defaultIfBlank(prefix, "") + "/";
this.securityDefinitionMap = securityDefinitionMap;
this.securityMap = securityMap;
}
@ResponseBody
public SwaggerEntity swaggerJson() {
this.DEFINITION_MAP.clear();
List<ApiInfo> infos = requestMagicDynamicRegistry.mappings();
SwaggerEntity swaggerEntity = new SwaggerEntity();
swaggerEntity.setInfo(info);
swaggerEntity.setBasePath(this.basePath);
swaggerEntity.addSecurityDefinitions(securityDefinitionMap);
swaggerEntity.addSecurity(securityMap);
for (ApiInfo info : infos) {
String groupName = magicResourceService.getGroupName(info.getGroupId()).replace("/", "-");
String requestPath = PathUtils.replaceSlash(this.prefix + magicResourceService.getGroupPath(info.getGroupId()) + "/" + info.getPath());
SwaggerEntity.Path path = new SwaggerEntity.Path(info.getId());
path.addTag(groupName);
boolean hasBody = false;
try {
List<Map<String, Object>> parameters = parseParameters(info);
hasBody = parameters.stream().anyMatch(it -> VAR_NAME_REQUEST_BODY.equals(it.get("in")));
BaseDefinition baseDefinition = info.getRequestBodyDefinition();
if (hasBody && baseDefinition != null) {
doProcessDefinition(baseDefinition, info, groupName, "root_", "request", 0);
}
parameters.forEach(path::addParameter);
if (this.persistenceResponseBody) {
baseDefinition = info.getResponseBodyDefinition();
if (baseDefinition != null) {
Map<String, Object> responseMap = parseResponse(info);
if (!responseMap.isEmpty()) {
path.setResponses(responseMap);
doProcessDefinition(baseDefinition, info, groupName, "root_" + baseDefinition.getName(), "response", 0);
}
} else {
path.addResponse("200", JsonUtils.readValue(Objects.toString(info.getResponseBody(), BODY_EMPTY), Object.class));
}
}
} catch (Exception ignored) {
}
if (hasBody) {
path.addConsume("application/json");
} else {
path.addConsume("*/*");
}
path.addProduce("application/json");
path.setSummary(info.getName());
path.setDescription(StringUtils.defaultIfBlank(info.getDescription(), info.getName()));
swaggerEntity.addPath(requestPath, info.getMethod(), path);
}
if (this.DEFINITION_MAP.size() > 0) {
Set<Map.Entry<String, Object>> entries =this.DEFINITION_MAP.entrySet();
for (Map.Entry<String, Object> entry : entries) {
swaggerEntity.addDefinitions(entry.getKey(), entry.getValue());
}
}
return swaggerEntity;
}
private List<Map<String, Object>> parseParameters(ApiInfo info) {
List<Map<String, Object>> parameters = new ArrayList<>();
info.getParameters().forEach(it -> parameters.add(SwaggerEntity.createParameter(it.isRequired(), it.getName(), VAR_NAME_QUERY, it.getDataType().getJavascriptType(), it.getDescription(), it.getValue())));
info.getHeaders().forEach(it -> parameters.add(SwaggerEntity.createParameter(it.isRequired(), it.getName(), VAR_NAME_HEADER, it.getDataType().getJavascriptType(), it.getDescription(), it.getValue())));
List<Path> paths = new ArrayList<>(info.getPaths());
MagicConfiguration.getMagicResourceService().getGroupsByFileId(info.getId())
.stream()
.flatMap(it -> it.getPaths().stream())
.filter(it -> !paths.contains(it))
.forEach(paths::add);
paths.forEach(it -> parameters.add(SwaggerEntity.createParameter(it.isRequired(), it.getName(), VAR_NAME_PATH_VARIABLE, it.getDataType().getJavascriptType(), it.getDescription(), it.getValue())));
try {
BaseDefinition baseDefinition = info.getRequestBodyDefinition();
if (baseDefinition != null && !CollectionUtils.isEmpty(baseDefinition.getChildren())) {
Map<String, Object> parameter = SwaggerEntity.createParameter(baseDefinition.isRequired(), StringUtils.isNotBlank(baseDefinition.getName()) ? baseDefinition.getName() : VAR_NAME_REQUEST_BODY, VAR_NAME_REQUEST_BODY, baseDefinition.getDataType().getJavascriptType(), baseDefinition.getDescription(), baseDefinition);
Map<String, Object> schema = new HashMap<>(2);
String groupName = magicResourceService.getGroupName(info.getGroupId()).replace("/", "-");
String voName = groupName + "«" + info.getPath().replaceFirst("/", "").replaceAll("/", "_") + "«request«";
if (DataType.Array == baseDefinition.getDataType()) {
voName += "root_" + (StringUtils.isNotBlank(baseDefinition.getName()) ? baseDefinition.getName() + "_" : "_") + "»»»";
Map<String, Object> items = new HashMap<>(2);
items.put("originalRef", voName);
items.put("$ref", DEFINITION + voName);
schema.put("items", items);
schema.put("type", VAR_NAME_REQUEST_BODY_VALUE_TYPE_ARRAY);
} else {
voName += "root_" + baseDefinition.getName() + "»»»";
schema.put("originalRef", voName);
schema.put("$ref", DEFINITION + voName);
}
parameter.put("schema", schema);
parameters.add(parameter);
} else if (StringUtils.isNotBlank(info.getRequestBody())) {
Object object = JsonUtils.readValue(info.getResponseBody(), Object.class);
boolean isListOrMap = (object instanceof List || object instanceof Map);
if (isListOrMap && BooleanLiteral.isTrue(object)) {
parameters.add(SwaggerEntity.createParameter(false, VAR_NAME_REQUEST_BODY, VAR_NAME_REQUEST_BODY, object instanceof List ? VAR_NAME_REQUEST_BODY_VALUE_TYPE_ARRAY : VAR_NAME_REQUEST_BODY_VALUE_TYPE_OBJECT, null, object));
}
}
} catch (Exception ignored) {
}
return parameters;
}
private Map<String, Object> parseResponse(ApiInfo info) {
Map<String, Object> result = new HashMap<>();
BaseDefinition baseDefinition = info.getResponseBodyDefinition();
if (!CollectionUtils.isEmpty(baseDefinition.getChildren())) {
String groupName = magicResourceService.getGroupName(info.getGroupId()).replace("/", "-");
String voName = groupName + "«" + info.getPath().replaceFirst("/", "").replaceAll("/", "_") + "«response«";
voName += "root_" + baseDefinition.getName() + "»»»";
Map<String, Object> schema = new HashMap<>(2);
schema.put("originalRef", voName);
schema.put("$ref", DEFINITION + voName);
Map<String, Object> response = new HashMap<>(2);
response.put("description", "OK");
response.put("schema", schema);
result.put("200", response);
}
return result;
}
private Map<String, Object> doProcessDefinition(BaseDefinition target, ApiInfo info, String groupName, String parentName, String definitionType, int level) {
Map<String, Object> result = new HashMap<>(4);
result.put("description", target.getDescription());
if (DataType.Array == target.getDataType()) {
if (!CollectionUtils.isEmpty(target.getChildren())) {
result.put("items", doProcessDefinition(target.getChildren().get(0), info, groupName, parentName + target.getName() + "_", definitionType, level + 1));
} else {
result.put("items", Collections.emptyList());
}
result.put("type", target.getDataType().getJavascriptType());
} else if (DataType.Object == target.getDataType() || DataType.Any == target.getDataType()) {
String voName = groupName + "«" + info.getPath().replaceFirst("/", "").replaceAll("/", "_") + (StringUtils.equals("response", definitionType) ? "«response«" : "«request«") + parentName + target.getName() + "»»»";
Map<String, Object> definition = new HashMap<>(4);
Map<String, Map<String, Object>> properties = new HashMap<>(target.getChildren().size());
Set<String> requiredSet = new HashSet<>(target.getChildren().size());
for (BaseDefinition obj : target.getChildren()) {
properties.put(obj.getName(), doProcessDefinition(obj, info, groupName, parentName + target.getName() + "_", definitionType, level + 1));
if (obj.isRequired()) {
requiredSet.add(obj.getName());
}
}
definition.put("properties", properties);
definition.put("description", target.getDescription());
definition.put("type", target.getDataType().getJavascriptType());
definition.put("required", requiredSet);
if (this.DEFINITION_MAP.containsKey(voName)) {
// TODO 应该不会出现名字都一样的
voName = voName.replace("»»»", "_" + level + "»»»");
}
this.DEFINITION_MAP.put(voName, definition);
result.put("originalRef", voName);
result.put("$ref", DEFINITION + voName);
} else {
result.put("example", target.getValue());
result.put("type", target.getDataType().getJavascriptType());
}
return result;
}
}
......@@ -17,6 +17,7 @@
<module>magic-api-plugin-task</module>
<module>magic-api-plugin-component</module>
<module>magic-api-plugin-swagger</module>
<module>magic-api-plugin-springdoc</module>
<module>magic-api-plugin-redis</module>
<module>magic-api-plugin-mongo</module>
<module>magic-api-plugin-elasticsearch</module>
......
......@@ -19,7 +19,6 @@
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.0.0</version>
<optional>true</optional>
</dependency>
</dependencies>
......
......@@ -35,6 +35,7 @@
<commons-io.version>2.7</commons-io.version>
<commons-text.version>1.6</commons-text.version>
<commons-beanutils.version>1.9.4</commons-beanutils.version>
<jakarta.version>6.0.0</jakarta.version>
<fastjson.version>1.2.83</fastjson.version>
<spring-boot-starter-log4j.version>1.3.8.RELEASE</spring-boot-starter-log4j.version>
<java.version>1.8</java.version>
......@@ -113,6 +114,11 @@
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>${jakarta.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册