swagger 怎么显示enum_swagger 动态显示枚举内容 + 数值类型空指针异常统一控制

本文介绍了如何在Swagger中动态显示枚举内容,并解决Integer、Boolean字段的空指针异常问题。通过自定义拦截方法,设置枚举字段的description,并为数值类型字段设置默认example。
摘要由CSDN通过智能技术生成

遇到的问题:

当我们定义接口的入参或者返回值的字段想把他关联的枚举内容显示到swagger的页面上方便前端同学查看,但是又不想在每次修改枚举值的时候去手动修改description,如果不去手动修改又会遇到前后端掌握的枚举值不一致的情况

定义的接口参数Integer、Boolean 字段的时候,如果不去设置该值的example的时候,获取swagger页面的时候,会提示nullpointException

解决方法:

问题1:拦截生成swagger doc的过程,在这个过程判断字段是否是枚举字段,遍历完后设置到description中

问题2:拦截生成swagger doc过程,如果是数值字段或者Boolean,设置默认的example

show 代码

定义拦截方法,对数值和枚举做替换

import com.fasterxml.classmate.ResolvedType;

import com.google.common.base.Optional;

import io.swagger.annotations.ApiModelProperty;

import java.lang.reflect.Field;

import java.util.Arrays;

import java.util.List;

import java.util.Objects;

import java.util.stream.Collectors;

import lombok.extern.slf4j.Slf4j;

import org.apache.commons.lang3.StringUtils;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.context.annotation.Primary;

import org.springframework.core.annotation.AnnotationUtils;

import org.springframework.stereotype.Component;

import springfox.documentation.builders.ModelPropertyBuilder;

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.swagger.schema.ApiModelProperties;

/**

* 对swagger展示进行修改 1. 数字、Boolean属性设置默认的example 2. 支持将枚举变量的描述按照枚举类定义展示

*

* @see SwaggerDisplayEnum

* @see ApiModelProperty

*/

@Component

@Primary

@Slf4j

public class SwaggerDisplayConfig implements ModelPropertyBuilderPlugin {

/**

* 是否允许swagger

*/

@Value("${swagger.enable:false}")

private Boolean enableSwagger;

@Override

public void apply(ModelPropertyContext context) {

//如果不支持swagger的话,直接返回

if (!enableSwagger) {

return;

}

//获取当前字段的类型

final Class fieldType = context.getBeanPropertyDefinition().get().getField().getRawType();

//设置对数字的字段设置默认的example

setDefaultExample(context, fieldType);

//为枚举字段设置注释

descForEnumFields(context, fieldType);

}

/**

* 为枚举字段设置注释

*/

private void descForEnumFields(ModelPropertyContext context, Class fieldType) {

Optional annotation = Optional.absent();

if (context.getAnnotatedElement().isPresent()) {

annotation = annotation

.or(ApiModelProperties.findApiModePropertyAnnotation(context.getAnnotatedElement().get()));

}

if (context.getBeanPropertyDefinition().isPresent()) {

annotation = annotation.or(Annotations.findPropertyAnnotation(

context.getBeanPropertyDefinition().get(),

ApiModelProperty.class));

}

//没有@ApiModelProperty 或者 notes 属性没有值,直接返回

if (!annotation.isPresent() || StringUtils.isBlank((annotation.get()).notes())) {

return;

}

//@ApiModelProperties中的notes指定的class类型

Class rawPrimaryType;

try {

rawPrimaryType = Class.forName((annotation.get()).notes());

} catch (ClassNotFoundException e) {

//如果指定的类型无法转化,直接忽略

return;

}

//如果对应的class是一个@SwaggerDisplayEnum修饰的枚举类,获取其中的枚举值

Object[] subItemRecords = null;

SwaggerDisplayEnum swaggerDisplayEnum = AnnotationUtils

.findAnnotation(rawPrimaryType, SwaggerDisplayEnum.class);

if (null != swaggerDisplayEnum && Enum.class.isAssignableFrom(rawPrimaryType)) {

subItemRecords = rawPrimaryType.getEnumConstants();

}

if (null == subItemRecords) {

return;

}

//从annotation中获取对应的值和描述的变量名

String valueName = swaggerDisplayEnum.valueName();

String descName = swaggerDisplayEnum.descName();

if (StringUtils.isBlank(valueName) || StringUtils.isBlank(descName)) {

return;

}

final List displayValues = Arrays.stream(subItemRecords).filter(Objects::nonNull).map(item -> {

Class currentClass = item.getClass();

String value;

String desc;

try {

Field valueField = currentClass.getField(valueName);

Field descField = currentClass.getField(descName);

valueField.setAccessible(true);

descField.setAccessible(true);

value = valueField.get(item).toString();

desc = descField.get(item).toString();

} catch (NoSuchFieldException | IllegalAccessException e) {

log.warn("获取枚举的属性和值失败, {}", e.getMessage());

return null;

}

return value + ":" + desc;

}).filter(Objects::nonNull).collect(Collectors.toList());

String joinText = " (" + String.join("; ", displayValues) + ")";

try {

Field mField = ModelPropertyBuilder.class.getDeclaredField("description");

mField.setAccessible(true);

joinText = mField.get(context.getBuilder()) + joinText;

} catch (Exception e) {

log.error(e.getMessage());

}

final ResolvedType resolvedType = context.getResolver().resolve(fieldType);

context.getBuilder().description(joinText).type(resolvedType);

}

/**

* 设置默认的example

*/

private void setDefaultExample(ModelPropertyContext context, Class fieldType) {

if (Number.class.isAssignableFrom(fieldType)) {

context.getBuilder().example("1");

}

if (Boolean.class.isAssignableFrom(fieldType)) {

context.getBuilder().example("true");

}

}

@Override

public boolean supports(DocumentationType documentationType) {

return true;

}

}

复制代码定义用来判断是否需要显示枚举到swagger上的annotation

/**

* 需要swagger展示的枚举

* 默认 支持 枚举中属性名为 value和desc

* 如果不是,请设置valueName和descName

*

*/

@Target({ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

public @interface SwaggerDisplayEnum {

String valueName() default "value";

String descName() default "desc";

}

复制代码在定义出入参bean的时候,在想要显示枚举详情的字段上@ApiModelProperties属性中指定该字段对应的枚举类

@Data

@ApiModel("返回值bean")

public class ResultBean {

....

/**

* 枚举字段

*/

@ApiModelProperty(value = "需要显示的枚举值", notes = "com.li.test.enums.AAEnum")

private Integer aa;

...

}

复制代码

完成上面的操作,aa对应的枚举类AAEnum的值和意思都能在swagger字段的description中显示出来了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值