配置SpringDoc文档枚举值以及描述

本文介绍了如何在SpringDoc中配置枚举值的描述,创建自定义枚举接口IEnum,并为API参数和属性提供枚举值设置和详细描述,以优化Swagger文档的呈现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

配置SpringDoc文档枚举值以及描述

创建自定义枚举 IEnum

import java.io.Serializable

/**
 * 通用枚举接口,定义了枚举的基本行为和属性。
 *
 * @param <V> 枚举值的类型,该类型需实现Serializable接口,以便于序列化和反序列化。
 * @param <E> 子枚举类型,指明实现该接口的具体枚举类。
 */
interface IEnum<V : Serializable> {

    /**
     * 获取枚举项的值。该属性被[@JsonValue]注解标记,用于在JSON序列化和反序列化时使用。
     */
    @get:JsonValue
    val value: V

    /**
     * 从值反序列化枚举。这是一个companion object方法,用于根据提供的值查找并返回对应的枚举常量。
     *
     * @param value 要查找的枚举值。
     * @param B 实现IEnum接口的枚举类。
     * @return 找到的枚举常量,如果未找到则返回null。
     */
    companion object {
        inline fun <reified B, V> Class<B>.fromValue(value: V): B?
                where B : IEnum<V>, V : Serializable {
            return enumConstants?.asSequence()
                ?.filter { it.value == value } // 筛选出值匹配的枚举常量
                ?.firstOrNull() // 获取第一个匹配项,若无则返回null
        }
    }
}


创建工具类

import io.swagger.v3.core.util.PrimitiveType
import io.swagger.v3.oas.models.media.ObjectSchema
import io.swagger.v3.oas.models.media.Schema
import org.springframework.beans.BeanUtils
import org.springframework.util.ReflectionUtils
import java.lang.reflect.Modifier
import java.lang.reflect.Type

/**
 * IEnum枚举自定义器接口,提供操作枚举的自定义方法
 * @see IEnum
 */
interface IEnumCustomizer {

    /**
     * 获取枚举的所有值
     *
     * @param enumClazz 枚举的class
     * @return 枚举的所有值列表
     */
    fun getValues(enumClazz: Class<*>): List<Any> {
        // 通过反射获取枚举类的所有常量
        return enumClazz.enumConstants
            .mapNotNull { item ->
                // 收集每个枚举值的"getValue"方法返回的值
                val getValue = ReflectionUtils.findMethod(item.javaClass, "getValue")
                getValue?.let {
                    ReflectionUtils.makeAccessible(it)
                    ReflectionUtils.invokeMethod(it, item)
                }
            }
    }

    /**
     * 获取枚举值和对应描述的字符串表示
     *
     * @param enumClazz 枚举的class
     * @return 描述信息字符串
     */
    fun getDescription(enumClazz: Class<*>): String {
        // 获取枚举类中非静态字段,并按名称降序排序
        val fieldList = enumClazz.declaredFields
            .filter { !Modifier.isStatic(it.modifiers) }
            .sortedByDescending { it.name }

        // 使所有字段可访问
        fieldList.forEach { ReflectionUtils.makeAccessible(it) }

        // 构建每个枚举值及其字段描述的字符串
        return enumClazz.enumConstants
            .filterNotNull().joinToString("; ") { item ->
                fieldList.joinToString(" : ") { field ->
                    field.get(item).toString()
                }
            }
    }

    /**
     * 根据枚举值的类型获取相应的Swagger Schema对象
     *
     * @param type         枚举值的类型
     * @param sourceSchema 从属性中加载的原始Schema对象
     * @return 枚举值类型对应的Schema对象
     */
    fun getSchemaByType(type: Type, sourceSchema: Schema<*>): Schema<Any> {
        // 根据枚举值类型决定使用哪种类型的Schema
        val schema = PrimitiveType.fromType(type)?.createProperty()
            ?: ObjectSchema()

        // 复制原始schema的属性到新schema
        BeanUtils.copyProperties(sourceSchema, schema)

        // 返回配置好的schema
        return schema
    }
}

创建SpringDoc参数自定义配置

import io.swagger.v3.oas.models.media.Schema
import io.swagger.v3.oas.models.parameters.Parameter
import org.springdoc.core.customizers.ParameterCustomizer
import org.springframework.core.MethodParameter
import org.springframework.stereotype.Component

/**
 * 枚举参数自定义配置类。用于为API枚举参数提供自定义配置,包括参数描述和枚举值的设置。
 */
@Component
class ApiEnumParameterCustomizer : ParameterCustomizer, IEnumCustomizer {

    /**
     * 自定义API参数配置。
     * @param parameterModel API参数模型,用于配置参数属性。
     * @param methodParameter 方法参数,表示当前被解析的方法参数信息。
     * @return 返回经过自定义配置后的参数模型。如果未进行任何修改,则返回原始参数模型。
     */
    override fun customize(parameterModel: Parameter?, methodParameter: MethodParameter): Parameter? {
        val parameterType = methodParameter.parameterType
        parameterModel?.let {
            // 检查当前参数类型是否为枚举类型
            if (IEnum::class.java.isAssignableFrom(parameterType)) {
                // 设置参数描述
                it.description = getDescription(parameterType)
                // 配置参数的枚举值
                val schema = Schema<Any>()
                schema.enum = getValues(parameterType)
                it.schema = schema
            }
        }
        return parameterModel
    }
}

创建SpringDoc属性自定义配置

import com.fasterxml.jackson.databind.type.SimpleType
import io.swagger.v3.core.converter.AnnotatedType
import io.swagger.v3.oas.models.media.Schema
import org.springdoc.core.customizers.PropertyCustomizer
import org.springframework.stereotype.Component
import org.springframework.util.ObjectUtils
import java.lang.reflect.ParameterizedType

/**
 * 枚举属性自定义配置类,用于定制Swagger文档中枚举类型的展示方式。
 */
@Component
class ApiEnumPropertyCustomizer : PropertyCustomizer, IEnumCustomizer {

    /**
     * 自定义Swagger字段的枚举展示。
     * @param property Swagger字段模型
     * @param type 字段的注解类型
     * @return 修改后的Swagger字段模型
     */
    override fun customize(property: Schema<*>, type: AnnotatedType): Schema<*> {
        // 检查类型是否为SimpleType并获取实际字段类
        if (type.type is SimpleType) {
            val fieldClazz = (type.type as SimpleType).rawClass

            // 检查字段类是否为枚举
            if (IEnum::class.java.isAssignableFrom(fieldClazz)) {
                // 获取枚举的父接口,用于解析枚举值的类型
                val genericInterfaces = fieldClazz.genericInterfaces
                if (genericInterfaces.isNotEmpty() && genericInterfaces[0] is ParameterizedType) {
                    // 解析枚举值的实际类型
                    val actualTypeArgument = (genericInterfaces[0] as ParameterizedType).actualTypeArguments[0]
                    val schema = getSchemaByType(actualTypeArgument, property)

                    // 设置枚举的值和描述
                    schema.enum = this.getValues(fieldClazz)
                    val description = this.getDescription(fieldClazz)
                    schema.description = if (ObjectUtils.isEmpty(property.description)) description else "${property.description} ($description)"

                    return schema
                }
            }
        }
        return property
    }
}

在这里插入图片描述

在这里插入图片描述

1 Spring基本特征 6 2 Spring的组成 6 2.1 Spring的jar包 6 2.2 Spring配置文件 7 2.3 Spring API 8 3 Spring基本功能详解 8 3.1 SpringIOC 8 3.2别名Alias 11 别名拓展: 11 3.3 Spring容器内部对象的创建 12 Spring容器内部对象创建拓展: 12 3.3.1使用类构造器实例化(默认无参数) 14 3.3.2使用静态工厂方法实例化(简单工厂模式) 14 3.3.3初始化(创建)bean时机 15 Lazy-init初始化bean的时机拓展: 15 3.4 Bean的作用域 16 Scope单例多例作用域拓展: 16 3.4.1 singleton(默认) 16 3.4.2 prototype 17 3.4.3 Request 17 3.4.4 Session 18 3.4.5 Global session 18 3.4.6 指定Bean的初始化方法和销毁方法 18 Bean的初始化和销毁拓展: 18 Spring的IOC总结: 20 3.5 依赖注入(DI) 20 3.5.1 使用构造器注入 20 3.5.2 使用属性setting方法进行注入 21 3.5.3 装配list集合 22 3.5.4 装配set集合 22 3.5.5 装配map 22 3.5.6 装配Properties 23 3.6 注解注入 23 注解注入拓展: 23 3.6.1 @Autowired 26 3.6.2 @Qualifier 27 3.6.3 @Resource 27 3.6.4 @PostConstruct 28 3.6.5 @PreDestroy 28 注解注入拓展: 28 3.7扫描注入 30 注解扫描拓展: 32 Mvc用注解写: 34 Spring容器IOC和di的整个启动过程: 38 3.8 spring中的继承 38 拓展spring为类中的属性赋: 40 小结: 47 面向接口编程: 47 4 面向切面编程 52 4.1 代理模式 52 代理模式拓展: 52 4.1.1 JDK动态代理 58 JDK动态代理拓展: 59 4.1.2 CGLIB做代理 66 CGLIB动态代理拓展: 68 4.1.3 Spring的动态代理 71 4.2 AOP编程 71 4.2.1概念: 71 SpringAOP概念拓展: 73 之前实现了目标方法的动态调用,现在来实现切面的动态调用。 74 4.2.2 AOP实现的两种模式 78 4.2.2.1 xml形式 78 XML形式拓展: 81 异常通知处理例子: 91 不用spring异常通知,另一种处理异常 96 4.2.2.2Aop注解形式(了解) 99 注解注入拓展: 103 5 Spring数据库 106 5.1 Spring+JDBC 106 5.1.1 Jdbc编程特点 106 5.1.2引入DataSource 106 5.1.3 核心类JdbcTemplate 106 5.1.4 使用JdbcTemplate 106 5.1.5 继承JdbcDaoSupport 107 5.1.6 使用properties文件 107 5.1.7 RowMapper的使用 107 拓展: 108 DataSource注入的三种方式: 108 5.1.8声明式事务管理 116 5.1.8.1Spring的事务管理器 117 5.1.8.2Spring事务的传播属性 117 5.1.8.3Spring事务的隔离级别 117 拓展: 118 5.1.8.4以XML配置的 形式 119 拓展: 120 5.1.8.5以注解方式配置 125 拓展: 127 5.1.9使用CGLIB以XML形式配置事务 130 5.2 Spring+Hibernate 131 5.2.1 HibernateTemplate模板 131 5.2.2 声明式事务 131 配置XML文件 131 拓展: 132 注解形式: 137 拓展: 138 6 Struts2+spring+hibernate 141 6.1 需要添加的jar包 141 6.2 Spring融合web服务器 141 6.3 struts.xml文件 143 6.4 OpenInSessionView 143 拓展: 144 实例: 146
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值