关于java:引Swagger2-关于JSONObject参数在API文档中展示详细参数以及参数说明

4次阅读

共计 30747 个字符,预计需要花费 77 分钟才能阅读完成。

引言

原文出处 Swagger2 对于 JSONObject 参数在 API 文档中展现具体参数以及参数阐明
相似的 Swagger2 对于 Map 参数在 API 文档中展现具体参数以及参数阐明
原理就不再做阐明,读者能够查看该文章即可。作者稍作了些扭转,也是花了很多工夫整顿,接下来咱们只负责搬砖就好,话不多说间接看代码。

代码实现

自定义注解类 ApiJsonObject2

package com.mybatis.plus.swagger;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * @Author wulongbo
 * @Date 2020/9/14 17:20
 * @Version 1.0
 */
@Target({ElementType.PARAMETER, ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiJsonObject2 {ApiJsonProperty2[] value(); // 对象属性值
 ApiJsonResult result() default @ApiJsonResult({});
 String name() default "";}

自定义注解类ApiJsonProperty2

package com.mybatis.plus.swagger;
import io.swagger.annotations.Example;
import io.swagger.annotations.ExampleProperty;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * @Author wulongbo
 * @Date 2020/9/14 17:23
 * @Version 1.0
 */
@Target(ElementType.ANNOTATION_TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiJsonProperty2 {String name();
 String defaultValue() default "";
 String description() default "";
 String allowableValues() default "";
 boolean required() default false;
 String access() default "";
 boolean allowMultiple() default false;
 Class<?> type() default String.class ;
 String paramType() default "";
 String example() default "";
 Example examples() default @Example(value = @ExampleProperty(mediaType = "", value =""));
 String format() default "";
 boolean readOnly() default false;
 String collectionFormat() default "";}

自定义注解类 ApiJsonResult

package com.mybatis.plus.swagger;
/**
 * Created by yueh on 2018/9/7.
 */
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.ANNOTATION_TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiJsonResult {String[] value();
 String name() default "";
 String type() default CommonData.RESULT_TYPE_NORMAL_FINAL;}

ApiListingJsonScanner

package com.mybatis.plus.swagger;
/**
 * Created by yueh on 2018/9/12. */
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
import com.google.common.base.*;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.Iterables;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.Multimap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import springfox.documentation.PathProvider;
import springfox.documentation.builders.ApiListingBuilder;
import springfox.documentation.schema.Model;
import springfox.documentation.service.*;
import springfox.documentation.spi.service.contexts.ApiListingContext;
import springfox.documentation.spi.service.contexts.DocumentationContext;
import springfox.documentation.spi.service.contexts.RequestMappingContext;
import springfox.documentation.spring.web.paths.PathMappingAdjuster;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.spring.web.plugins.DocumentationPluginsManager;
import springfox.documentation.spring.web.scanners.ApiDescriptionReader;
import springfox.documentation.spring.web.scanners.ApiListingScanner;
import springfox.documentation.spring.web.scanners.ApiListingScanningContext;
import springfox.documentation.spring.web.scanners.ApiModelReader;
import java.util.*;
import static com.google.common.base.Predicates.and;
import static com.google.common.collect.FluentIterable.from;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Sets.newHashSet;
import static java.util.stream.Collectors.toList;
import static springfox.documentation.builders.BuilderDefaults.nullToEmptyList;
import static springfox.documentation.spi.service.contexts.Orderings.methodComparator;
import static springfox.documentation.spi.service.contexts.Orderings.resourceGroupComparator;
@Component
@Primary
public class ApiListingJsonScanner extends ApiListingScanner {
    private final ApiDescriptionReader apiDescriptionReader;
 private final ApiModelReader apiModelReader;
 private final DocumentationPluginsManager pluginsManager;
 public static final String ROOT = "/";
 @Autowired
 public ApiListingJsonScanner(
            ApiDescriptionReader apiDescriptionReader,
 ApiModelReader apiModelReader,
 DocumentationPluginsManager pluginsManager) {super(apiDescriptionReader,apiModelReader,pluginsManager);
 this.apiDescriptionReader = apiDescriptionReader;
 this.apiModelReader = apiModelReader;
 this.pluginsManager = pluginsManager;
 }
    static Optional<String> longestCommonPath(List<ApiDescription> apiDescriptions) {List<String> commons = newArrayList();
 if (null == apiDescriptions || apiDescriptions.isEmpty()) {return Optional.absent();
 }
        List<String> firstWords = urlParts(apiDescriptions.get(0));
 for (int position = 0; position < firstWords.size(); position++) {String word = firstWords.get(position);
 boolean allContain = true;
 for (int i = 1; i < apiDescriptions.size(); i++) {List<String> words = urlParts(apiDescriptions.get(i));
 if (words.size() < position + 1 || !words.get(position).equals(word)) {
                    allContain = false;
 break; }
            }
            if (allContain) {commons.add(word);
 }
        }
        Joiner joiner = Joiner.on("/").skipNulls();
 return Optional.of("/" + joiner.join(commons));
 }
    static List<String> urlParts(ApiDescription apiDescription) {return Splitter.on('/')
                .omitEmptyStrings()
                .trimResults()
                .splitToList(apiDescription.getPath());
 }
    public Multimap<String, ApiListing> scan(ApiListingScanningContext context) {final Multimap<String, ApiListing> apiListingMap = LinkedListMultimap.create();
 int position = 0;
 Map<ResourceGroup, List<RequestMappingContext>> requestMappingsByResourceGroup
                = context.getRequestMappingsByResourceGroup();
 Collection<ApiDescription> additionalListings = pluginsManager.additionalListings(context);
 Set<ResourceGroup> allResourceGroups = FluentIterable.from(collectResourceGroups(additionalListings))
                .append(requestMappingsByResourceGroup.keySet())
                .toSet();
 List<SecurityReference> securityReferences = newArrayList();
 for (final ResourceGroup resourceGroup : sortedByName(allResourceGroups)) {DocumentationContext documentationContext = context.getDocumentationContext();
 Set<String> produces = new LinkedHashSet<String>(documentationContext.getProduces());
 Set<String> consumes = new LinkedHashSet<String>(documentationContext.getConsumes());
 String host = documentationContext.getHost();
 Set<String> protocols = new LinkedHashSet<String>(documentationContext.getProtocols());
 Set<ApiDescription> apiDescriptions = newHashSet();
 Map<String, Model> models = new LinkedHashMap<String, Model>();
 List<RequestMappingContext> requestMappings = nullToEmptyList(requestMappingsByResourceGroup.get(resourceGroup));
 for (RequestMappingContext each : sortedByMethods(requestMappings)) {//url
 Map<String, Model> knownModels = new HashMap<>();
 models.putAll(apiModelReader.read(each.withKnownModels(models)));
 apiDescriptions.addAll(apiDescriptionReader.read(each));
 }
            //
 models.putAll(ModelCache.getInstance().getKnownModels());
 List<ApiDescription> additional = from(additionalListings)
                    .filter(and(belongsTo(resourceGroup.getGroupName()),
 onlySelectedApis(documentationContext)))
                    .toList();
 apiDescriptions.addAll(additional);
 List<ApiDescription> sortedApis = FluentIterable.from(apiDescriptions)
                    .toSortedList(documentationContext.getApiDescriptionOrdering());
 Optional<String> o = longestCommonPath(sortedApis);
 String resourcePath = new ResourcePathProvider(resourceGroup)
                    .resourcePath()
                    .or(o)
                    .orNull();
 PathProvider pathProvider = documentationContext.getPathProvider();
 String basePath = pathProvider.getApplicationBasePath();
 PathAdjuster adjuster = new PathMappingAdjuster(documentationContext);
 ApiListingBuilder apiListingBuilder = new ApiListingBuilder(context.apiDescriptionOrdering())
                    .apiVersion(documentationContext.getApiInfo().getVersion())
                    .basePath(adjuster.adjustedPath(basePath))
                    .resourcePath(resourcePath)
                    .produces(produces)
                    .consumes(consumes)
                    .host(host)
                    .protocols(protocols)
                    .securityReferences(securityReferences)
                    .apis(sortedApis)
                    .models(models)
                    .position(position++)
                    .availableTags(documentationContext.getTags());
 ApiListingContext apiListingContext = new ApiListingContext(context.getDocumentationType(),
 resourceGroup,
 apiListingBuilder);
 apiListingMap.put(resourceGroup.getGroupName(), pluginsManager.apiListing(apiListingContext));
 }
        return apiListingMap;
 }
    private Predicate<ApiDescription> onlySelectedApis(final DocumentationContext context) {return new Predicate<ApiDescription>() {
            @Override
 public boolean apply(ApiDescription input) {return context.getApiSelector().getPathSelector().apply(input.getPath());
 }
        };
 }
    private Iterable<RequestMappingContext> sortedByMethods(List<RequestMappingContext> contexts) {return contexts.stream().sorted(methodComparator()).collect(toList());
 }
    static Iterable<ResourceGroup> collectResourceGroups(Collection<ApiDescription> apiDescriptions) {return from(apiDescriptions)
                .transform(toResourceGroups());
 }
    static Iterable<ResourceGroup> sortedByName(Set<ResourceGroup> resourceGroups) {return from(resourceGroups).toSortedList(resourceGroupComparator());
 }
    static Predicate<ApiDescription> belongsTo(final String groupName) {return new Predicate<ApiDescription>() {
            @Override
 public boolean apply(ApiDescription input) {return !input.getGroupName().isPresent()
                        || groupName.equals(input.getGroupName().get());
 }
        };
 }
    private static Function<ApiDescription, ResourceGroup> toResourceGroups() {return new Function<ApiDescription, ResourceGroup>() {
            @Override
 public ResourceGroup apply(ApiDescription input) {
                return new ResourceGroup(input.getGroupName().or(Docket.DEFAULT_GROUP_NAME),
 null);
 }
        };
 }
    class ResourcePathProvider {
        private final ResourceGroup resourceGroup;
 ResourcePathProvider(ResourceGroup resourceGroup) {this.resourceGroup = resourceGroup;}
        public Optional<String> resourcePath() {
            return Optional.fromNullable(Strings.emptyToNull(controllerClass()
                            .transform(resourcePathExtractor())
                            .or("")));
 }
        private Function<Class<?>, String> resourcePathExtractor() {return new Function<Class<?>, String>() {
                @Override
 public String apply(Class<?> input) {String path = Iterables.getFirst(Arrays.asList(paths(input)), "");
 if (Strings.isNullOrEmpty(path)) {return "";}
                    if (path.startsWith("/")) {return path;}
                    return "/" + path;
 }
            };
 }
        @VisibleForTesting
 String[] paths(Class<?> controller) {
            RequestMapping annotation
                    = AnnotationUtils.findAnnotation(controller, RequestMapping.class);
 if (annotation != null) {return annotation.path();
 }
            return new String[]{};
 }
        private Optional<? extends Class<?>> controllerClass() {return resourceGroup.getControllerClass();
 }
    }
}

自定义注解类 ApiSingleParam

package com.mybatis.plus.swagger;
/**
 * Created by yueh on 2018/9/7. 
 */
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiSingleParam {Sring name() default "";
 String value() default "";
 Class<?> type() default String.class;
 String example() default "";
 boolean allowMultiple() default false;}

CommonData

package com.mybatis.plus.swagger;
/**
 * Created by yueh on 2018/9/18. 
 */
 public class CommonData {
 private static String RESULT_TYPE_NORMAL = "normal";
 private static String RESULT_TYPE_PAGE = "page";
 private static String RESULT_TYPE_LIST = "list";
 private static String RESULT_TYPE_OTHER = "other";
 private static String JSON_ERROR_CODE = "errorCode";
 private static String JSON_ERROR_MSG = "errorMsg";
 private static String JSON_START_PAGE_NUM = "startPageNum";
 private static String JSON_PAGE_SIZE = "pageSize";
 private static String JSON_PAGE_COUNT = "pageCount";
 private static String JSON_TOTAL_COUNT = "totalCount";
 public static final String RESULT_TYPE_NORMAL_FINAL = "normal";
 public static String getResultTypeNormal() {return RESULT_TYPE_NORMAL;}
    public static void setResultTypeNormal(String resultTypeNormal) {RESULT_TYPE_NORMAL = resultTypeNormal;}
    public static String getResultTypePage() {return RESULT_TYPE_PAGE;}
    public static void setResultTypePage(String resultTypePage) {RESULT_TYPE_PAGE = resultTypePage;}
    public static String getResultTypeList() {return RESULT_TYPE_LIST;}
    public static void setResultTypeList(String resultTypeList) {RESULT_TYPE_LIST = resultTypeList;}
    public static String getResultTypeOther() {return RESULT_TYPE_OTHER;}
    public static void setResultTypeOther(String resultTypeOther) {RESULT_TYPE_OTHER = resultTypeOther;}
    public static String getJsonErrorCode() {return JSON_ERROR_CODE;}
    public static void setJsonErrorCode(String jsonErrorCode) {JSON_ERROR_CODE = jsonErrorCode;}
    public static String getJsonErrorMsg() {return JSON_ERROR_MSG;}
    public static void setJsonErrorMsg(String jsonErrorMsg) {JSON_ERROR_MSG = jsonErrorMsg;}
    public static String getJsonStartPageNum() {return JSON_START_PAGE_NUM;}
    public static void setJsonStartPageNum(String jsonStartPageNum) {JSON_START_PAGE_NUM = jsonStartPageNum;}
    public static String getJsonPageSize() {return JSON_PAGE_SIZE;}
    public static void setJsonPageSize(String jsonPageSize) {JSON_PAGE_SIZE = jsonPageSize;}
    public static String getJsonPageCount() {return JSON_PAGE_COUNT;}
    public static void setJsonPageCount(String jsonPageCount) {JSON_PAGE_COUNT = jsonPageCount;}
    public static String getJsonTotalCount() {return JSON_TOTAL_COUNT;}
    public static void setJsonTotalCount(String jsonTotalCount) {JSON_TOTAL_COUNT = jsonTotalCount;}
}

全局字符串 GlobalString

package com.mybatis.plus.swagger;
/**
 * @Author wulongbo
 * @Date 2020/9/14 17:34
 * @Version 1.0
 */
 public class GlobalString {@ApiSingleParam(value = "姓名", example = "isWulongbo")
    public static final String JSON_NAME = "name";
 @ApiSingleParam(value = "年龄", example = "25")
    public static final String JSON_AGE = "age";
 @ApiSingleParam(value = "邮箱", example = "1191935532@qq.com")
    public static final String JSON_EMAIL = "email";
 @ApiSingleParam(value = "错误码", example = "0", type = Integer.class)
    public static final String JSON_ERROR_CODE = "errorCode";
 @ApiSingleParam(value = "错误信息", example = "OK")
    public static final String JSON_ERROR_MSG = "errorMsg";
}

ModelCache

package com.mybatis.plus.swagger;
import com.fasterxml.classmate.ResolvedType;
import com.fasterxml.classmate.TypeResolver;
import com.google.common.base.Function;
import org.springframework.plugin.core.OrderAwarePluginRegistry;
import org.springframework.plugin.core.PluginRegistry;
import springfox.documentation.schema.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.schema.TypeNameProviderPlugin;
import springfox.documentation.spi.schema.contexts.ModelContext;
import springfox.documentation.spi.service.contexts.DocumentationContext;
import java.lang.reflect.Field;
import java.util.*;
import static com.google.common.base.Strings.isNullOrEmpty;
import static com.google.common.collect.Lists.newArrayList;
import static com.mybatis.plus.swagger.CommonData.*;
import static org.springframework.util.ObjectUtils.isEmpty;
import static springfox.documentation.schema.Collections.collectionElementType;
import static springfox.documentation.spi.schema.contexts.ModelContext.inputParam;
/**
 * Created by yueh on 2018/9/13. */public class ModelCache {private Map<String, Model> knownModels = new HashMap<>();
 private DocumentationContext context;
 private Function<ResolvedType, ? extends ModelReference> factory;
 private TypeResolver typeResolver = new TypeResolver();
 private Map<String, ApiSingleParam> paramMap = new HashMap<>();
 private Class<?> cls;
 private ModelCache() {}
    public static ModelCache getInstance() {return ModelCacheSub.instance;}
    public ModelCache setParamMap(Map<String, ApiSingleParam> paramMap) {
        this.paramMap = paramMap;
 return getInstance();}
    public ModelCache setParamClass(Class<?> cls) {
        this.cls = cls;
 return getInstance();}
    public Class<?> getParamClass() {return cls;}
    public ModelCache setFactory(Function<ResolvedType, ? extends ModelReference> factory) {
        this.factory = factory;
 return getInstance();}
    public void setContext(DocumentationContext context) {this.context = context;}
    public DocumentationContext getContext() {return context;}
    public Map<String, Model> getKnownModels() {return knownModels;}
    public ModelCache addModel(ApiJsonObject2 jsonObj) {String modelName = jsonObj.name();
 knownModels.put(modelName,
 new Model(modelName,
 modelName,
 new TypeResolver().resolve(String.class),
 "com.mybatis.plus.swagger.CommonData",
 toPropertyMap(jsonObj.value()),
 "POST 参数",
 "","",
 newArrayList(), null, null));
 String resultName = jsonObj.name() + "-" + "result";
 knownModels.put(resultName,
 new Model(resultName,
 resultName,
 new TypeResolver().resolve(String.class),
 "com.mybatis.plus.swagger.CommonData",
 toResultMap(jsonObj.result(), resultName),
 "返回模型",
 "","",
 newArrayList(), null, null));
 return ModelCacheSub.instance;
 }
    public Map<String, ModelProperty> toResultMap(ApiJsonResult jsonResult, String groupName) {//        System.out.println("--- toResultMap ---");
 List<String> values = Arrays.asList(jsonResult.value());
 List<String> outer = new ArrayList<>();
 if (!getResultTypeOther().equals(jsonResult.type())) {outer.add(getJsonErrorCode());
 outer.add(getJsonErrorMsg());
 if (!getResultTypeNormal().equals(jsonResult.type())) {
                //model
 String subModelName = groupName + "-" + jsonResult.name();
 knownModels.put(subModelName,
 new Model(subModelName,
 subModelName,
 new TypeResolver().resolve(String.class),
 "com.mybatis.plus.swagger.CommonData",
 transResultMap(values),
 "返回模型",
 "","",
 newArrayList(), null, null));
 //prop
 Map<String, ModelProperty> propertyMap = new HashMap<>();
//                outer.add(jsonResult.name());
 ResolvedType type = new TypeResolver().resolve(List.class);
 ModelProperty mp = new ModelProperty(jsonResult.name(),
 type,
 "",
 0,
 false, false, true, false, "",
 null, "",
 null, "",
 null, newArrayList());// new AllowableRangeValues("1", "2000"),//.allowableValues(new AllowableListValues(["ABC", "ONE", "TWO"], "string"))
 mp.updateModelRef(getModelRef());
 ResolvedType collectionElementType = collectionElementType(type);
 try {Field f = ModelProperty.class.getDeclaredField("modelRef");
 f.setAccessible(true);
 f.set(mp, new ModelRef("List", new ModelRef(subModelName)));
 } catch (Exception e) {e.printStackTrace();
 }
                propertyMap.put(jsonResult.name(), mp);
 if (getResultTypePage().equals(jsonResult.type())) {outer.add(getJsonStartPageNum());
 outer.add(getJsonPageSize());
 outer.add(getJsonTotalCount());
 }
                propertyMap.putAll(transResultMap(outer));
 return propertyMap;
 }
            outer.addAll(values);
 return transResultMap(outer);
 }
        return transResultMap(values);
 }
    public Map<String, ModelProperty> transResultMap(List<String> values) {Map<String, ModelProperty> propertyMap = new HashMap<>();
 for (String resultName : values) {ApiSingleParam param = paramMap.get(resultName);
 if (isEmpty(param)) {continue;}
            Class<?> type = param.type();
 if (!isEmpty(param)) {type = param.type();
 } else if (isEmpty(type)) {type = String.class;}
            boolean allowMultiple = param.allowMultiple();
 if (!isEmpty(param)) {allowMultiple = param.allowMultiple();
 }
            ResolvedType resolvedType = null;
 if (allowMultiple) {resolvedType = new TypeResolver().resolve(List.class, type);
 } else {resolvedType = new TypeResolver().resolve(type);
 }
            ModelProperty mp = new ModelProperty(
                    resultName,
 resolvedType,
 param.type().getName(),
 0,
 false, false, true, false, param.value(),
 null, param.example(),
 null, "",
 null, newArrayList());// new AllowableRangeValues("1", "2000"),//.allowableValues(new AllowableListValues(["ABC", "ONE", "TWO"], "string"))
 mp.updateModelRef(getModelRef());
 propertyMap.put(resultName, mp);
 }
        return propertyMap;
 }
    public Map<String, ModelProperty> toPropertyMap(ApiJsonProperty2[] jsonProp) {//        System.out.println("--- toPropertyMap ---");
 Map<String, ModelProperty> propertyMap = new HashMap<String, ModelProperty>();
 for (ApiJsonProperty2 property : jsonProp) {String propertyName = property.name();
 ApiSingleParam param = paramMap.get(propertyName);
 String description = property.description();
 if (isNullOrEmpty(description) && !isEmpty(param)) {description = param.value();
 }
            String example = property.description();
 if (isNullOrEmpty(example) && !isEmpty(param)) {example = param.example();
 }
            Class<?> type = property.type();
 if (!isEmpty(param)) {type = param.type();
 } else if (isEmpty(type)) {type = String.class;}
            boolean allowMultiple = property.allowMultiple();
 if (!isEmpty(param)) {allowMultiple = param.allowMultiple();
 }
            ResolvedType resolvedType = null;
 if (allowMultiple) {resolvedType = new TypeResolver().resolve(List.class, type);
 } else {resolvedType = new TypeResolver().resolve(type);
 }
//            System.out.println("----- example:" + example);
//            System.out.println("----- description:" + description);
 ModelProperty mp = new ModelProperty(
                    propertyName,
 resolvedType,
 type.toString(),
 0,
 property.required(),
 false, property.readOnly(),
 null, description,
 null, example,
 null, property.defaultValue(),
 null, newArrayList());// new AllowableRangeValues("1", "2000"),//.allowableValues(new AllowableListValues(["ABC", "ONE", "TWO"], "string"))
 mp.updateModelRef(getModelRef());
 propertyMap.put(property.name(), mp);
 }
        return propertyMap;
 }
    private static class ModelCacheSub {private static ModelCache instance = new ModelCache();
 }
    private Function<ResolvedType, ? extends ModelReference> getModelRef() {Function<ResolvedType, ? extends ModelReference> factory = getFactory();
//        ModelReference stringModel = factory.apply(typeResolver.resolve(List.class, String.class));
 return factory;
 }
    public Function<ResolvedType, ? extends ModelReference> getFactory() {if (factory == null) {List<DefaultTypeNameProvider> providers = newArrayList();
 providers.add(new DefaultTypeNameProvider());
 PluginRegistry<TypeNameProviderPlugin, DocumentationType> modelNameRegistry =
                    OrderAwarePluginRegistry.create(providers);
 TypeNameExtractor typeNameExtractor = new TypeNameExtractor(
                    typeResolver,
 modelNameRegistry,
 new JacksonEnumTypeDeterminer());
 ModelContext modelContext = inputParam(context.getGroupName(),
 String.class,
 context.getDocumentationType(),
 context.getAlternateTypeProvider(),
 context.getGenericsNamingStrategy(),
 context.getIgnorableParameterTypes());
 factory = ResolvedTypes.modelRefFactory(modelContext, typeNameExtractor);
 }
        return factory;
 }
}

留神:在 ModelCache 类中 CommonData 的门路肯定要改为你实在的我的项目门路

ParametersReader

package com.mybatis.plus.swagger;
import com.fasterxml.classmate.ResolvedType;
import com.fasterxml.classmate.TypeResolver;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.schema.ModelReference;
import springfox.documentation.schema.ResolvedTypes;
import springfox.documentation.schema.TypeNameExtractor;
import springfox.documentation.service.Parameter;
import springfox.documentation.service.ResolvedMethodParameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.schema.contexts.ModelContext;
import springfox.documentation.spi.service.OperationBuilderPlugin;
import springfox.documentation.spi.service.contexts.OperationContext;
import springfox.documentation.spi.service.contexts.ParameterContext;
import springfox.documentation.spring.web.DescriptionResolver;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static springfox.documentation.spi.schema.contexts.ModelContext.inputParam;
import static springfox.documentation.swagger.common.SwaggerPluginSupport.pluginDoesApply;
/**
 * Created by yueh on 2018/9/10. 
 */
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class ParametersReader implements OperationBuilderPlugin {
    private final DescriptionResolver descriptions;
 private final TypeNameExtractor nameExtractor;
 private final TypeResolver resolver;
 @Autowired
 public ParametersReader(DescriptionResolver descriptions, TypeNameExtractor nameExtractor, TypeResolver resolver) {
        this.nameExtractor = nameExtractor;
 this.resolver = resolver;
 this.descriptions = descriptions;
 }
    @Override
 public void apply(OperationContext context) {context.operationBuilder().parameters(readParameters(context));
 }
    @Override
 public boolean supports(DocumentationType delimiter) {return pluginDoesApply(delimiter);
 }
    private List<Parameter> readParameters(OperationContext context) {List<Parameter> parameters = Lists.newArrayList();
 List<ResolvedMethodParameter> methodParameters = context.getParameters();
 Map<String, ApiSingleParam> paramMap = new HashMap<>();
 Field[] fields = ModelCache.getInstance().getParamClass().getDeclaredFields();
 String type = new String();
 for (Field field : fields) {if (field.isAnnotationPresent(ApiSingleParam.class)) {ApiSingleParam param = field.getAnnotation(ApiSingleParam.class);
 try {String name = (String) field.get(type);
 paramMap.put(name, param);
 } catch (Exception e) {}}
        }
        for (ResolvedMethodParameter methodParameter : methodParameters) {
            ParameterContext parameterContext = new ParameterContext(methodParameter,
 new ParameterBuilder(),
 context.getDocumentationContext(),
 context.getGenericsNamingStrategy(),
 context);
 Function<ResolvedType, ? extends ModelReference> factory = createModelRefFactory(parameterContext);
 Optional<ApiJsonObject2> annotation = context.findAnnotation(ApiJsonObject2.class);
 if (annotation.isPresent()) {ModelCache.getInstance().setFactory(factory)
                        .setParamMap(paramMap)
                        .addModel(annotation.get());
 }
        }
        return parameters;
 }
    private Function<ResolvedType, ? extends ModelReference> createModelRefFactory(ParameterContext context) {
        ModelContext modelContext = inputParam(context.getGroupName(),
 context.resolvedMethodParameter().getParameterType(),
 context.getDocumentationType(),
 context.getAlternateTypeProvider(),
 context.getGenericNamingStrategy(),
 context.getIgnorableParameterTypes());
 return ResolvedTypes.modelRefFactory(modelContext, nameExtractor);
 }
}

OK!贴完代码后的目录构造如下:

因为咱们之前 mybatis-plus 我的项目没有引入 json 依赖
pom.xml 文件引入fastjson

<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
 <groupId>com.alibaba</groupId>
 <artifactId>fastjson</artifactId>
 <version>1.2.70</version>
</dependency>

封装返回值

新建一个 base 文件夹,贴入罕用的封装类
BaseApiService

package com.mybatis.plus.base;
import lombok.Data;
import org.springframework.stereotype.Component;
@Data
@Component
public class BaseApiService<T> {public BaseResponse<T> setResultError(Integer code, String msg) {return setResult(code, msg, null);
 }
   // 返回谬误,能够传 msg
 public BaseResponse<T> setResultError(String msg) {return setResult(PageCodeEnum.HTTP_RES_500.getCode(), msg, null);
 }
   // 返回胜利,能够传 data 值
 public BaseResponse<T> setResultSuccess(T data) {return setResult(PageCodeEnum.HTTP_RES_200.getCode(), PageCodeEnum.HTTP_RES_200.getMsg(), data);
 }
   // 返回胜利,沒有 data 值
 public BaseResponse<T> setResultSuccess() {return setResult(PageCodeEnum.HTTP_RES_200.getCode(), PageCodeEnum.HTTP_RES_200.getMsg(), null);
 }
   // 返回胜利,沒有 data 值
 public BaseResponse<T> setResultSuccess(String msg) {return setResult(PageCodeEnum.HTTP_RES_200.getCode(), msg, null);
 }
   // 通用封装
 public BaseResponse<T> setResult(Integer code, String msg, T data) {return new BaseResponse<T>(code, msg, data);
 }
   // 调用数据库封装
 public Boolean toDaoResult(int result){return result>0?true:false;}
}

BaseResponse

package com.mybatis.plus.base;
import lombok.Data;
@Data
public class BaseResponse<T> {
   /**
 * 返回码
 */
 private Integer code;
 /**
 * 音讯(最好用简写,不占用宽带)
 */ private String msg;
 /**
 * 数据
 */
 private T data;
 public BaseResponse() {}
   public BaseResponse(Integer code, String msg, T data) {super();
 this.code = code;
 this.msg = msg;
 this.data = data;
 }
   /**
 * 未登录返回后果
 */
 public static <T>   BaseResponse<T> unauthorized(T data) {return new BaseResponse<T>(ResultCode.UNAUTHORIZED.getCode(), ResultCode.UNAUTHORIZED.getMessage(), data);
 }
   /**
 * 未受权返回后果
 */
 public static <T>   BaseResponse<T> forbidden(T data) {return new BaseResponse<T>(ResultCode.FORBIDDEN.getCode(), ResultCode.FORBIDDEN.getMessage(), data);
 }
}

IErrorCode

package com.mybatis.plus.base;
/**
 * 封装 API 的错误码
 */
public interface IErrorCode {Integer getCode();
 String getMessage();}

PageCodeEnum

package com.mybatis.plus.base;
/**
 * @Author wulongbo
 * @Date 2020/9/14 15:38
 * @Version 1.0
 */public enum PageCodeEnum {
    // 公共
 HTTP_RES_200(200,"success"),
 HTTP_RES_500(500,"fail"),
 SUCCESS(200, "胜利"),
 UNKNOWN_ERROR(9998,"未知异样"),
 SYSTEM_ERROR(9999, "零碎异样"),
 INSUFFICIENT_PERMISSION(4003, "权限有余"),
 WARN(9000, "失败"),
 REQUEST_PARAMETER_ERROR(1002, "申请参数谬误"),
 // 分页
 PAGE_CURRENTPAGE_EMPTY(5000, "以后页码不能为空!"),
 PAGE_PAGESIZE_EMPTY(5001, "每页显示的条数不能为空!");
 private Integer code;
 private String msg;
 // 构造方法,留神:构造方法不能为 public,因为 enum 并不能够被实例化
 private PageCodeEnum(Integer code, String msg) {
        this.code = code;
 this.msg = msg;
 }
    // 不须要定义 set 办法,避免批改
 public Integer getCode() {return code;}
    public String getMsg() {return msg;}
}

ResultCode

package com.mybatis.plus.base;
/**
 * 枚举了一些罕用 API 操作码
 */
public enum ResultCode implements IErrorCode {SUCCESS(200, "操作胜利"),
 FAILED(500, "操作失败"),
 VALIDATE_FAILED(404, "参数检验失败"),
 UNAUTHORIZED(401, "暂未登录或 token 曾经过期"),
 FORBIDDEN(403, "没有相干权限");
 private Integer code;
 private String message;
 private ResultCode(Integer code, String message) {
        this.code = code;
 this.message = message;
 }
    public Integer getCode() {return code;}
    public String getMessage() {return message;}
}

OK!目录构造如下:

当初咱们在 UserController 中退出咱们自定义的注解

package com.mybatis.plus.controller;
import com.alibaba.fastjson.JSONObject;
import com.mybatis.plus.base.BaseApiService;
import com.mybatis.plus.base.BaseResponse;
import com.mybatis.plus.base.PageCodeEnum;
import com.mybatis.plus.entity.User;
import com.mybatis.plus.service.IUserService;
import com.mybatis.plus.swagger.ApiJsonObject2;
import com.mybatis.plus.swagger.ApiJsonProperty2;
import com.mybatis.plus.swagger.ApiJsonResult;
import com.mybatis.plus.swagger.GlobalString;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author wulongbo
 * @since 2020-11-09
 */
@RestController
@RequestMapping("/user")
@CrossOrigin
public class UserController extends BaseApiService {
    @Autowired
 private IUserService iUserService;
 @ApiOperation(value="增加用户信息", notes="增加用户信息")
    @ApiImplicitParams({@ApiImplicitParam(paramType = "query", name = "name", dataType = "String", required = true, value = "姓名"),
 @ApiImplicitParam(paramType = "query", name = "age", dataType = "int", required = true, value = "年龄"),
 @ApiImplicitParam(paramType = "query", name = "email", dataType = "String", required = true, value = "邮箱") })
    @PostMapping("/addUser")
    public boolean addUser(String name,Integer age,String email) {
        try {User user=new User();
 user.setName(name);
 user.setAge(age);
 user.setEmail(email);
 iUserService.recordJob(user);
 }catch (Exception e){return false;}
        return true;
 }
    @ApiOperation(value="删除用户信息", notes="删除用户信息")
    @ApiImplicitParams({@ApiImplicitParam(paramType = "query", name = "id", dataType = "long", required = true, value = "用户 id")})
    @PostMapping("/delUser")
    public boolean delUser(Long id) {
        try {User user=new User();
 user.setId(id);
 iUserService.delJob(user);
 }catch (Exception e){return false;}
        return true;
 }
    /**
 * JSONObject 参数增加用户信息
 * @param json
 * @return
 */
 @ApiOperation(value="JSONObject 参数增加用户信息", notes="JSONObject 参数增加用户信息")
    @ApiJsonObject2(name = "addUserByJson", value = {@ApiJsonProperty2(name = GlobalString.JSON_NAME),
 @ApiJsonProperty2(name = GlobalString.JSON_AGE),
 @ApiJsonProperty2(name = GlobalString.JSON_EMAIL)},
 result = @ApiJsonResult({}))
    @ApiImplicitParam(name = "json", required = true, dataType = "addUserByJson")
    @ApiResponses({@ApiResponse(code = 200, message = "OK", reference = "addUserByJson")})
    @RequestMapping(value = "/addUserByJson", method = RequestMethod.POST, consumes ="application/json", produces = "application/json")
    public BaseResponse<JSONObject> addUserByJson(@RequestBody String json){JSONObject jsonObject=JSONObject.parseObject(json);
 String name=jsonObject.getString("name"); // 姓名
 Integer age=jsonObject.getInteger("age");// 年龄
 String email=jsonObject.getString("email");// 邮箱
 try {User user=new User();
 user.setName(name);
 user.setAge(age);
 user.setEmail(email);
 iUserService.recordJob(user);
 }catch (Exception e){return setResultError(PageCodeEnum.HTTP_RES_500.getMsg());
 }
        return setResultSuccess(PageCodeEnum.HTTP_RES_200);
 }
    
}

启动 MybatisPlusApplication 并拜访 http://localhost:8080/swagger-ui.html

好!接下来咱们看看 swagger 文档会有什么不同!

GlobalString 中的参数主动读取到了 swagger 中,咱们间接执行接口拜访:

并查看数据库是否有新增记录:

完满!至此咱们 swagger 再也不必手填参数数值了,间接丢给前端,你 get 到了吗!

正文完
 0