springboot+dubbo整合swagger-ui+swagger-dubbo


場景

在項目開發中我們對dubbo接口通常可以通過junit編寫單頁測試來進行自測,配合spring-boot-starter-test,通常是如下方式:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = XxxApplication.class)
public class XxxServiceTest {
    
    @Autowired
    private XxxService xxxService;

    @Test    
    public void testFunc() throws Exception {
        xxxService.func();
    }
}

這種方式測試單個接口很方便,但有個不足是每次測試單個接口,基本上相當於重啟了項目,當項目很大時運行可能比較耗時。
注:可通過執行整個測試類、或在structure里選中多個方法批量跑單元測試;或者在/src/test/resources/下單獨定義測試需要的配置,這樣能加快啟動時間。

於是想能否項目只啟動一次,然后調各個接口測試。
一個springboot項目啟動好,當定義了controller時,我們可以通過瀏覽器或者postman這樣的http工具調用接口,
那沒有controller接口,只暴露了dubbo服務能否直接調用呢?
答案是肯定的,dubbo從很早的版本2.0.5開始就支持通過telnet命令來進行服務治理。

參考官方文檔:http://dubbo.apache.org/zh/docs/v2.7/user/references/telnet/
比如項目的dubbo配置:

<dubbo:protocol name="dubbo" port="20001" threadpool="fixed" threads="200" />

dubbo端口是10001,通過telnet命令連接:
telnet localhost 20001

連接后,常用命令:
status -l:查看服務狀態,包括服務狀態是否OK、核心線程數、在運行線程數等。

ls:查看接口類列表。

ls -l com.cdfive.xxx.service.XxxService:查看某接口類下所有接口方法。

invoke com.cdfive.xxx.service.XxxService.func({"name":"111","class":"xxx""}:調用某接口方法。

invoke命令讓我們可以調用想測試的某個接口。
這種方式解決了的上面接口測試的問題,即項目啟動1次,然后調想任意想測試的接口。
但它仍有不足是:操作步驟較繁瑣,要先telnet連接,然后invoke調接口,而telnet窗口不像shell里有方便的自動完成功能,
並且接口方法和參數需要提前准備好。

如果有可視化的方式,當啟動好項目能在界面上直接調dubbo接口就更方便了。

swagger和swagger-ui

官方:https://github.com/springfox/springfox/tree/master/springfox-swagger-ui

swagger是一個規范和完整的框架,用於生成、描述、調用和可視化 RESTful 風格的 Web 服務。
在項目中使用swagger提供的@Api@ApiOperation@ApiModel@ApiModelProperty等一系列注解標識在具體的接口和參數上,
然后通過swagger-ui提供的web界面,查看接口文檔、測試接口調用。

集成步驟:

  1. 引入swaggerswagger-ui依賴
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.7.0</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.7.0</version>
</dependency>
  1. 創建swagger配置類
/**
 * @author cdfive
 */
@ConditionalOnProperty(name = "swagger.enable", matchIfMissing = false)
@EnableSwagger2
@Configuration
public class SwaggerConfig {

    @Bean
    public Docket docket() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.cdfive.xxx.controller"))
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("xxx-service")
                .description("xxx-service description")
                .version("0.0.1")
                .build();
    }
}

注:swagger.enable用於區分不同環境(如:開發、測試、生產),在生產環境需要禁用swagger。

  1. 在controller類的接口方法使用swagger注解

如:

@ApiOperation(value="修改用戶密碼", notes="根據用戶id修改密碼")
@ApiImplicitParams({
    @ApiImplicitParam(paramType="query", name = "userId", value = "用戶id", required = true, dataType = "Integer"),
    @ApiImplicitParam(paramType="query", name = "password", value = "舊密碼", required = true, dataType = "String"),
    @ApiImplicitParam(paramType="query", name = "newPassword", value = "新密碼", required = true, dataType = "String")
})
@RequestMapping("/modifyPassword")
public void modifyPassword(@RequestParam(value="userId") Integer userId
        , @RequestParam(value="password") String password, 
        @RequestParam(value="newPassword") String newPassword) {
     ...
}

啟動項目,訪問http://ip:port/swagger-ui.html查看swagger-ui的主頁面。

swagger-dubbo

官方:https://github.com/Sayi/swagger-dubbo/

swagger-dubbo解析項目中的dubbo接口,基於swagger規范生成文檔,然后我們可通過swagger-ui直接調用dubbo接口。

集成步驟:

  1. 引入swagger-dubbo依賴
<dependency>
    <groupId>com.deepoove</groupId>
    <artifactId>swagger-dubbo</artifactId>
    <version>2.0.1</version>
</dependency>
  1. 創建swagger-dubbo配置類
@ConditionalOnProperty(name = "swagger.dubbo.enable", matchIfMissing = false)
@EnableDubboSwagger
@Configuration
public class SwaggerDubboConfig {
    ...
}

注:swagger.dubbo.enable用於區分不同環境(如:開發、測試、生產),在生產環境需要禁用swagger-dubbo。

啟動項目,訪問http://ip:port/swagger-dubbo/api-docs查看swagger-dubbo解析生成的文檔。

訪問http://ip:port/swagger-ui.html,發現頂部的下拉列表里只有1個選項:default(/v2/api-docs),
默認swagger-ui只展示了controller的接口,swagger-dubbo解析生成的文檔打開是一個json串,並沒有展示在swagger-ui上。

注:此時雖然swagger-ui頁面沒有展示,但可以通過http rest接口http://ip:port/h/com.xxx.XxService/xxxMethod調用dubbo接口。

運行官方的dubbo-provider-springboot示例,發現頂部的下拉列表變成了輸入框,當啟用跨域訪問后就能看到解析除的dubbo接口。
在工程的/src/main/resources/static/distv2的目錄下,有定制的swagger-ui相關文件。
但如果每個項目中都加入這些前端相關的文件有點麻煩,希望在官方默認的swagger-ui頁面中就能看到項目中的dubbo接口。

springfox-swagger-ui的官方介紹里有一句話:
Adds a JSON endpoint /swagger-resources which lists all of the swagger resources and versions configured for a given application.

在啟動項目的日志里也能看到:
Mapped "{[/swagger-resources/configuration/ui]}" onto public org.springframework.http.ResponseEntity<springfox.documentation.swagger.web.UiConfiguration> springfox.documentation.swagger.web.ApiResourceController.uiConfiguration()
Mapped "{[/swagger-resources/configuration/security]}" onto public org.springframework.http.ResponseEntity<springfox.documentation.swagger.web.SecurityConfiguration> springfox.documentation.swagger.web.ApiResourceController.securityConfiguration()
Mapped "{[/swagger-resources]}" onto public org.springframework.http.ResponseEntity<java.util.List<springfox.documentation.swagger.web.SwaggerResource>> springfox.documentation.swagger.web.ApiResourceController.swaggerResources()
springfox.documentation.swagger.web.ApiResourceController暴露了3個地址,其中/swagger-resources就是swagger-ui頁面頂部下拉列表的數據源。
打開該controller的源碼,發現是通過SwaggerResourcesProvider接口實現的,該接口繼承了guava的Supplier接口。
查看接口只有1個實現類InMemorySwaggerResourcesProvider,里面的get方法就是獲取數據源。

swagger-dubbo解析的dubbo接口已生成了數據源,通過/swagger-dubbo/api-docs暴露,因此對SwaggerDubboConfig做一些改造:

/**
 * @author cdfive
 */
@ConditionalOnProperty(name = "swagger.dubbo.enable", matchIfMissing = false)
@EnableDubboSwagger
@Configuration
public class SwaggerDubboConfig {

    @Primary
    @Bean
    public SwaggerResourcesProvider swaggerResourcesProvider(Environment environment, DocumentationCache documentationCache) {
        return new CustormSwaggerResourcesProvider(environment, documentationCache);
    }

    static class CustormSwaggerResourcesProvider extends InMemorySwaggerResourcesProvider {

        public CustormSwaggerResourcesProvider(Environment environment, DocumentationCache documentationCache) {
            super(environment, documentationCache);
        }

        @Override
        public List<SwaggerResource> get() {
            List<SwaggerResource> swaggerResources = super.get();

            SwaggerResource swaggerDubboResource = new SwaggerResource();
            swaggerDubboResource.setName("dubbo");
            swaggerDubboResource.setLocation("/swagger-dubbo/api-docs");
            swaggerDubboResource.setSwaggerVersion("2.0");
            swaggerResources.add(swaggerDubboResource);
            return swaggerResources;
        }
    }
}

思路是自定義CustormSwaggerResourcesProvider繼承InMemorySwaggerResourcesProvider,里面將dubbo對應的/swagger-dubbo/api-docs
數據源添加進去,通過@Primary注解標識該實現類優先使用。

改造后重新啟動項目,訪問http://ip:port/swagger-ui.html頁面,頂部下拉列表就有了2個選項:
default(/v2/api-docs)和dubbo(/swagger-dubbo/api-docs),切換到dubbo后項目中的dubbo接口在界面展示了出來,並且輸入參數值即可調用。

總結

  • 項目可能經常需要在本地對dubbo接口進行自測,通常使用junit單元測試,結合spring-boot-test,如果項目很大啟動測試可能很耗時。
  • 先啟動好項目,通過telnet連接dubbo服務,通過invoke命令能直接調用接口測試,但需要在命令里准備好接口和參數,不能可視化。
  • 通過引入swagger-ui並結合swagger-dubbo能直接在界面調用dubbo接口,方便自測、測試和調試,能在一定程度上幫助提高開發效率。

參考


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM