Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
ssssssss-team
magic-api
提交
21c15a39
M
magic-api
项目概览
ssssssss-team
/
magic-api
9 个月 前同步成功
通知
41
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
M
magic-api
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
21c15a39
编写于
3月 18, 2023
作者:
J
jmxd
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
添加springdoc插件,不支持spring boot 2.x 版本
上级
d4a3593f
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
1212 addition
and
1 deletion
+1212
-1
magic-api-plugins/magic-api-plugin-springdoc/pom.xml
magic-api-plugins/magic-api-plugin-springdoc/pom.xml
+50
-0
magic-api-plugins/magic-api-plugin-springdoc/src/main/java/org/ssssssss/magicapi/springdoc/MagicSpringDocConfiguration.java
...sssss/magicapi/springdoc/MagicSpringDocConfiguration.java
+137
-0
magic-api-plugins/magic-api-plugin-springdoc/src/main/java/org/ssssssss/magicapi/springdoc/SpringDocConfig.java
...java/org/ssssssss/magicapi/springdoc/SpringDocConfig.java
+145
-0
magic-api-plugins/magic-api-plugin-springdoc/src/main/java/org/ssssssss/magicapi/springdoc/entity/SwaggerEntity.java
...org/ssssssss/magicapi/springdoc/entity/SwaggerEntity.java
+637
-0
magic-api-plugins/magic-api-plugin-springdoc/src/main/java/org/ssssssss/magicapi/springdoc/entity/SwaggerProvider.java
...g/ssssssss/magicapi/springdoc/entity/SwaggerProvider.java
+235
-0
magic-api-plugins/magic-api-plugin-springdoc/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
...ingframework.boot.autoconfigure.AutoConfiguration.imports
+1
-0
magic-api-plugins/pom.xml
magic-api-plugins/pom.xml
+1
-0
magic-api-servlet/magic-api-servlet-jakarta/pom.xml
magic-api-servlet/magic-api-servlet-jakarta/pom.xml
+0
-1
pom.xml
pom.xml
+6
-0
未找到文件。
magic-api-plugins/magic-api-plugin-springdoc/pom.xml
0 → 100644
浏览文件 @
21c15a39
<?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>
magic-api-plugins/magic-api-plugin-springdoc/src/main/java/org/ssssssss/magicapi/springdoc/MagicSpringDocConfiguration.java
0 → 100644
浏览文件 @
21c15a39
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"
));
}
}
magic-api-plugins/magic-api-plugin-springdoc/src/main/java/org/ssssssss/magicapi/springdoc/SpringDocConfig.java
0 → 100644
浏览文件 @
21c15a39
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
;
}
}
magic-api-plugins/magic-api-plugin-springdoc/src/main/java/org/ssssssss/magicapi/springdoc/entity/SwaggerEntity.java
0 → 100644
浏览文件 @
21c15a39
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
;
}
}
}
magic-api-plugins/magic-api-plugin-springdoc/src/main/java/org/ssssssss/magicapi/springdoc/entity/SwaggerProvider.java
0 → 100644
浏览文件 @
21c15a39
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
;
}
}
magic-api-plugins/magic-api-plugin-springdoc/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
0 → 100644
浏览文件 @
21c15a39
org.ssssssss.magicapi.springdoc.MagicSpringDocConfiguration
\ No newline at end of file
magic-api-plugins/pom.xml
浏览文件 @
21c15a39
...
@@ -17,6 +17,7 @@
...
@@ -17,6 +17,7 @@
<module>
magic-api-plugin-task
</module>
<module>
magic-api-plugin-task
</module>
<module>
magic-api-plugin-component
</module>
<module>
magic-api-plugin-component
</module>
<module>
magic-api-plugin-swagger
</module>
<module>
magic-api-plugin-swagger
</module>
<module>
magic-api-plugin-springdoc
</module>
<module>
magic-api-plugin-redis
</module>
<module>
magic-api-plugin-redis
</module>
<module>
magic-api-plugin-mongo
</module>
<module>
magic-api-plugin-mongo
</module>
<module>
magic-api-plugin-elasticsearch
</module>
<module>
magic-api-plugin-elasticsearch
</module>
...
...
magic-api-servlet/magic-api-servlet-jakarta/pom.xml
浏览文件 @
21c15a39
...
@@ -19,7 +19,6 @@
...
@@ -19,7 +19,6 @@
<dependency>
<dependency>
<groupId>
jakarta.servlet
</groupId>
<groupId>
jakarta.servlet
</groupId>
<artifactId>
jakarta.servlet-api
</artifactId>
<artifactId>
jakarta.servlet-api
</artifactId>
<version>
6.0.0
</version>
<optional>
true
</optional>
<optional>
true
</optional>
</dependency>
</dependency>
</dependencies>
</dependencies>
...
...
pom.xml
浏览文件 @
21c15a39
...
@@ -35,6 +35,7 @@
...
@@ -35,6 +35,7 @@
<commons-io.version>
2.7
</commons-io.version>
<commons-io.version>
2.7
</commons-io.version>
<commons-text.version>
1.6
</commons-text.version>
<commons-text.version>
1.6
</commons-text.version>
<commons-beanutils.version>
1.9.4
</commons-beanutils.version>
<commons-beanutils.version>
1.9.4
</commons-beanutils.version>
<jakarta.version>
6.0.0
</jakarta.version>
<fastjson.version>
1.2.83
</fastjson.version>
<fastjson.version>
1.2.83
</fastjson.version>
<spring-boot-starter-log4j.version>
1.3.8.RELEASE
</spring-boot-starter-log4j.version>
<spring-boot-starter-log4j.version>
1.3.8.RELEASE
</spring-boot-starter-log4j.version>
<java.version>
1.8
</java.version>
<java.version>
1.8
</java.version>
...
@@ -113,6 +114,11 @@
...
@@ -113,6 +114,11 @@
<artifactId>
fastjson
</artifactId>
<artifactId>
fastjson
</artifactId>
<version>
${fastjson.version}
</version>
<version>
${fastjson.version}
</version>
</dependency>
</dependency>
<dependency>
<groupId>
jakarta.servlet
</groupId>
<artifactId>
jakarta.servlet-api
</artifactId>
<version>
${jakarta.version}
</version>
</dependency>
</dependencies>
</dependencies>
</dependencyManagement>
</dependencyManagement>
<build>
<build>
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录