swagger2 接口排序

      最近在使用swagger2作用在线文档工具,完成后发现在页面上模块和接口的顺序是混乱的。

     swagger 使用的版本信息


            io.springfox
            springfox-swagger2
            2.9.2
        
        
            com.github.xiaoymin
            swagger-bootstrap-ui
            1.8.9
        

     理想的顺序是,模块是开发、二次开发、测试,接口是开始、暂停、继续、结束。项目启动后,接口的显示没有和预计的一样。

swagger2 接口排序_第1张图片

      经过分析发现,接口信息的数据中通过http://127.0.0.1:8080/v2/api-docs接口获取的。在返回数据中,tags对应的是目录节点,paths对应的是各个接口,通过里面的tags里的。如果要进行排序,则返回结里tags和paths都是按照指定的顺序返回的。

      接下来分析源码

springfox.documentation.swagger2.mappers.ServiceModelToSwagger2MapperImpl的mapDocumentation方法:

  public Swagger mapDocumentation(Documentation from) {
        if (from == null) {
            return null;
        } else {
            Swagger swagger = new Swagger();
            swagger.setVendorExtensions(this.vendorExtensionsMapper.mapExtensions(from.getVendorExtensions()));
            swagger.setSchemes(this.mapSchemes(from.getSchemes()));
            // path属性设置
            swagger.setPaths(this.mapApiListings(from.getApiListings()));
            swagger.setHost(from.getHost());
            swagger.setDefinitions(this.modelMapper.modelsFromApiListings(from.getApiListings()));
        
 swagger.setSecurityDefinitions(this.securityMapper.toSecuritySchemeDefinitions(from.getResourceListing()));
            ApiInfo info = this.fromResourceListingInfo(from);
            if (info != null) {
                swagger.setInfo(this.mapApiInfo(info));
            }

            swagger.setBasePath(from.getBasePath());
             // tags 属性设置
            swagger.setTags(this.tagSetToTagList(from.getTags()));
....

 

springfox.documentation.swagger2.mappers.ServiceModelToSwagger2Mapper

//  paths 属性封闭实现方法 
protected Map mapApiListings(Multimap apiListings) {
        Map paths = Maps.newTreeMap();
        Iterator var3 = apiListings.values().iterator();

        while(var3.hasNext()) {
            ApiListing each = (ApiListing)var3.next();
            Iterator var5 = each.getApis().iterator();

            while(var5.hasNext()) {
                ApiDescription api = (ApiDescription)var5.next();
                paths.put(api.getPath(), this.mapOperations(api, Optional.fromNullable(paths.get(api.getPath()))));
            }
        }

        return paths;
    }

//  tags 属性的封装实现方法
   protected List tagSetToTagList(Set set) {
        if (set == null) {
            return null;
        } else {
            List list = new ArrayList(set.size());
            Iterator var3 = set.iterator();

            while(var3.hasNext()) {
                springfox.documentation.service.Tag tag = (springfox.documentation.service.Tag)var3.next();
                list.add(this.mapTag(tag));
            }

            return list;
        }
    }

经过代码跟踪分析,总结如下:

1. 模块的排序是依据tag 的名称进行的,虽然@Api里保留有position属性,但是已经完全弃用。

2.接口的排序也是依据@ApiOperation里value的值进行的,position属性虽然废弃,但是仍可以进行设置取值。

解决方案为依据排序设计规则,重写相应的方法。规则如下:

1.模块的排序,使用tag名称排序,在名称前加上前缀0X-,即在名称就加上"01-"、"02-"。但为了页面展示效果,在排序后把前缀进行处理;

2.接口的排序,使用@ApiOperation的position实现。

 代码实现  

@Api(tags = "01-开发")
@RestController
@RequestMapping("/b")
public class Test3Contoller {


    @ApiOperation(value = "开始",position = 1)
   @ApiImplicitParam(name = "platformNo", value = "平台编号", required = true, dataType = "String", defaultValue = "34020000001320000001")
    @GetMapping(value = "/start")
    public RespData queryCatalog(String platformNo) {
        return RespData.success();
    }
package com.ferry.configer;

import com.google.common.base.Optional;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import io.swagger.models.Operation;
import io.swagger.models.Path;
import io.swagger.models.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import springfox.documentation.builders.BuilderDefaults;
import springfox.documentation.service.ApiDescription;
import springfox.documentation.service.ApiListing;
import springfox.documentation.swagger2.mappers.ServiceModelToSwagger2MapperImpl;
import springfox.documentation.swagger2.mappers.VendorExtensionsMapper;

import java.util.*;


@Primary //同一个接口,可能会有几种不同的实现类,而默认只会采取其中一种的情况下
@Component("ServiceModelToSwagger2Mapper")
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CustomModelToSwaggerMapper extends ServiceModelToSwagger2MapperImpl {
    @Autowired
    private VendorExtensionsMapper vendorExtensionsMapper;


    protected Map mapApiListings(Multimap apiListings) {
        Map paths = Maps.newTreeMap();
        Iterator var3 = apiListings.values().iterator();

        while (var3.hasNext()) {
            ApiListing each = (ApiListing) var3.next();
            List list = each.getApis();
            Iterator var5 = each.getApis().iterator();

            while (var5.hasNext()) {
                ApiDescription api = (ApiDescription) var5.next();
                paths.put(api.getOperations().get(0).getPosition() + "-" + api.getPath(), this.mapOperations(api, Optional.fromNullable(paths.get(api.getPath()))));
            }
        }
        Map paths2 = new LinkedHashMap<>();
        for (String key : paths.keySet()) {
            paths2.put(key.substring(key.indexOf("-") + 1), paths.get(key));
        }
        return paths2;
    }

    private Path mapOperations(ApiDescription api, Optional existingPath) {
        Path path = (Path) existingPath.or(new Path());
        Iterator var4 = BuilderDefaults.nullToEmptyList(api.getOperations()).iterator();

        while (var4.hasNext()) {
            springfox.documentation.service.Operation each = (springfox.documentation.service.Operation) var4.next();
            Operation operation = this.mapOperation(each);
            path.set(each.getMethod().toString().toLowerCase(), operation);
        }

        return path;
    }


    protected Operation mapOperation(springfox.documentation.service.Operation from) {
        if (from == null) {
            return null;
        } else {
            Operation operation = new Operation();
            operation.setSecurity(this.mapAuthorizations(from.getSecurityReferences()));
            operation.setVendorExtensions(this.vendorExtensionsMapper.mapExtensions(from.getVendorExtensions()));
            operation.setDescription(from.getNotes());
            operation.setOperationId(from.getPosition() + from.getUniqueId());
            operation.setResponses(this.mapResponseMessages(from.getResponseMessages()));
            operation.setSchemes(this.stringSetToSchemeList(from.getProtocol()));
            Set set = from.getTags();
            if (set != null) {
                Iterator it= set.iterator();
                Set rset= new HashSet<>();
                while (it.hasNext()){
                    String tagName= it.next();
                    rset.add(tagName.substring(tagName.indexOf("-")+1));
                }
                operation.setTags(new ArrayList(rset));
            } else {
                operation.setTags((List) null);
            }

            operation.setSummary(from.getSummary());
            Set set1 = from.getConsumes();
            if (set1 != null) {
                operation.setConsumes(new ArrayList(set1));
            } else {
                operation.setConsumes((List) null);
            }

            Set set2 = from.getProduces();
            if (set2 != null) {
                operation.setProduces(new ArrayList(set2));
            } else {
                operation.setProduces((List) null);
            }

            operation.setParameters(this.parameterListToParameterList(from.getParameters()));
            if (from.getDeprecated() != null) {
                operation.setDeprecated(Boolean.parseBoolean(from.getDeprecated()));
            }

            return operation;
        }
    }

    @Override
    protected List tagSetToTagList(Set set) {
        List tlist = super.tagSetToTagList(set);
        List result = new LinkedList<>();
        Iterator it = tlist.iterator();
        while (it.hasNext()) {
            Tag tag = it.next();
            Tag tt = new Tag();
            tt.setName(tag.getName().substring(tag.getName().indexOf("-") + 1));
            tt.setDescription(tag.getDescription());
            result.add(tt);
        }
        return result;
    }
}

     重新运行的效果:

                                      swagger2 接口排序_第2张图片

 

 

你可能感兴趣的:(swagger2)