Skip to content

一、背景与问题

经常后端会返回给前端一个枚举定义,比如性别: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创新实验室”
“烩面里加肉”
“ 咖啡配胡辣汤,提神又饱腹”
抖音 : 六边形工程师
直播:赚钱、代码、中医