add swagger starter.

This commit is contained in:
ljh01459796
2023-06-21 18:34:22 +08:00
parent 95150b6be7
commit 40e231f0d8
12 changed files with 361 additions and 6 deletions

View File

@@ -18,6 +18,9 @@
<spring.boot.version>2.7.11</spring.boot.version>
<orion.all.version>1.0.5</orion.all.version>
<lombok.version>1.18.26</lombok.version>
<springdoc.version>1.6.15</springdoc.version>
<knife4j.version>4.1.0</knife4j.version>
<mapstruct.version>1.5.5.Final</mapstruct.version>
</properties>
@@ -60,16 +63,52 @@
<artifactId>orion-ops-spring-boot-starter-web</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.orion.ops</groupId>
<artifactId>orion-ops-spring-boot-starter-swagger</artifactId>
<version>${revision}</version>
</dependency>
<!-- spring -->
<!-- other -->
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<!-- mapstruct -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${mapstruct.version}</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<version>${mapstruct.version}</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</dependency>
<!-- doc -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>${springdoc.version}</version>
</dependency>
<!-- knife4j -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-spring-boot-starter</artifactId>
<version>${knife4j.version}</version>
</dependency>
</dependencies>
</dependencyManagement>

View File

@@ -26,6 +26,27 @@
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- mapstruct -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
</dependency>
<!-- doc -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@@ -33,7 +33,7 @@ public class BannerApplicationRunner implements ApplicationRunner {
String line = AnsiCode.GLOSS_GREEN.stain(":: orion-ops-server v" + version + " 服务已启动(" + env + ") ::\n") +
AnsiCode.GLOSS_GREEN.stain(":: swagger 文档 ") +
// TODO swagger 地址
AnsiCode.GLOSS_BLUE.stain("http://127.0.0.1:xxxx/dox.html\n") +
AnsiCode.GLOSS_BLUE.stain("http://127.0.0.1:" + port + "/doc.html\n") +
AnsiCode.GLOSS_GREEN.stain(":: server 心跳检测 ") +
AnsiCode.GLOSS_BLUE +
"curl -X GET --location \"http://127.0.0.1:" + port + apiPrefix + "/server/bootstrap/health\"" +

View File

@@ -9,3 +9,4 @@ ${AnsiColor.BRIGHT_GREEN}:: Application Name ${AnsiColor.BLUE}${spring.appli
${AnsiColor.BRIGHT_GREEN}:: Application Version ${AnsiColor.BLUE}${orion.version}
${AnsiColor.BRIGHT_GREEN}:: SpringBoot Version ${AnsiColor.BLUE}${spring-boot.version}
${AnsiColor.BRIGHT_GREEN}:: Active Profile ${AnsiColor.BLUE}${spring.profiles.active}
${AnsiColor.DEFAULT}

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.orion.ops</groupId>
<artifactId>orion-ops-framework</artifactId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>orion-ops-spring-boot-starter-swagger</artifactId>
<name>${project.artifactId}</name>
<packaging>jar</packaging>
<description>项目 swagger 配置包</description>
<url>https://github.com/lijiahangmax/orion-ops-pro</url>
<dependencies>
<dependency>
<groupId>com.orion.ops</groupId>
<artifactId>orion-ops-common</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- doc -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
</dependency>
<!-- knife4j -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,160 @@
package com.orion.ops.framework.swagger.config;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.media.StringSchema;
import io.swagger.v3.oas.models.parameters.Parameter;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.springdoc.core.*;
import org.springdoc.core.customizers.OpenApiBuilderCustomizer;
import org.springdoc.core.customizers.ServerBaseUrlCustomizer;
import org.springdoc.core.providers.JavadocProvider;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
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.Profile;
import org.springframework.http.HttpHeaders;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
/**
* swagger 配置
*
* @author Jiahang Li
* @version 1.0.0
* @since 2022/6/21 11:22
*/
@Profile({"dev"})
@ConditionalOnClass({OpenAPI.class})
@EnableConfigurationProperties(SwaggerProperties.class)
@ConditionalOnProperty(prefix = "springdoc.api-docs", name = "enabled", havingValue = "true", matchIfMissing = true)
@AutoConfiguration
public class OrionSwaggerAutoConfiguration {
private static String orionApiPrefix;
/**
* @param properties 配置
* @return API
*/
@Bean
public OpenAPI createApi(SwaggerProperties properties) {
Map<String, SecurityScheme> securitySchemas = this.buildSecuritySchemes();
OpenAPI api = new OpenAPI()
// 接口信息
.info(buildInfo(properties))
// 接口安全配置
.components(new Components().securitySchemes(securitySchemas));
securitySchemas.keySet()
.forEach(key -> api.addSecurityItem(new SecurityRequirement().addList(key)));
return api;
}
/**
* api 摘要信息
*/
private Info buildInfo(SwaggerProperties properties) {
return new Info()
.title(properties.getTitle())
.description(properties.getDescription())
.version(properties.getVersion())
.contact(new Contact().name(properties.getAuthor()).url(properties.getUrl()).email(properties.getEmail()))
.license(new License().name(properties.getLicense()).url(properties.getLicenseUrl()));
}
/**
* 配置请求头 Authorization 传递 token 参数
*
* @return 安全模式
*/
private Map<String, SecurityScheme> buildSecuritySchemes() {
Map<String, SecurityScheme> securitySchemes = new HashMap<>();
SecurityScheme securityScheme = new SecurityScheme()
// 类型
.type(SecurityScheme.Type.APIKEY)
// 请求头的 name
.name(HttpHeaders.AUTHORIZATION)
// token 所在位置
.in(SecurityScheme.In.HEADER);
securitySchemes.put(HttpHeaders.AUTHORIZATION, securityScheme);
return securitySchemes;
}
/**
* @return 自定义 OpenAPI 处理器
*/
@Bean
public OpenAPIService openApiBuilder(Optional<OpenAPI> openAPI,
SecurityService securityParser,
SpringDocConfigProperties springDocConfigProperties,
PropertyResolverUtils propertyResolverUtils,
Optional<List<OpenApiBuilderCustomizer>> openApiBuilderCustomizers,
Optional<List<ServerBaseUrlCustomizer>> serverBaseUrlCustomizers,
Optional<JavadocProvider> javadocProvider) {
return new OpenAPIService(openAPI, securityParser, springDocConfigProperties,
propertyResolverUtils, openApiBuilderCustomizers, serverBaseUrlCustomizers, javadocProvider);
}
/**
* @return 所有模块的 api 分组
*/
@Bean
public GroupedOpenApi allGroupedOpenApi() {
return buildGroupedOpenApi("全部", "");
}
/**
* 构建 api 分组
*
* @param group group
* @return group
*/
public static GroupedOpenApi buildGroupedOpenApi(String group) {
return buildGroupedOpenApi(group, group);
}
/**
* 构建 api 分组
*
* @param group group
* @param path path
* @return group
*/
public static GroupedOpenApi buildGroupedOpenApi(String group, String path) {
return GroupedOpenApi.builder()
.group(group)
.pathsToMatch(orionApiPrefix + "/" + path + "/**")
.addOperationCustomizer((operation, handlerMethod) -> operation
.addParametersItem(buildSecurityHeaderParameter()))
.build();
}
/**
* @return Authorization 认证请求头参数
*/
private static Parameter buildSecurityHeaderParameter() {
return new Parameter()
.name(HttpHeaders.AUTHORIZATION)
.description("认证 Token")
.in(String.valueOf(SecurityScheme.In.HEADER))
.schema(new StringSchema()._default("Bearer ").name("NAME").description("认证 Token"));
}
@Value("${orion.api.prefix}")
public void setOrionApiPrefix(String orionApiPrefix) {
OrionSwaggerAutoConfiguration.orionApiPrefix = orionApiPrefix;
}
}

View File

@@ -0,0 +1,55 @@
package com.orion.ops.framework.swagger.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* @author Jiahang Li
* @version 1.0.0
* @since 2023/6/21 11:13
*/
@Data
@ConfigurationProperties("orion.swagger")
public class SwaggerProperties {
/**
* 标题
*/
private String title;
/**
* 描述
*/
private String description;
/**
* 作者
*/
private String author;
/**
* 版本
*/
private String version;
/**
* url
*/
private String url;
/**
* email
*/
private String email;
/**
* license
*/
private String license;
/**
* license-url
*/
private String licenseUrl;
}

View File

@@ -0,0 +1 @@
com.orion.ops.framework.swagger.config.OrionSwaggerAutoConfiguration

View File

@@ -15,6 +15,8 @@ import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.http.MediaType;
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
@@ -27,6 +29,8 @@ import java.util.List;
/**
* web 配置类
* <p>
* TODO XSS 后续选择性的配置
*
* @author Jiahang Li
* @version 1.0.0
@@ -38,12 +42,12 @@ public class OrionWebAutoConfiguration implements WebMvcConfigurer {
@Value("${orion.api.prefix}")
private String orionApiPrefix;
// TODO XSS
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
// 公共 api 前缀
configurer.addPathPrefix(orionApiPrefix, clazz -> clazz.isAnnotationPresent(RestController.class));
AntPathMatcher antPathMatcher = new AntPathMatcher(".");
configurer.addPathPrefix(orionApiPrefix, clazz -> clazz.isAnnotationPresent(RestController.class)
&& antPathMatcher.match("com.orion.ops.**.controller.**", clazz.getPackage().getName())); // 仅仅匹配 controller 包
}
/**

View File

@@ -17,8 +17,9 @@
<modules>
<module>orion-ops-common</module>
<module>orion-ops-spring-boot-starter-banner</module>
<module>orion-ops-spring-boot-starter-web</module>
<module>orion-ops-spring-boot-starter-banner</module>
<module>orion-ops-spring-boot-starter-swagger</module>
</modules>
</project>

View File

@@ -32,6 +32,10 @@
<groupId>com.orion.ops</groupId>
<artifactId>orion-ops-spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.orion.ops</groupId>
<artifactId>orion-ops-spring-boot-starter-swagger</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>

View File

@@ -21,11 +21,37 @@ spring:
pathmatch:
matching-strategy: ANT_PATH_MATCHER
springdoc:
api-docs:
enabled: true
path: /v3/api-docs
swagger-ui:
enabled: true
path: /swagger-ui
tags-sorter: alpha
operations-sorter: alpha
show-extensions: true
knife4j:
enable: true
setting:
language: zh_cn
orion:
# 版本
version: @revision@
# api 信息
api:
# 公共api前缀
prefix: /orion-api
# 是否开启跨域
cors: true
# 文档配置
swagger:
title: orion-ops-pro 运维平台
description: 一站式提供运维功能
version: ${orion.version}
url: https://github.com/lijiahangmax/orion-ops-pro
email: ljh1553488six@139.com
license: Apache-2.0
license-url: https://github.com/lijiahangmax/orion-ops-pro/blob/main/LICENSE