SwaggerDisplayConfig.java 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. package com.persagy.fm.common.config;
  2. import com.fasterxml.classmate.ResolvedType;
  3. import com.google.common.base.Optional;
  4. import com.persagy.fm.common.model.annotation.SwaggerDisplayEnum;
  5. import io.swagger.annotations.ApiModelProperty;
  6. import lombok.extern.slf4j.Slf4j;
  7. import org.apache.commons.lang3.StringUtils;
  8. import org.springframework.context.annotation.Primary;
  9. import org.springframework.core.annotation.AnnotationUtils;
  10. import org.springframework.stereotype.Component;
  11. import org.springframework.util.ReflectionUtils;
  12. import springfox.documentation.builders.ModelPropertyBuilder;
  13. import springfox.documentation.schema.Annotations;
  14. import springfox.documentation.spi.DocumentationType;
  15. import springfox.documentation.spi.schema.ModelPropertyBuilderPlugin;
  16. import springfox.documentation.spi.schema.contexts.ModelPropertyContext;
  17. import springfox.documentation.swagger.schema.ApiModelProperties;
  18. import java.lang.reflect.Field;
  19. import java.util.Arrays;
  20. import java.util.List;
  21. import java.util.Objects;
  22. import java.util.stream.Collectors;
  23. /**
  24. * 类说明
  25. *
  26. * @author lixing
  27. * @version V1.0 2021/4/12 10:43 上午
  28. **/
  29. @Component
  30. @Primary
  31. @Slf4j
  32. public class SwaggerDisplayConfig implements ModelPropertyBuilderPlugin {
  33. @Override
  34. public void apply(ModelPropertyContext context) {
  35. //获取当前字段的类型
  36. final Class fieldType = context.getBeanPropertyDefinition().get().getField().getRawType();
  37. //为枚举字段设置注释
  38. descForEnumFields(context, fieldType);
  39. }
  40. /**
  41. * 为枚举字段设置注释
  42. */
  43. private void descForEnumFields(ModelPropertyContext context, Class fieldType) {
  44. Optional<ApiModelProperty> annotation = Optional.absent();
  45. if (context.getAnnotatedElement().isPresent()) {
  46. annotation = annotation
  47. .or(ApiModelProperties.findApiModePropertyAnnotation(context.getAnnotatedElement().get()));
  48. }
  49. if (context.getBeanPropertyDefinition().isPresent()) {
  50. annotation = annotation.or(Annotations.findPropertyAnnotation(
  51. context.getBeanPropertyDefinition().get(),
  52. ApiModelProperty.class));
  53. }
  54. //没有@ApiModelProperty 或者 notes 属性没有值,直接返回
  55. if (!annotation.isPresent() || StringUtils.isBlank((annotation.get()).notes())) {
  56. return;
  57. }
  58. //@ApiModelProperties中的notes指定的class类型
  59. Class rawPrimaryType;
  60. try {
  61. rawPrimaryType = Class.forName((annotation.get()).notes());
  62. } catch (ClassNotFoundException e) {
  63. //如果指定的类型无法转化,直接忽略
  64. return;
  65. }
  66. //如果对应的class是一个@SwaggerDisplayEnum修饰的枚举类,获取其中的枚举值
  67. Object[] subItemRecords = null;
  68. SwaggerDisplayEnum swaggerDisplayEnum = AnnotationUtils
  69. .findAnnotation(rawPrimaryType, SwaggerDisplayEnum.class);
  70. if (null != swaggerDisplayEnum && Enum.class.isAssignableFrom(rawPrimaryType)) {
  71. subItemRecords = rawPrimaryType.getEnumConstants();
  72. }
  73. if (null == subItemRecords) {
  74. return;
  75. }
  76. final List<String> displayValues = Arrays.stream(subItemRecords).filter(Objects::nonNull).map(item -> {
  77. String typeName = swaggerDisplayEnum.type();
  78. String descName = swaggerDisplayEnum.desc();
  79. Object type = null;
  80. Object desc = null;
  81. Field typeField = ReflectionUtils.findField(item.getClass(), typeName);
  82. if (typeField != null) {
  83. ReflectionUtils.makeAccessible(typeField);
  84. type = ReflectionUtils.getField(typeField, item);
  85. }
  86. Field descField = ReflectionUtils.findField(item.getClass(), descName);
  87. if (descField != null) {
  88. ReflectionUtils.makeAccessible(descField);
  89. desc = ReflectionUtils.getField(descField, item);
  90. }
  91. type = type == null ? "" : type;
  92. desc = desc == null ? "" : desc;
  93. return type + ":" + desc;
  94. }).filter(Objects::nonNull).collect(Collectors.toList());
  95. String joinText = " (" + String.join("; ", displayValues) + ")";
  96. try {
  97. Field mField = ModelPropertyBuilder.class.getDeclaredField("description");
  98. mField.setAccessible(true);
  99. joinText = mField.get(context.getBuilder()) + joinText;
  100. } catch (Exception e) {
  101. log.error(e.getMessage());
  102. }
  103. final ResolvedType resolvedType = context.getResolver().resolve(fieldType);
  104. context.getBuilder().description(joinText).type(resolvedType);
  105. }
  106. @Override
  107. public boolean supports(DocumentationType documentationType) {
  108. return true;
  109. }
  110. }