Java项目使用Swagger开发包含文档的API接口

Swagger ?

  • 什么是Swagger?官网首页如下介绍
    Swagger is the world’s largest framework of API developer tools for the OpenAPI Specification(OAS), enabling development across the entire API lifecycle, from design and documentation, to test and deployment. (Swagger是世界上最大的基于OAS规范的API开发工具集框架,允许开发者贯穿整个API生命周期,从设计到文档,测试至部署)
    Swagger项目下主要包含了有swagger-editor、swagger-ui、swagger-Specification、swagger-Swagger Codegen几个项目,每个项目的作用、使用在官网都有详细介绍和帮助文档,可自行查阅。

本文要点摘要

  1. 简单介绍swagger-editor
  2. 使用swagger-editor和预定义的文档规范生成相应的Java服务端代码。并逐一介绍生成的代码。

1. swagger-editor

  • swagger-editor ?
    swagger-editor可以理解为是一个以OpenAPI规范来编写初始化文档一种预定义文档编辑器,其支持的类型主要有json、yaml两种文档格式,如果对于这两种文档格式有不了解的可以百度搜索,有很多相关的介绍和教程。我们将编辑好的预定义文档粘贴如swagger-editor中,便可以利用swagger-codegen来生成相应的服务端或者客户端代码。

  • 一些有用的链接(强烈推荐)

    1. swagger 预定义文档的编写详细介绍,参考1:swagger从入门到精通
    2. 阮一峰老师的yaml的基本语法,参考2:YAML 语言教程

    熟悉以上推荐的两个教程以后,下面的工作就是手到擒来的事儿了。下面我假设您已经对swagger预定义文档和yaml有一定程度了解,至少能读懂相应代码,了解其意义了。

  • swagger-editor图解
    这里写图片描述

    面板分为两个区域,左边是基于OpenAPI规范的预定义文档,右边是根据预定义文档生成的API文档预览,顶上工具栏部分为一些功能,可以上传本地定义好的文档,将其他类型文档转换为YAML文档,根据文档生成各种语言和框架的服务端和客户端代码,但是官网的在线版本有一个bug,如下所示
    这里写图片描述
    具体含义大致是因为混用https和http导致请求被锁定,无法完成代码生成的工作,所以我们使用离线版本,离线版本的安装运行请参照,参考3:swagger-editor离线版下载及使用说明
    文档中下载时使用的时wget链接为

    wget https://github.com/swagger-api/swagger-editor/releases/download/v2.10.4/swagger-editor.zip

    在linux上,直接复制到命令行便可运行,当在windows上操作时直接将链接地址https://github.com/swagger-api/swagger-editor/releases/download/v2.10.4/swagger-editor.zip复制到浏览器便可以下载,下载后解压,然后按照说明进行相应操作便可。启动后界面和在线版一样。

例子使用的预定义文档

swagger: '2.0'
info:
  version: 1.0.0
  title: Simple API
  description: A simple API to learn how to write OpenAPI Specification
schemes:
  - https
host: simple.api
basePath: /openapi101
paths:
  /persons:
    get:
      summary: get a person by username
      description: get a person
      parameters:
      - name: username
        in: query
        description: a user's name
        required: true
        type: string
        format: string
      responses:
        '200':
          description: a person
          schema:
            type: object
            items:
              properties:
                username:
                  type: string
                address:
                  type: string
                birthday:
                  type: string

该文档定义了一个名/persons的接口,其访问地址为:https://simple.api/openapi101/persons?username=定义类get方法,该方法需要一个string类型的参数,该接口返回200时返回一个对象,对象里包含了person的详细信息。
将以上内容输入swagger-editor以后,会在右边生成文档预览如下图所示:
这里写图片描述

然后我们选择要生成的接口代码类型generate server - spring生成java接口我们选择spring而不选择java语言,选择spring时生成的接口代码是集成SwaggerSpringBoot的,目前Java开发API大多利用SrpingBoot来进行开发,若想了解其区别可分别选择java和spring下载生成的服务端代码。下载完代码解压后如图所示:
这里写图片描述
可以删除.swagger-codgen相关的东西,只保留pom.xmlsrc目录下的内容
下面我们使用maven将项目打包如图所示
这里写图片描述
打包成功以后进入target目录运行生成的jar包
这里写图片描述
等到项目启动成功之后访问:http://localhost:8081/openapi101/(因为我启动http-server时占用了8080端口,所以已经提前将src/main/resource/application.properties中的server.port改为8081)效果如图所示
这里写图片描述
我们的第一个基于swagger和spring的接口便完成了。后面我们分析代码

2. 生成代码分析

  • 生成代码结构
    这里写图片描述

Springboot和Swagger集成以及配置:Swagger2SpringBoot.java

import springfox.documentation.swagger2.annotations.EnableSwagger2;

@SpringBootApplication
@EnableSwagger2
@ComponentScan(basePackages = { "io.swagger", "io.swagger.api" })
public class Swagger2SpringBoot implements CommandLineRunner {

    @Override
    public void run(String... arg0) throws Exception {
        if (arg0.length > 0 && arg0[0].equals("exitcode")) {
            throw new ExitException();
        }
    }

    public static void main(String[] args) throws Exception {
        new SpringApplication(Swagger2SpringBoot.class).run(args);
    }

    class ExitException extends RuntimeException implements ExitCodeGenerator {
        private static final long serialVersionUID = 1L;

        @Override
        public int getExitCode() {
            return 10;
        }

    }
}

该类的主要作用是SpringBoot的启动类,除了SpringBoot的注解之外,添加了Swagger2的注解@EnableSwagger2以提供对Swagger的支持。

日期转换类 RFC3339DateFormat.java


public class RFC3339DateFormat extends ISO8601DateFormat {

  // Same as ISO8601DateFormat but serializing milliseconds.
  @Override
  public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) {
    String value = ISO8601Utils.format(date, true);
    toAppendTo.append(value);
    return toAppendTo;
  }

}

文档页面跳转 configuration/HomeController.class ,具体作用注释和代码已经写得很明白了

/**
 * Home redirection to swagger api documentation 
 */
@Controller
public class HomeController {
    @RequestMapping(value = "/")
    public String index() {
        System.out.println("swagger-ui.html");
        return "redirect:swagger-ui.html";
    }
}

Swagger文档配置 configuration/SwaggerDocumentationConifg.java

// 该注解是swagger-codgen在生成代码时自动加入的,没有实际用于,主要是用于标记,标识区分swagger自动生成的类和后期开发中开发者写得类,可以删除不用。
@javax.annotation.Generated(value = "io.swagger.codegen.languages.SpringCodegen", date = "2017-10-14T15:20:48.971Z")

@Configuration
public class SwaggerDocumentationConfig {
    //里面的字段有没有很熟悉的感觉?这就是我们预定义文档中相应的值,用于生成文档的,设置文档的基本信息。
    ApiInfo apiInfo() {
        return new ApiInfoBuilder()
            .title("Simple API")
            .description("A simple API to learn how to write OpenAPI Specification")
            .license("")
            .licenseUrl("http://unlicense.org")
            .termsOfServiceUrl("")
            .version("1.0.0")
            .contact(new Contact("","", ""))
            .build();
    }

    //设置文档类型,载入文档基本信息
    @Bean
    public Docket customImplementation(){
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                    .apis(RequestHandlerSelectors.basePackage("io.swagger.api"))
                    .build()
                .directModelSubstitute(org.joda.time.LocalDate.class, java.sql.Date.class)
                .directModelSubstitute(org.joda.time.DateTime.class, java.util.Date.class)
                .apiInfo(apiInfo());
    }

}

跨域处理和请求方法处理的类api/ApiOriginFilter.java 该类实现了java.servlet.Filter接口

public class ApiOriginFilter implements javax.servlet.Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        HttpServletResponse res = (HttpServletResponse) response;
        //设置跨域信息和允许的请求方法等请求头信息。
        res.addHeader("Access-Control-Allow-Origin", "*");
        res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
        res.addHeader("Access-Control-Allow-Headers", "Content-Type");
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
}

最后两个需要介绍的是我们要的API api/PersonsApi.java 接口和其实现 api/PersonsApiController.java

//这是我们在预定于文档中指定的person的pai接口
@javax.annotation.Generated(value = "io.swagger.codegen.languages.SpringCodegen", date = "2017-10-14T15:20:48.971Z")
//该注解的描述是我们在预定于的yaml文档中编写的可以参照上面的yaml文档来理解以下的注释及其含义,里面设置到的spring相关的东西就不在赘述了。
@Api(value = "persons", description = "the persons API")
public interface PersonsApi {

    @ApiOperation(value = "get a person by username", notes = "get a person", response = Object.class, tags={  })
    @ApiResponses(value = { 
        @ApiResponse(code = 200, message = "a person", response = Object.class) })

    @RequestMapping(value = "/persons",
        method = RequestMethod.GET)
    ResponseEntity<Object> personsGet( @NotNull@ApiParam(value = "a user's name", required = true) @RequestParam(value = "username", required = true) String username);

}

//这是person api的实现
@javax.annotation.Generated(value = "io.swagger.codegen.languages.SpringCodegen", date = "2017-10-14T15:20:48.971Z")

@Controller
public class PersonsApiController implements PersonsApi {



    public ResponseEntity<Object> personsGet( @NotNull@ApiParam(value = "a user's name", required = true) @RequestParam(value = "username", required = true) String username) {
        // !ResponseEntity有多个构造方法,每个构造方法及其含义请参考其API文档。都写得很简单。在此也不在说了。可以利用其提供的构造方法来返回接口调用所需要的数据
        return new ResponseEntity<Object>(HttpStatus.OK);
    }

}

除了以上几个类之外,swagger-codgen还生成了一些处理异常的类,这个大家自己查看吧。!

总结

其实这个东西就是帮助我们了解Swagger框架,帮助我们快速入门和开发,接口都可以由预定义文档结合swagger-editor(实际代码生成是用swagger-codgen)来自动生成,我们只需要塞入相应的业务逻辑便可。我们理解了swagger-editor这个东西以后至少解决了有两个问题:
1:如何使用swagger来自动生成接口文档和接口
2:如何在项目中集成swagger(无论什么语言,无论什么框架,只要在其支持的基础之上)–只需要选择相应的客户端/客户端代码便可,swagger-codgen会自动集成,然后我们再基于其代码来集成便可,下次便不用费这么多功夫来解决集成的问题了。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值