一、背景与问题
经常后端会返回给前端一个枚举定义,比如性别:gender
java
gender = 1;// 表示男性
gender = 2;// 表示女性
在给javabean添加swagger @ApiModelProperty
注解的时候,就需要额外说明,每个值代表的是什么含义,如下:
java
public class PersonVO {
@ApiModelProperty("性别: 1男,2女")
private Integer gender;
}
这样一旦再多加一种性别:gender = 3;// 表示中性
,你就需要找到所有地方,都改下,但凡漏掉一个地方,就可能导致前端的对应不上,这种隐藏的Bug是十分危险的。
二、解决方案
2.1、BaseEnum接口
java
public interface BaseEnum {
/**
* 获取枚举类的值
*/
Object getValue();
/**
* 获取枚举类的说明
*/
String getDesc();
比如商品状态类的枚举变量:
java
@AllArgsConstructor
@Getter
public enum GoodsStatusEnum implements BaseEnum {
APPOINTMENT(1, "预约中"),
SELL(2, "售卖中"),
SELL_OUT(3, "售罄");
private final Integer value;
private final String desc;
}
2.2、枚举注解
我们定义了一个枚举注解:@ApiModelPropertyEnum
,在javabean中枚举字段添加
java
@Data
public class GoodsVO {
@ApiModelProperty("商品名称")
private String goodsName;
@ApiModelPropertyEnum(GoodsStatusEnum.class)
private Integer goodsStatus;
2.3、效果
swagger效果如下:
你会发现这不是前端代码吗?为什么要这样?
2.4、前端vue-enum配合
因为swagger文档多用于前端,后端人员较少,前端使用的枚举维护是:vue-enum
所以直接用Java代码生成了前端代码,这样前端人员直接copy走就可以了。
关爱前端,节省时间
当然如果前端是app端的话,想修改返回结果,可以直接修改BaseEnum.getInfo()
方法
三、实现原理
@ApiModelPropertyEnum
注解
我们自己实现了一个swagger插件ModelPropertyBuilderPlugin
插件:SwaggerApiModelPropertyEnumPlugin
,在插件中使用@ApiModelPropertyEnum
注解,这样在swagger文档中就可以很好的显示了
java
@Component
@Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1)
public class SwaggerApiModelPropertyEnumPlugin implements ModelPropertyBuilderPlugin {
@Override
public void apply(ModelPropertyContext context) {
Optional<ApiModelPropertyEnum> annotation = Optional.absent();
if (context.getAnnotatedElement().isPresent()) {
annotation = annotation.or(findApiModePropertyAnnotation(context.getAnnotatedElement().get()));
}
if (context.getBeanPropertyDefinition().isPresent()) {
annotation = annotation.or(findPropertyAnnotation(context.getBeanPropertyDefinition().get(), ApiModelPropertyEnum.class));
}
if (annotation.isPresent()) {
ApiModelPropertyEnum anEnum = annotation.get();
String enumInfo = BaseEnum.getInfo(anEnum.value());
context.getBuilder()
.required(annotation.transform(toIsRequired()).or(false))
.description(anEnum.desc() + ":" + enumInfo)
.example(annotation.transform(toExample()).orNull())
.isHidden(anEnum.hidden());
}
}
@Override
public boolean supports(DocumentationType delimiter) {
return SwaggerPluginSupport.pluginDoesApply(delimiter);
}
static Function<ApiModelPropertyEnum, Boolean> toIsRequired() {
return annotation -> annotation.required();
}
public static Optional<ApiModelPropertyEnum> findApiModePropertyAnnotation(AnnotatedElement annotated) {
return Optional.fromNullable(AnnotationUtils.getAnnotation(annotated, ApiModelPropertyEnum.class));
}
static Function<ApiModelPropertyEnum, String> toExample() {
return annotation -> {
String example = annotation.example();
if (StringUtils.isBlank(example)) {
return "";
}
return example;
};
}
}
outline: 'deep'
联系我们
1024创新实验室-主任:卓大,混迹于各个技术圈,研究过计算机,熟悉点 java,略懂点前端。
1024创新实验室(河南·洛阳) 致力于成为中原领先、国内一流的技术团队,以技术创新为驱动,合作各类项目(软件外包、技术顾问、培训等等)。
加微信: 卓大 拉你入群,一起学习 | 公众号 :六边形工程师 分享:赚钱、代码、生活 | 请 “1024创新实验室” “烩面里加肉” “ 咖啡配胡辣汤,提神又饱腹” | 抖音 : 六边形工程师 直播:赚钱、代码、中医 |