跳转至

SpringDoc

关于泛型

  • 泛型类不要加title,加description即可,不然所有泛型参数的name为同一个,保持自动生成title即可

关于Query

  • OpenAPI的查询参数即便作为一个对象,也不会unwrap,参数名还是变量名,只不过引用了一个对象
    • apifox仅支持从这个对象属性的description获取名称,而不是title
  • Flat Param Object:扁平化参数对象,支持解析对象的属性做为QueryString的参数schema,即 不会额外生成参数名且引用一个对象,而是直接unwrap
    • 全局开启:springdoc.default-flat-param-object
      • 需要注意被忽视的情况,如@RequestBody、请求响应等对象
      • 如果需要添加忽视类,根据DelegatingMethodParameter\#customize,可以调用AbstractRequestService\#addRequestWrapperToIgnore
    • 部分开启:@ParameterObject,推荐
      • 注意
      • 根据DelegatingMethodParameter\#customize@ParameterObject是调用MethodParameter#hasParameterAnnotation,因此不是用AnnotatedElementUtils,但是对参数类用AnnotatedElementUtils,因此如果要用AnnotatedElementUtils机制,就注解在类上

自定义

ParameterCustomizer:自定义参数

public class EnumParameterCustomizer implements ParameterCustomizer {  
  @Override  
  public Parameter customize(Parameter parameterModel, MethodParameter methodParameter) {  
    ParameterEnum parameterEnum = methodParameter.getParameterAnnotation(ParameterEnum.class);  
    if (parameterEnum == null || !Enum.class.isAssignableFrom(parameterEnum.value())) {  
      return parameterModel;  
    }  
    if(  
        //  
        !methodParameter.hasParameterAnnotation(io.swagger.v3.oas.annotations.Parameter .class)  
        /**  
         * 配合自定义的ModelConverter,可以不理会是否是schemaProperty,但是PropertyCustomizer则不行,  
         * 其Springdoc机制的PropertyCustomizingConverter则会检查。  
         * 因为各使用各的比较好(Parameter自己解析,Property自己解析),因此这里添加这个条件  
         * (当然也可以直接setEnumDoc然后拼接description,其他情况就不要了)  
         */  
     || StringUtils.isBlank(parameterModel.getSchema().getDescription())  
    ){  
      ParameterEnumModelConverter.setEnumDoc(parameterModel.getSchema(), parameterEnum, (desc)->{  
        if(StringUtils.isBlank(parameterModel.getDescription())  
            || StringUtils.equals(parameterModel.getDescription(), parameterModel.getSchema().getDescription())){  
          parameterModel.setDescription(desc);  
        }else{  
          parameterModel.setDescription(parameterModel.getDescription() + ", " + desc);  
        }  
      });  
      return parameterModel;  
    }  
    /**  
     * Parameter的schema为空(不是用schema注解,没有设置schema属性)时,在AbstractRequestService\#build中  
     * 调用AbstractRequestService\#buildParams才会解析schema,  
     * 从而使用ParameterEnumModelConverter构建枚举描述和值(此时就不需要重复构建枚举信息了)。  
     * 另外:使用 @Parameter 才正确设置了类型,否则都是string(或者手动指定了schema的类型声明)  
     */  
    parameterModel.setDescription(StringUtils.isBlank(parameterModel.getDescription()) ?  
        parameterModel.getSchema().getDescription()  
        : parameterModel.getDescription() + ", " + parameterModel.getSchema().getDescription());  
    return parameterModel;  
  }  
}

PropertyCustomizer 自定义schema属性

  • 仅仅只是被 PropertyCustomizingConverter 使用,和自己自定义ModelConverter是一样的
  • ModelConverter添加方法:ModelConverters.getInstance() 或者 一个bean

ReturnTypeParser

  • 自定义返回类型的解析
    /**  
     * 解构目标类型,如 Flux<ServerSentEvent<Data>>, noWrapClassList包含Flux、ServerSentEvent,就解构为Data  
     */public class UnWrapReturnTypeParser implements ReturnTypeParser {  
      private final List<Class> noWrapClassList;  
    
      public UnWrapReturnTypeParser(List<Class> noWrapClassList) {  
        this.noWrapClassList = noWrapClassList;  
      }  
    
      @Override  
      public Type getReturnType(MethodParameter methodParameter) {  
        Type genericParameterType = methodParameter.getGenericParameterType();  
        if (genericParameterType instanceof ParameterizedType){  
          Type targetType = genericParameterType;  
          while (true){  
            Class<?> rowType =(Class<?>) ((ParameterizedType) targetType).getRawType();  
            if(noWrapClassList.stream().noneMatch(e-> e.isAssignableFrom(rowType))){  
              break;  
            }  
            targetType = ((ParameterizedType) targetType).getActualTypeArguments()[0];  
          }  
          return ReturnTypeParser.resolveType(targetType, methodParameter.getContainingClass());  
        }  
        return methodParameter.getParameterType();  
      }  
    }