swagger筆記

介紹

  • swagger是用來管理api的開源項目
  • 可以用來給團隊共享api文檔和提供測試api接口的工具
  • 文檔和測試工具會隨着代碼的更新而更新
  • 只需要很少的配置就能實現

模塊

  • swagger分爲swagger模塊和swagger-ui模塊 前後端分離

版本選擇

springfox

  • 目前最新版本2.9.2
  • 接受或返回map時 需要藉助bean對象或插件(有缺陷)使接口文檔中包含具體的參數和返回字段
  • api ui是以上下滾動摺疊框分組的形式提供的
  • 不符合國人習慣
  • 不過習慣嗎用着用着就改變了
  • 最重要的是api測試功能輸入沒有記憶功能
  • 重新進入網頁後再次測試相同的接口參數沒有提示功能 這要這麼搞
  • 當你需要同時測試多個接口時這感覺很酸爽 因爲沒有麪包屑 你會迷失在滾動的海洋

xiaoymin

  • 核心還是使用的swagger 把swagger-ui換了 在加了些曾強功能
  • 提供獨立的註解來解決map問題
  • ui符合國人習慣 左右分欄
  • 測試有輸入記憶功能
  • 有麪包屑需要同時請求多個接口也方便
  • 對於我這種把測試接口當ui來用的人來說還是蠻好用的

使用

  • 分文單應用和多應用兩種情況

依賴部分

  • springfox
    <!-- 集成 swagger -->
    <dependency>
    	<groupId>io.springfox</groupId>
    	<artifactId>springfox-swagger2</artifactId>
    	<version>2.9.2</version>
    </dependency>
    <!-- 集成 swagger-ui 需提供ui訪問的服務引用 -->
    <dependency>
    	<groupId>io.springfox</groupId>
    	<artifactId>springfox-swagger-ui</artifactId>
    	<version>2.9.2</version>
    </dependency>
    
  • xiaoymin
    <!-- ui+服務端 -->
    <dependency>
    	<groupId>com.github.xiaoymin</groupId>
    	<artifactId>knife4j-spring-boot-starter</artifactId>
    	<version>2.0.2</version>
    </dependency>
    <!-- 單服務端 -->
     <dependency>
    	<groupId>com.github.xiaoymin</groupId>
    	<artifactId>knife4j-micro-spring-boot-starter</artifactId>
    </dependency>
    
  • 注意事項
    org.springframework.context.ApplicationContextException: Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NoSuchMethodError: com.google.common.collect.FluentIterable.append(Ljava/lang/Iterable;)Lcom/google/common/collect/FluentIterable;
    at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:184) ~[spring-context-5.0.8.RELEASE.jar:5.0.8.RELEASE]
    Caused by: java.lang.NoSuchMethodError: com.google.common.collect.FluentIterable.append(Ljava/lang/Iterable;)Lcom/google/common/collect/FluentIterable;
    

    如果運行時報上面的錯那就是需要引入瓜娃子

    <dependency>
    	<groupId>com.google.guava</groupId>
    	<artifactId>guava</artifactId>
    	<version>29.0-jre</version>
    </dependency>
    

代碼部分

  • 單應用

    • 直接引用依賴 創建個Docket(這名字貌似很牛逼啊)交給spring管理 開啓swagger
    @EnableKnife4j //knife4j獨有 提供增強功能
    @EnableSwagger2
    @Configuration
    @Profile({"dev","test","local","tt"})
    public class SwaggerConfig {
    
        @Bean
        @Order(value = 1)
        public Docket groupRestApi() {
            return new Docket(DocumentationType.SWAGGER_2)
                    .apiInfo(apiInfo())
                    .select()
                .apis(RequestHandlerSelectors.basePackage("com.xiaominfo.swagger.service.user.controller"))
                .paths(PathSelectors.any())
                .build()
                // 用來設置Authorization和Authorization-x用來token訪問
                .securityContexts(Lists.newArrayList(securityContext(),securityContext1()))
                .securitySchemes(Lists.<SecurityScheme>newArrayList(apiKey(),apiKey1()));
        }
    
        private ApiInfo apiInfo(){
            return new ApiInfoBuilder()
                    .title("api文檔")
                    .description("<div style='font-size:14px;color:red;'>api文檔</div>")
                    .termsOfServiceUrl("http://www.shangtian.com/")
                    .contact("[email protected]")
                    .version("1.0")
                    .build();
        }
        
    	 private ApiKey apiKey() {
            return new ApiKey("BearerToken", "Authorization", "header");
        }
        
        private ApiKey apiKey1() {
            return new ApiKey("BearerToken1", "Authorization-x", "header");
        }
    
        private SecurityContext securityContext() {
            return SecurityContext.builder()
                    .securityReferences(defaultAuth())
                    .forPaths(PathSelectors.regex("/.*"))
                    .build();
        }
        private SecurityContext securityContext1() {
            return SecurityContext.builder()
                    .securityReferences(defaultAuth1())
                    .forPaths(PathSelectors.regex("/.*"))
                    .build();
        }
    
        List<SecurityReference> defaultAuth() {
            AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
            AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
            authorizationScopes[0] = authorizationScope;
            return Lists.newArrayList(new SecurityReference("BearerToken", authorizationScopes));
        }
        List<SecurityReference> defaultAuth1() {
            AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
            AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
            authorizationScopes[0] = authorizationScope;
            return Lists.newArrayList(new SecurityReference("BearerToken1", authorizationScopes));
        }
    }
    
  • 多應用

    • 可以在每個應用按照單應用的來

    • 但是這樣一來如果有20個工程或者更多的話 訪問起來這滋味應該相當的爽

    • 要提供api文檔的所有服務都引用swagger模塊

    • 需要提供訪問swagger界面的服務引用swagger-ui模塊 並且提供路由信息 通常爲網關服務

    • 如果是其他服務需要收集路由信息 可以是到網關或註冊中心獲取 獲取廣播採集 再不濟採用錄入方式

    • 步驟爲根據路由信息生成接口請求地址 ->  根據請求地址請求目標服務接口

    • 這樣就解決了需要訪問多個服務的api時需要開多個網站的問題

    • 假如現在有5個服務除了註冊中心其他需要提供api文檔 服務如下

    • 1個註冊中心 1個user服務  1個訂單服務 1個商品服務 1個網關服務(zuul)

    • 註冊中心不用管 user、訂單、商品服務 引入服務端依賴 按單應用的配置走

    • 網關服務引入服務端和ui依賴 配置如下

    @EnableSwagger2
    @Configuration
    @Profile({"dev","test","local","tt"})
    public class SwaggerConfig {
    
        @Bean
        @Order(value = 1)
        public Docket groupRestApi() {
            return new Docket(DocumentationType.SWAGGER_2)
                    .apiInfo(apiInfo());
        }
    
        private ApiInfo apiInfo(){
            return new ApiInfoBuilder()
                    .title("api文檔")
                    .description("<div style='font-size:14px;color:red;'>api文檔</div>")
                    .termsOfServiceUrl("http://www.shangtian.com/")
                    .contact("[email protected]")
                    .version("1.0")
                    .build();
        }
    }
    
    @Component
    @Primary
    @Profile({"dev","test","local","tt"})
    public class SwaggerResourceConfig implements SwaggerResourcesProvider {
    
        Logger logger= LoggerFactory.getLogger(SwaggerResourceConfig.class);
    
    
        @Autowired
        RouteLocator routeLocator;
    
        @Override
        public List<SwaggerResource> get() {
            //獲取所有router
            List<SwaggerResource> resources = new ArrayList<>();
            List<Route> routes = routeLocator.getRoutes();
            logger.info("Route Size:{}",routes.size());
            for (Route route:routes) {
                resources.add(swaggerResource(route.getId(), route.getFullPath().replace("**", "v2/api-docs")));
            }
            return resources;
        }
        private SwaggerResource swaggerResource(String name, String location) {
            logger.info("name:{},location:{}",name,location);
            SwaggerResource swaggerResource = new SwaggerResource();
            swaggerResource.setName(name);
            swaggerResource.setLocation(location);
            swaggerResource.setSwaggerVersion("1.0");
            return swaggerResource;
        }
    }
    
    • 通過上面的配置就可以通過網關訪問user、訂單、商品服務的api文檔了
    • 如果網關服務不是zuul或者沒有網關 可以藉助nginx的反向代理  在實現對應的SwaggerResourceConfig就行了

資料文獻

knife4j項目說明

swagger使用示例

springfox

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章