分享

Micro Service工具集之Swagger:可测试的样式化API文档

 WindySky 2017-09-14
     在我之前的一篇博文中,介绍了Yammer开发团队贡献的开源微服务开发框架DropWizard(http://ningandjiao./blog/1766498),有了服务之后,开发者最关心的事情是什么呢? 就是有人用你的服务。而开发者使用一个服务之前,首先需要知道的是该服务的API,目前几乎所有的开放平台都是把API以文档的形式放在网站上,如下:




不知道有没有开发人员和我一样,有时对一些API说明的理解比较模糊,总想着能直接验证一下自己的理解就好了,而不是需要去项目写测试代码来验证自己的想法。即API文档应具备直接执行能力。 Swagger就是这样的一个利器,其实,Swagger本身的目标比上面描述的要大很多:“Swagger is a specification and complete framework implementation for describing, producing, consuming, and visualizing RESTful web services. ”。但是,本文中只想聊聊如何通过Swagger为已有项目的生成具备执行能力的样式化API文档。

为已存在的项目添加Swagger(以DropWizard为例)
首先,为项目引入Swagger依赖包
Gradle代码  收藏代码
  1. 'com.wordnik:swagger-jaxrs_2.9.1:1.3.0'  

然后,把Swagger加入DropWizard的Service中:
Java代码  收藏代码
  1. private void initSwaggerConfig(Environment environment) {  
  2.         // Swagger Resource  
  3.         environment.addResource(new ApiListingResourceJSON());  
  4.   
  5.         // Swagger providers  
  6.         environment.addProvider(new ApiDeclarationProvider());  
  7.         environment.addProvider(new ResourceListingProvider());  
  8.   
  9.         // Swagger Scanner, which finds all the resources for @Api Annotations  
  10.         ScannerFactory.setScanner(new DefaultJaxrsScanner());  
  11.   
  12.         // Add the reader, which scans the resources and extracts the resource information  
  13.         ClassReaders.setReader(new DefaultJaxrsApiReader());  
  14.   
  15.         //Config API information. this information will show on the Swagger UI page  
  16.         SwaggerConfig config = ConfigFactory.config();  
  17.         config.setApiVersion("0.1");  
  18.         config.setApiPath("/api/api-docs"); //Swagger UI 默认把API信息显示在base_path/api-docs下  
  19.         config.setBasePath("http://localhost:9090/api");  
  20.         config.setInfo(Option.apply(new ApiInfo("DropWizard Demo Swagger UI",  
  21.                 "This is just a demo to show how to integrate Swagger UI with a dropwizard project.",  
  22.                 null,  
  23.                 "xianlinbox@gmail.com",  
  24.                 null,  
  25.                 null)));  
  26.     }  

接着,给开放API的Resource类加上API Annotation,这样上一步配置的Scanner就能够扫描到该Resource开放的API了。
Java代码  收藏代码
  1. @Path("/helloWorld")  
  2. @Api(value = "/helloWorld", description = "Greeting API", position = 1)  
  3. @Produces(APPLICATION_JSON)  
  4. public class HelloWorldResource {  
  5.     private final String template;  
  6.     private final String defaultName;  
  7.     private final AtomicLong counter;  
  8.   
  9.     public HelloWorldResource(String template, String defaultName) {  
  10.         this.template = template;  
  11.         this.defaultName = defaultName;  
  12.         this.counter = new AtomicLong();  
  13.     }  
  14.   
  15.     @GET  
  16.     @Path("/{name}")  
  17.     @ApiOperation(value = "Greeting by Name",  
  18.             notes = "Say hello to the people",  
  19.             response = SayingRepresentation.class,  
  20.             position = 0)  
  21.     @ApiResponses(value = {  
  22.             @ApiResponse(code = 400, message = "No Name Provided")  
  23.     })  
  24.     @Produces(APPLICATION_JSON)  
  25.     @Timed  
  26.     public SayingRepresentation sayHello(@ApiParam(value = "name for greeting", required = true) @PathParam("name") String name) {  
  27.         return new SayingRepresentation(counter.incrementAndGet(), String.format(template, name != null ? name : defaultName))  
  28.                 ;  
  29.     }  
  30. }  

在Swagger Annotation中:
  • @API表示一个开放的API,可以通过description简要描述该API的功能。
  • 在一个@API下,可有多个@ApiOperation,表示针对该API的CRUD操作。在ApiOperation Annotation中可以通过value,notes描述该操作的作用,response描述正常情况下该请求的返回对象类型。
  • 在一个ApiOperation下,可以通过ApiResponses描述该API操作可能出现的异常情况。
  • @ApiParam用于描述该API操作接受的参数类型

再接着,为项目的Model对象添加Swagger Annotation,这样Swagger Scanner可以获取更多关于Model对象的信息。
Java代码  收藏代码
  1. @ApiModel(value = "A SayingRepresentation is a representation of greeting")  
  2. @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)  
  3. public class SayingRepresentation {  
  4.     private long id;  
  5.     @ApiModelProperty(value = "greeting content", required = true)  
  6.     private String content;  
  7.   
  8.     public SayingRepresentation(long id, String content) {  
  9.         this.id = id;  
  10.         this.content = content;  
  11.     }  
  12.   
  13.     public long getId() {  
  14.         return id;  
  15.     }  
  16.   
  17.     public String getContent() {  
  18.         return content;  
  19.     }  
  20. }  

通过上面的步骤,项目已经具备了提供Swagger格式的API信息的能力,接下来,我们把这些信息和Swagger UI集成,以非常美观,实用的方式把这些API信息展示出来。

和Swagger UI的集成
首先,从github(https://github.com/wordnik/swagger-ui)上下载Swagger-UI, 把该项目dist目录下的内容拷贝到项目的resources的目录assets下。

然后,修改index.html, 把Swagger UI对象中的URL替换为自己的API路径。
Javascript代码  收藏代码
  1. window.swaggerUi = new SwaggerUi({  
  2.      url: "/api/api-docs",  
  3.      dom_id: "swagger-ui-container",  

最后,为了能访问到该页面,还需要在Service的Initialize方法中,添加AssetsBundle,
Java代码  收藏代码
  1. public void initialize(Bootstrap<HelloWorldConfiguration> bootstrap) {  
  2.         //指定配置文件的名字  
  3.         bootstrap.setName("helloWorld");  
  4.         bootstrap.addBundle(new AssetsBundle("/assets", "/", "index.html"));  
  5.     }  

最后的效果图:




    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多