先看效果
1.自定义注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @description: swagger 属性绑定 枚举对象注解
* @author guyi
* @date 2023/11/24 9:53
**/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiModelPropertyEnum {
Class value();
}
2.实现Swagger 的 ModelPropertyBuilderPlugin 接口
import com.fasterxml.classmate.ResolvedType;
import com.fasterxml.classmate.TypeResolver;
import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
import io.swagger.annotations.ApiModelProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import springfox.documentation.schema.Annotations;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.schema.ModelPropertyBuilderPlugin;
import springfox.documentation.spi.schema.contexts.ModelPropertyContext;
import springfox.documentation.spring.web.DescriptionResolver;
import springfox.documentation.swagger.common.SwaggerPluginSupport;
import springfox.documentation.swagger.schema.ApiModelProperties;
import java.lang.reflect.*;
import java.util.Map;
import java.util.Optional;
/**
* @Description: 自定义 Swagger 属性绑定
* @Author: guyi
* @Date: 2023-11-24 09:58
**/
@Component
@Order(-2147482648)
public class MyModelPropertyBuilderPlugin implements ModelPropertyBuilderPlugin {
private final DescriptionResolver descriptions;
@Autowired
public MyModelPropertyBuilderPlugin(DescriptionResolver descriptions) {
this.descriptions = descriptions;
}
@Override
public void apply(ModelPropertyContext context) {
Optional<ApiModelProperty> annotation = Optional.empty();
if (context.getAnnotatedElement().isPresent()) {
annotation = (Optional) annotation.map(Optional::of).orElse(ApiModelProperties.findApiModePropertyAnnotation((AnnotatedElement) context.getAnnotatedElement().get()));
}
if (context.getBeanPropertyDefinition().isPresent()) {
annotation = (Optional) annotation.map(Optional::of).orElse(Annotations.findPropertyAnnotation((BeanPropertyDefinition) context.getBeanPropertyDefinition().get(), ApiModelProperty.class));
}
if (annotation.isPresent()) {
ApiModelProperty apiModelProperty = annotation.get();
ApiModelPropertyEnum apiModelPropertyEnum = context.getBeanPropertyDefinition().get().getField().getAnnotation(ApiModelPropertyEnum.class);
try {
StringBuilder stringBuilder = null;
if (apiModelPropertyEnum != null && !apiModelProperty.value().contains("(")) {
InvocationHandler invocationHandler = Proxy.getInvocationHandler(apiModelProperty);
Field memberValues = invocationHandler.getClass().getDeclaredField("memberValues");
memberValues.setAccessible(true);
Map o = (Map) memberValues.get(invocationHandler);
Class<?> aClass = apiModelPropertyEnum.value();
Object[] enumConstants = aClass.getEnumConstants();
stringBuilder = new StringBuilder();
stringBuilder.append(apiModelProperty.value());
stringBuilder.append("(");
for (Object enumConstant : enumConstants) {
Method[] declaredMethods = aClass.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
String name = declaredMethod.getName();
if (name.equals("values") || name.equals("valueOf")) {
continue;
}
stringBuilder.append(declaredMethod.invoke(enumConstant));
stringBuilder.append(":");
}
stringBuilder.delete(stringBuilder.length() - 1, stringBuilder.length());
stringBuilder.append(",");
}
stringBuilder.delete(stringBuilder.length() - 1, stringBuilder.length());
stringBuilder.append(")");
o.put("value", stringBuilder.toString());
}
context.getBuilder()
.allowableValues(apiModelProperty.allowableValues() == null ? null : ApiModelProperties.allowableValueFromString(apiModelProperty.allowableValues()))
.required(apiModelProperty.required())
.readOnly(apiModelProperty.readOnly())
.description(stringBuilder == null ? null : stringBuilder.toString())
.isHidden(apiModelProperty.hidden())
.type(resolve(context.getResolver(), apiModelProperty))
.position(apiModelProperty.position());
} catch (Exception e) {
e.printStackTrace();
}
}
}
public ResolvedType resolve(TypeResolver resolver, ApiModelProperty apiModelProperty) {
try {
return resolver.resolve(Class.forName(apiModelProperty.dataType()), new Type[0]);
} catch (ClassNotFoundException e) {
return resolver.resolve(Object.class, new Type[0]);
}
}
@Override
public boolean supports(DocumentationType delimiter) {
return SwaggerPluginSupport.pluginDoesApply(delimiter);
}
}
3.定义枚举对象
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @Description: 通用枚举类,把所有枚举类都写到一起
* @Author: guyi
* @Date: 2023-11-24 14:00
**/
public final class ComEnum {
/**
* 通用字典表-是否(0-否,1-是)
*/
@Getter
@AllArgsConstructor
public enum YESORNO {
NO("0","否"),
YES("1","是");
private final String value;
private final String label;
}
/**
* 荣誉获奖表--获奖级别(1-国家级、2-省级、3-市级、4-区级、5-校级)
*/
@Getter
@AllArgsConstructor
public enum AwardsHistoryLevel {
NATION("1","国家级"),
// PROVINCE("2","省级"),
CITY("3","市级"),
AREA("4","区级"),
SCHOOL("5","校级");
private final String value;
private final String label;
}
}
4.注解使用
/**获奖级别*/
@ApiModelProperty(value = "获奖级别")
@ApiModelPropertyEnum(value = ComEnum.AwardsHistoryLevel.class)
private String level;