创建 SwaggerEnum 注解
用于标识枚举类
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface SwaggerEnum {
String VALUE = "value";
String DESC = "desc";
/**
* @return 枚举的含义
*/
String value();
/**
* @return 数据库实际对应的类型
*/
Class type() default Integer.class;
/**
* @return 数据库实际对应的类型
*/
String modelRef() default "int";
/**
* @return 枚举实际使用的字段
*/
String valueName() default VALUE;
/**
* @return 枚举中用于描述的字段
*/
String descName() default DESC;
}
创建处理枚举的工具类
@Component
public class EnumCommon {
/**
* 获取 {@link SwaggerEnum}
*
* @param enumClass 枚举类
* @return {@link SwaggerEnum}
*/
public SwaggerEnum getSwaggerEnum(Class enumClass) {
if (enumClass == null || !Enum.class.isAssignableFrom(enumClass)) {
return null;
}
return AnnotationUtils.findAnnotation(enumClass, SwaggerEnum.class);
}
/**
* 生成 desc
*
* @param enumClass 枚举类
* @param swaggerEnum {@link SwaggerEnum}
* @return desc
*/
public String getDesc(Class enumClass, SwaggerEnum swaggerEnum) {
if (swaggerEnum == null) {
return null;
}
// 获取枚举对应的值
Object[] enumConstants = enumClass.getEnumConstants();
if (ArrayUtils.isEmpty(enumConstants)) {
return null;
}
// 将枚举的值转成字符串
return Arrays.stream(enumConstants)
.filter(Objects::nonNull)
.map(item -> {
try {
Reflect enumReflect = Reflect.on(item);
Object value = enumReflect.get(swaggerEnum.valueName());
Object desc = enumReflect.get(swaggerEnum.descName());
return StrUtil.format("{} : {}", value, desc);
} catch (Exception e) {
return null;
}
}).filter(Objects::nonNull)
.collect(Collectors.joining(",", swaggerEnum.value() + " ", ""));
}
}
Reflect 使用的 joor
StrUtil 使用的 hutool
创建 ExpandedParameterBuilderPlugin
用于处理 query 传参中的枚举
@Component
public class EnumExpandedParameterBuilderPlugin implements ExpandedParameterBuilderPlugin {
private final EnumCommon enumCommon;
private final TypeResolver resolver;
public EnumExpandedParameterBuilderPlugin(EnumCommon enumCommon, TypeResolver resolver) {
this.enumCommon = enumCommon;
this.resolver = resolver;
}
@Override
public void apply(ParameterExpansionContext context) {
Class<?> erasedType = context.getFieldType().getErasedType();
SwaggerEnum swaggerEnum = enumCommon.getSwaggerEnum(erasedType);
String desc = enumCommon.getDesc(erasedType, swaggerEnum);
if (desc != null) {
Reflect parameterBuilderReflect = Reflect.on(context.getParameterBuilder());
// 将 allowableValues 设置成 null
// context.getParameterBuilder().allowableValues() 并不能设置 null,只能反射
parameterBuilderReflect.set("allowableValues", null);
context.getParameterBuilder()
.allowMultiple(false)
.modelRef(new ModelRef(swaggerEnum.modelRef()))
.description(desc)
.type(resolver.resolve(swaggerEnum.type()));
}
}
@Override
public boolean supports(DocumentationType delimiter) {
return true;
}
}
创建 ModelPropertyBuilderPlugin
用于处理 request body 对应的类以及接口的返回值的类
@Component
public class EnumModelPropertyBuilderPlugin implements ModelPropertyBuilderPlugin {
private final EnumCommon enumCommon;
public EnumModelPropertyBuilderPlugin(EnumCommon enumCommon) {
this.enumCommon = enumCommon;
}
@Override
public void apply(ModelPropertyContext context) {
if (context.getBeanPropertyDefinition().isPresent()) {
Class<?> rawPrimaryType = context.getBeanPropertyDefinition().get().getRawPrimaryType();
SwaggerEnum swaggerEnum = enumCommon.getSwaggerEnum(rawPrimaryType);
String desc = enumCommon.getDesc(rawPrimaryType, swaggerEnum);
if (desc != null) {
// 修改描述和类型
ResolvedType type = context.getResolver().resolve(swaggerEnum.type());
context.getBuilder().description(desc).type(type);
}
}
}
@Override
public boolean supports(DocumentationType documentationType) {
return true;
}
}
示例
@SwaggerEnum("性别")
public enum GenderEnum {
/**
* 枚举值
*/
MAN(1, "男"),
WOMAN(2, "女");
@Getter
private int value;
@Getter
private String desc;
GenderEnum(int value, String desc) {
this.value = value;
this.desc = desc;
}
}
最后生成的 description :性别 1 : 男,2 : 女
写的不好,仅供参考