zoukankan      html  css  js  c++  java
  • 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接口,方便自测、测试和调试,能在一定程度上帮助提高开发效率。

    参考

  • 相关阅读:
    CSS定位
    使用开源框架进行get,post提交
    使用httpclient框架分别用post,get方式提交
    C++ const_cast
    C++ 类继承 常量对象调用函数
    C++ 类继承 子类调用父类
    C++ explicit关键字
    C++ class入门
    C#检测耗时操作
    面向对象编程入门
  • 原文地址:https://www.cnblogs.com/cdfive2018/p/14330299.html
Copyright © 2011-2022 走看看