我是靠谱客的博主 淡然星星,最近开发中收集的这篇文章主要介绍swagger3 展示枚举类型,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

原文是基于swagger2编写的,在原文的基础上做了相应的改造。适用于swagger3

原文:swagger展示枚举类型
https://blog.csdn.net/weixin_50276625/article/details/115858744

改造点:

1、将 @SwaggerDisplayEnum 注解改为 SwaggerDisplayEnum 接口,优点是会强制枚举类实现 description() 描述方法。
2、针对swagger3,实现类做了相应的调整

一、pom.xml的jar依赖

<!-- swagger3 生成接口api文档 -->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-boot-starter</artifactId>
    <version>3.0.0</version>
    <scope>provided</scope>
</dependency>

二、SwaggerDisplayEnum 接口

public interface SwaggerDisplayEnum {
    String description();
}

三、枚举类实例

import lombok.AllArgsConstructor;
import lombok.Getter;

/**
 * 文件来源类型,1-文件存储服务读取;2-参数Base64传递;
 */
@Getter
@AllArgsConstructor
public enum DictFileFromType implements SwaggerDisplayEnum {

    /**文件存储服务读取*/
    FILE_STORAGE(1, "文件存储服务读取[默认]"),

    /**参数Base64传递*/
    PARAM_BASE64(2, "参数Base64传递");

    private Integer value;
    private String info;

    @Override
    public String description() {
        return value + "-" + info;
    }
}

四、需要显示枚举类型的字段属性

通过 @ApiModelProperty 的 notes 属性标识枚举类的全路径
/**
 * 文件的来源类型
 * @see  DictFileFromType
 */
@ApiModelProperty(value = "word文件来源类型(可选参数).", notes = "***.dict.DictFileFromType")
private Integer docFileFromType = DictFileFromType.FILE_STORAGE.getValue();

五、swaggerConfig 配置文件

@ConditionalOnProperty(name = “spring.profiles.active”, havingValue = “dev”, matchIfMissing = true),仅当开发环境的时候才加载,生产环境则不会加载swagger

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.PropertySpecificationBuilder;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.schema.Annotations;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.schema.ModelPropertyBuilderPlugin;
import springfox.documentation.spi.schema.contexts.ModelPropertyContext;
import springfox.documentation.spring.web.plugins.Docket;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

@Slf4j
@Configuration
@EnableOpenApi
@ConditionalOnProperty(name = "spring.profiles.active", havingValue = "dev", matchIfMissing = true)
public class Swagger3Config implements ModelPropertyBuilderPlugin {

    /**
     * 创建swagger API文档,访问地址http://host:port/productName/swagger-ui/
     * <p>1、apiInfo():增加API相关的信息.
     * <p>2、select():返回ApiSelectorBuilder实例,用于控制哪些接口暴露给swagger来展现.
     * <p>3、apis():指定扫描的路径来指定要建立的API目录.
     *     RequestHandlerSelectors 用于配置要扫描的包,以下参数可选:
     *         basePackage():指定要扫描的包.
     *         any():扫描全部.
     *         none():都不扫描.
     *         withMethodAnnotation:扫描方法上的注解, 参数是一个注解的反射对象.
     *         withClassAnnotation:扫描类上的注解, 参数是一个注解的反射对象.
     *             例如:withClassAnnotation(RestController .class) 只扫描类上有@RestController的生成文档.
     * <p>4、paths():过滤什么路径.
     */
    @Bean
    public Docket createApi() {
        log.info("====> [Swagger3]开启.");
        return new Docket(DocumentationType.OAS_30)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
                .paths(PathSelectors.any())
                .build();
    }

    /**
     * Swagger2主界面信息,描述api的基本信息用于展示
     */
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("文档转换服务")
                .description("《文档转换服务》接口定义和规范")
                .termsOfServiceUrl("http://www.huaxinsign.com/")
                .contact(new Contact("华信云盛", "http://www.huaxinsign.com/", "unisign@huaxinsign.com"))
                .version("1.0")
                .license("版权所有©北京华信云盛科技有限公司")
                .build();
    }

    @Override
    public void apply(ModelPropertyContext context) {
        //为枚举字段设置注释
        descForEnumFields(context);
    }

    /**
     * 返回是否应根据给定的分隔符调用插件
     */
    @Override
    public boolean supports(DocumentationType documentationType) {
        return true;
    }

    /**
     * 为枚举字段设置注释
     */
    private void descForEnumFields(ModelPropertyContext context) {
        Optional<ApiModelProperty> annotation = Optional.empty();

        // 找到 @ApiModelProperty 注解修饰的枚举类
        if (context.getBeanPropertyDefinition().isPresent()) {
            annotation = Annotations.findPropertyAnnotation(context.getBeanPropertyDefinition().get(), ApiModelProperty.class);
        }

        //没有@ApiModelProperty 或者 notes 属性没有值,直接返回
        if (!annotation.isPresent() || StringUtils.isEmpty((annotation.get()).notes())) {
            return;
        }

        //@ApiModelProperties中的notes指定的class类型
        Class rawPrimaryType;
        try {
            rawPrimaryType = Class.forName((annotation.get()).notes());
        } catch (ClassNotFoundException e) {
            //如果指定的类型无法转化,直接忽略
            return;
        }

        Object[] subItemRecords = null;
        // 判断 rawPrimaryType 是否为枚举,且实现了 SwaggerDisplayEnum 接口
        if (Enum.class.isAssignableFrom(rawPrimaryType) && SwaggerDisplayEnum.class.isAssignableFrom(rawPrimaryType)) {
            // 拿到枚举的所有的值
            subItemRecords = rawPrimaryType.getEnumConstants();
        } else {
            return;
        }

        final List<String> displayValues = Arrays.stream(subItemRecords).filter(Objects::nonNull)
                        // 调用枚举类的 description 方法
                        .map(p -> ((SwaggerDisplayEnum) p).description()).filter(Objects::nonNull).collect(Collectors.toList());

        String joinText = " (" + String.join("; ", displayValues) + ")";
        try {
            // 拿到字段上原先的描述
            Field mField = PropertySpecificationBuilder.class.getDeclaredField("description");
            mField.setAccessible(true);
            // context 中的 builder 对象保存了字段的信息
            joinText = mField.get(context.getSpecificationBuilder()) + joinText;
        } catch (Exception e) {
            log.error(e.getMessage());
        }

        // 设置新的字段说明并且设置字段类型
        context.getSpecificationBuilder().description(joinText);
    }

}

六、SpringMVC拦截器配置

如果是实现WebMvcConfigurer接口则无需配置。

@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {

    /**
     * 配置SpringMvc不拦截 swagger3 的接口
     * @param registry
     */
    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/swagger-ui/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/");
    }
}

七、SpringBoot启动类添加文档连接

public static void main(String[] args) {
    ConfigurableApplicationContext context = SpringApplication.run(DocConvertApplication.class, args);

    if(context.containsBean("swagger3Config")){
        try {
            // 访问地址http://host:port/productName/swagger-ui/
            log.info("====> [Swagger3]文档的访问路径:http://{}:{}/{}/swagger-ui/index.html",
                    InetAddress.getLocalHost().getHostAddress(),
                    context.getEnvironment().getProperty("server.port"),
                    context.getEnvironment().getProperty("spring.application.name"));
        } catch (Exception ignored){}
    }
}

最后

以上就是淡然星星为你收集整理的swagger3 展示枚举类型的全部内容,希望文章能够帮你解决swagger3 展示枚举类型所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(35)

评论列表共有 0 条评论

立即
投稿
返回
顶部