关于使用Swagger-ui时文档显示实体类中隐藏部分字段的问题

所遇到的问题:

在swagger-ui测试页面测试接口时,由于在实体类中添加部分临时的实体类导致测试文档过于冗杂
如图:

解决:

pom.xml添加依赖:

 <dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.2</version></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.9.2</version></dependency><dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.2.0</version></dependency>

在common目录下的annotation创建@IgnoreSwaggerParameter
关于Annotation Types注解的链接: https://blog.csdn.net/sss2951/article/details/97907761
关于自定义注释@interface的用法理解的链接: https://blog.csdn.net/zhangbeizhen18/article/details/87885441/

package com.qqkj.server.common.annotation;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;// swagger忽略的参数
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface IgnoreSwaggerParameter {}

在common目录下的converter创建CustomizeModelAttributeParameterExpander.java

package com.qqkj.server.common.converter;import cn.hutool.core.util.ReflectUtil;
import com.fasterxml.classmate.ResolvedType;
import com.fasterxml.classmate.members.ResolvedField;
import com.fasterxml.classmate.members.ResolvedMethod;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.Sets;
import com.qqkj.server.common.annotation.IgnoreSwaggerParameter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.schema.Maps;
import springfox.documentation.schema.Types;
import springfox.documentation.schema.property.bean.AccessorsProvider;
import springfox.documentation.schema.property.field.FieldProvider;
import springfox.documentation.service.Parameter;
import springfox.documentation.spi.schema.AlternateTypeProvider;
import springfox.documentation.spi.schema.EnumTypeDeterminer;
import springfox.documentation.spi.service.contexts.ParameterExpansionContext;
import springfox.documentation.spring.web.plugins.DocumentationPluginsManager;
import springfox.documentation.spring.web.readers.parameter.ExpansionContext;
import springfox.documentation.spring.web.readers.parameter.ModelAttributeField;
import springfox.documentation.spring.web.readers.parameter.ModelAttributeParameterExpander;
import springfox.documentation.spring.web.readers.parameter.ModelAttributeParameterMetadataAccessor;import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;import static com.google.common.base.Objects.equal;
import static com.google.common.base.Predicates.*;
import static com.google.common.base.Strings.isNullOrEmpty;
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 springfox.documentation.schema.Collections.collectionElementType;
import static springfox.documentation.schema.Collections.isContainerType;
import static springfox.documentation.schema.Types.isVoid;
import static springfox.documentation.schema.Types.typeNameFor;/*** 覆盖{@link ModelAttributeParameterExpander}** @see IgnoreSwaggerParameter*/
@Component
@Primary
public class CustomizeModelAttributeParameterExpander extends ModelAttributeParameterExpander {private static final Logger LOG = LoggerFactory.getLogger(ModelAttributeParameterExpander.class);private final FieldProvider fields;private final AccessorsProvider accessors;private final EnumTypeDeterminer enumTypeDeterminer;@Autowiredprotected DocumentationPluginsManager pluginsManager;@Autowiredpublic CustomizeModelAttributeParameterExpander(FieldProvider fields, AccessorsProvider accessors, EnumTypeDeterminer enumTypeDeterminer) {super(fields, accessors, enumTypeDeterminer);this.fields = fields;this.accessors = accessors;this.enumTypeDeterminer = enumTypeDeterminer;}public List<Parameter> expand(ExpansionContext context) {List<Parameter> parameters = newArrayList();Set<PropertyDescriptor> propertyDescriptors = propertyDescriptors(context.getParamType().getErasedType());Map<Method, PropertyDescriptor> propertyLookupByGetter= propertyDescriptorsByMethod(context.getParamType().getErasedType(), propertyDescriptors);Iterable<ResolvedMethod> getters = FluentIterable.from(accessors.in(context.getParamType())).filter(onlyValidGetters(propertyLookupByGetter.keySet()));Map<String, ResolvedField> fieldsByName = FluentIterable.from(this.fields.in(context.getParamType())).uniqueIndex(new Function<ResolvedField, String>() {@Overridepublic String apply(ResolvedField input) {return input.getName();}});LOG.debug("Expanding parameter type: {}", context.getParamType());final AlternateTypeProvider alternateTypeProvider = context.getDocumentationContext().getAlternateTypeProvider();FluentIterable<ModelAttributeField> attributes =allModelAttributes(propertyLookupByGetter,getters,fieldsByName,alternateTypeProvider);FluentIterable<ModelAttributeField> expendables = attributes.filter(not(simpleType())).filter(not(recursiveType(context)));for (ModelAttributeField each : expendables) {LOG.debug("Attempting to expand expandable property: {}", each.getName());parameters.addAll(expand(context.childContext(nestedParentName(context.getParentName(), each),each.getFieldType(),context.getOperationContext())));}FluentIterable<ModelAttributeField> collectionTypes = attributes.filter(and(isCollection(), not(recursiveCollectionItemType(context.getParamType()))));for (ModelAttributeField each : collectionTypes) {LOG.debug("Attempting to expand collection/array field: {}", each.getName());ResolvedType itemType = collectionElementType(each.getFieldType());if (Types.isBaseType(itemType) || enumTypeDeterminer.isEnum(itemType.getErasedType())) {parameters.add(simpleFields(context.getParentName(), context, each));} else {ExpansionContext childContext = context.childContext(nestedParentName(context.getParentName(), each),itemType,context.getOperationContext());if (!context.hasSeenType(itemType)) {parameters.addAll(expand(childContext));}}}FluentIterable<ModelAttributeField> simpleFields = attributes.filter(simpleType());for (ModelAttributeField each : simpleFields) {parameters.add(simpleFields(context.getParentName(), context, each));}return FluentIterable.from(parameters).filter(not(hiddenParameters())).filter(not(voidParameters())).toList();}private FluentIterable<ModelAttributeField> allModelAttributes(Map<Method, PropertyDescriptor> propertyLookupByGetter,Iterable<ResolvedMethod> getters,Map<String, ResolvedField> fieldsByName,AlternateTypeProvider alternateTypeProvider) {FluentIterable<ModelAttributeField> modelAttributesFromGetters = from(getters).transform(toModelAttributeField(fieldsByName, propertyLookupByGetter, alternateTypeProvider));FluentIterable<ModelAttributeField> modelAttributesFromFields = from(fieldsByName.values()).filter(publicFields()).transform(toModelAttributeField(alternateTypeProvider));return FluentIterable.from(Sets.union(modelAttributesFromFields.toSet(),modelAttributesFromGetters.toSet()));}private Function<ResolvedField, ModelAttributeField> toModelAttributeField(final AlternateTypeProvider alternateTypeProvider) {return new Function<ResolvedField, ModelAttributeField>() {@Overridepublic ModelAttributeField apply(ResolvedField input) {return new ModelAttributeField(alternateTypeProvider.alternateFor(input.getType()),input.getName(),input,input);}};}private Predicate<ResolvedField> publicFields() {return new Predicate<ResolvedField>() {@Overridepublic boolean apply(ResolvedField input) {return input.isPublic();}};}private Predicate<Parameter> voidParameters() {return new Predicate<Parameter>() {@Overridepublic boolean apply(Parameter input) {return isVoid(input.getType().orNull());}};}private Predicate<ModelAttributeField> recursiveCollectionItemType(final ResolvedType paramType) {return new Predicate<ModelAttributeField>() {@Overridepublic boolean apply(ModelAttributeField input) {return equal(collectionElementType(input.getFieldType()), paramType);}};}private Predicate<Parameter> hiddenParameters() {return new Predicate<Parameter>() {@Overridepublic boolean apply(Parameter input) {return input.isHidden();}};}private Parameter simpleFields(String parentName,ExpansionContext context,ModelAttributeField each) {LOG.debug("Attempting to expand field: {}", each);String dataTypeName = Optional.fromNullable(typeNameFor(each.getFieldType().getErasedType())).or(each.getFieldType().getErasedType().getSimpleName());LOG.debug("Building parameter for field: {}, with type: ", each, each.getFieldType());ParameterExpansionContext parameterExpansionContext = new ParameterExpansionContext(dataTypeName,parentName,determineScalarParameterType(context.getOperationContext().consumes(),context.getOperationContext().httpMethod()),new ModelAttributeParameterMetadataAccessor(each.annotatedElements(),each.getFieldType(),each.getName()),context.getDocumentationContext().getDocumentationType(),new ParameterBuilder());return pluginsManager.expandParameter(parameterExpansionContext);}private Predicate<ModelAttributeField> recursiveType(final ExpansionContext context) {return new Predicate<ModelAttributeField>() {@Overridepublic boolean apply(ModelAttributeField input) {return context.hasSeenType(input.getFieldType());}};}private Predicate<ModelAttributeField> simpleType() {return and(not(isCollection()), not(isMap()),or(belongsToJavaPackage(),isBaseType(),isEnum()));}private Predicate<ModelAttributeField> isCollection() {return new Predicate<ModelAttributeField>() {@Overridepublic boolean apply(ModelAttributeField input) {return isContainerType(input.getFieldType());}};}private Predicate<ModelAttributeField> isMap() {return new Predicate<ModelAttributeField>() {@Overridepublic boolean apply(ModelAttributeField input) {return Maps.isMapType(input.getFieldType());}};}private Predicate<ModelAttributeField> isEnum() {return new Predicate<ModelAttributeField>() {@Overridepublic boolean apply(ModelAttributeField input) {return enumTypeDeterminer.isEnum(input.getFieldType().getErasedType());}};}private Predicate<ModelAttributeField> belongsToJavaPackage() {return new Predicate<ModelAttributeField>() {@Overridepublic boolean apply(ModelAttributeField input) {return ClassUtils.getPackageName(input.getFieldType().getErasedType()).startsWith("java.lang");}};}private Predicate<ModelAttributeField> isBaseType() {return new Predicate<ModelAttributeField>() {@Overridepublic boolean apply(ModelAttributeField input) {return Types.isBaseType(input.getFieldType())|| input.getFieldType().isPrimitive();}};}private Function<ResolvedMethod, ModelAttributeField> toModelAttributeField(final Map<String, ResolvedField> fieldsByName,final Map<Method, PropertyDescriptor> propertyLookupByGetter,final AlternateTypeProvider alternateTypeProvider) {return new Function<ResolvedMethod, ModelAttributeField>() {@Overridepublic ModelAttributeField apply(ResolvedMethod input) {String name = propertyLookupByGetter.get(input.getRawMember()).getName();return new ModelAttributeField(fieldType(alternateTypeProvider, input),name,input,fieldsByName.get(name));}};}private Predicate<ResolvedMethod> onlyValidGetters(final Set<Method> methods) {return new Predicate<ResolvedMethod>() {@Overridepublic boolean apply(ResolvedMethod input) {return methods.contains(input.getRawMember());}};}private String nestedParentName(String parentName, ModelAttributeField attribute) {String name = attribute.getName();ResolvedType fieldType = attribute.getFieldType();if (isContainerType(fieldType) && !Types.isBaseType(collectionElementType(fieldType))) {name += "[0]";}if (isNullOrEmpty(parentName)) {return name;}return String.format("%s.%s", parentName, name);}private ResolvedType fieldType(AlternateTypeProvider alternateTypeProvider, ResolvedMethod method) {return alternateTypeProvider.alternateFor(method.getType());}private Set<PropertyDescriptor> propertyDescriptors(final Class<?> clazz) {try {Set<PropertyDescriptor> beanProps = new HashSet<>();PropertyDescriptor[] descriptors = getBeanInfo(clazz).getPropertyDescriptors();for (PropertyDescriptor descriptor : descriptors) {Field field = null;try {// field = clazz.getDeclaredField(descriptor.getName());// 根据 Zy馒头  的反馈,上面的方式获取父类的字段会出错,所以使用了hutool工具包,大家可以根据自己的需要自行下载// <dependency>//     <groupId>cn.hutool</groupId>//     <artifactId>hutool-all</artifactId>//     <version>5.2.0</version>//</dependency>field = ReflectUtil.getField(clazz, descriptor.getName());} catch (Exception e) {LOG.debug(String.format("Failed to get bean properties on (%s)", clazz), e);}if (field != null) {field.setAccessible(true);IgnoreSwaggerParameter ignoreSwaggerParameter = field.getDeclaredAnnotation(IgnoreSwaggerParameter.class);if (ignoreSwaggerParameter != null) {continue;}}if (descriptor.getReadMethod() != null) {beanProps.add(descriptor);}}return beanProps;} catch (Exception e) {LOG.warn(String.format("Failed to get bean properties on (%s)", clazz), e);}return newHashSet();}private Map<Method, PropertyDescriptor> propertyDescriptorsByMethod(final Class<?> clazz,Set<PropertyDescriptor> propertyDescriptors) {return FluentIterable.from(propertyDescriptors).filter(new Predicate<PropertyDescriptor>() {@Overridepublic boolean apply(PropertyDescriptor input) {return input.getReadMethod() != null&& !clazz.isAssignableFrom(Collection.class)&& !"isEmpty".equals(input.getReadMethod().getName());}}).uniqueIndex(new Function<PropertyDescriptor, Method>() {@Overridepublic Method apply(PropertyDescriptor input) {return input.getReadMethod();}});}@VisibleForTestingBeanInfo getBeanInfo(Class<?> clazz) throws IntrospectionException {return Introspector.getBeanInfo(clazz);}public static String determineScalarParameterType(Set<? extends MediaType> consumes, HttpMethod method) {String parameterType = "query";if (consumes.contains(MediaType.APPLICATION_FORM_URLENCODED)&& method == HttpMethod.POST) {parameterType = "form";} else if (consumes.contains(MediaType.MULTIPART_FORM_DATA)&& method == HttpMethod.POST) {parameterType = "formData";}return parameterType;}
}

在实体类上添加注解@IgnoreSwaggerParameter,问题解决

 @TableField(exist = false)@IgnoreSwaggerParameterprivate transient List<Efficiency> efficiencyList;

关于使用Swagger-ui时文档显示实体类中隐藏部分字段的问题相关推荐

  1. Spring Boot接口返回的字段名和实体类中定义的字段名不一致

    问题描述:在使用@ResponseBody注解返回一个Controller接口数据时会遇到接口中返回的字段与实体中定义的字段不一致的情况,例如实体类中定义的字段名如下: @ApiModelProper ...

  2. java实体类 判断 字段_java8 根据实体类中的某个字段对实体类去重

    1.测试代码示例 import com.alibaba.fastjson.JSON; import lombok.Data; import lombok.extern.slf4j.Slf4j; imp ...

  3. mybatis plus忽略实体类中某一个字段的映射

    @TableField(exist = false) //不是数据库字段,但必须使用

  4. java查询数据库返回数据映射到实体类,不返回字段为空的属性

    查询mysql数据库,映射字段内容到实体类中,以下两种场景可以指定实体类返回的字段 情景1: 有些字段为null,指定有值返回 情景2:只想返回实体类中的部分字段,查询语句指定select后面要返回的 ...

  5. 创建Swagger UI文档的步骤

    Swagger是一个基于网络的API文档框架.它被用来为API创建交互式文档,这些API是为特定目的而建立的.与其他文档类型相比,Swagger UI文档享有许多优势. 它是开源的 使你能够创建和分享 ...

  6. Java使用swagger时显示实体类注解问题

    第一步,在实体类中@ApiModel(description= "表名描述") 第二步,在字段属性中@ApiModelProperty(value = "字段备注&quo ...

  7. IDEA中根据数据库自动生成实体类,并自定义所生成的实体类中的注解 @Table @Id @...

    使用IDEA项目添加Hibernate扩展,生成实体类并配置实体类中的注解 一.使用Hibernate自动生成实体类 1.在项目上右键,选择Add Framework Support找到 Hibern ...

  8. Long类型传到前端失去精度(2):Long类型不是实体类的某一个字段,Long类型是一个函数的返回值

    Long类型传到前端失去精度(2):Long类型不是实体类的某一个字段,Long类型是一个函数的返回值 又是转换Mybatis-Plus的一天,又遇到了之前熟悉的问题:Long类型传到前端失去精度.可 ...

  9. 显示mac电脑中隐藏的文件和文件夹

    显示mac电脑中隐藏的文件和文件夹的办法:打开电脑,cd到相应的文件夹,输入以下命令,为显示隐藏的文件和文件夹 defaults write com.apple.finder AppleShowAll ...

最新文章

  1. May 18:PHP 用到的学习工具
  2. 【算法】快速选择算法 ( 数组中找第 K 大元素 )
  3. Microsoft SQL Server SA权限最新入侵方法
  4. mysql affected rows_mysql_affected_rows函数定义与用法汇总
  5. java获取页面标签_java获取网页源代码后,提取标签内容……
  6. 【Anaconda版本重装】Anaconda版本与Python版本的对应关系
  7. 自制 Chrome Custom.css 设置网页字体为微软雅黑扩展
  8. 转贴:win2008改造成准VISTA
  9. 软件工程结对编程博客
  10. 微积分应用 计算机,微积分及其应用 P.D.Lax等著;林开亮
  11. 遗传算法原理及算法实例
  12. 质量管理 六西格玛-黑带大师
  13. 17张程序员壁纸推荐,是否有一张你喜欢的?
  14. HTML5期末大作业:腾讯游戏网站设计——腾讯游戏官网(13页) HTML+CSS+JavaScript web网页设计与开发
  15. 一千万数据,怎么快速查询
  16. SQL Native Client][SQL Server]无法将函数单元 'sp_sqlagent_get_startup_info' 添加到组件 'Agen...
  17. VB程序设计教程(第四版)龚沛曾 实验8-2
  18. poj 2152 树形dp(建立消防站)
  19. python单用户登录_Python 实现用户登录的简单方法
  20. java:POI导出excel

热门文章

  1. 基于python的国内外研究现状怎么写_如何写国内外研究现状-国内外研究
  2. 山东初二计算机会考,2017山东莱芜初二会考科目时间安排:6月14日
  3. python语法技巧
  4. Python - 文本处理模块
  5. 前端阿里矢量图的使用步骤
  6. CTF初体验:Web18秋名山车神
  7. 启信宝发布植树节产业洞察:超2000家绿色造纸企业,造纸业迭代落后产能
  8. 用户为什么要使用天翼LIVE?
  9. AndroidRecyclerView仿QQ相册功能
  10. 学习java的心得体会_学习java的心得体会范文.doc