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-editor、swagger-ui、swagger-Specification、swagger-Swagger Codegen
几个项目,每个项目的作用、使用在官网都有详细介绍和帮助文档,可自行查阅。本文要点摘要
1. swagger-editor
swagger-editor ?
swagger-editor
可以理解为是一个以OpenAPI规范来编写初始化文档一种预定义文档编辑器,其支持的类型主要有json、yaml
两种文档格式,如果对于这两种文档格式有不了解的可以百度搜索,有很多相关的介绍和教程。我们将编辑好的预定义文档粘贴如swagger-editor中,便可以利用swagger-codegen来生成相应的服务端或者客户端代码。
一些有用的链接(强烈推荐)
熟悉以上推荐的两个教程以后,下面的工作就是手到擒来的事儿了。下面我假设您已经对swagger预定义文档和yaml有一定程度了解,至少能读懂相应代码,了解其意义了。
面板分为两个区域,左边是基于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时生成的接口代码是集成Swagger
和SpringBoot
的,目前Java开发API大多利用SrpingBoot
来进行开发,若想了解其区别可分别选择java和spring下载生成的服务端代码。下载完代码解压后如图所示:
可以删除.swagger-codgen
相关的东西,只保留pom.xml
和src
目录下的内容
下面我们使用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
除了以上几个类之外,swagger-codgen还生成了一些处理异常的类,这个大家自己查看吧。!
总结
其实这个东西就是帮助我们了解Swagger框架,帮助我们快速入门和开发,接口都可以由预定义文档结合swagger-editor(实际代码生成是用swagger-codgen)来自动生成,我们只需要塞入相应的业务逻辑便可。我们理解了swagger-editor这个东西以后至少解决了有两个问题:
1:如何使用swagger来自动生成接口文档和接口
2:如何在项目中集成swagger(无论什么语言,无论什么框架,只要在其支持的基础之上)–只需要选择相应的客户端/客户端代码便可,swagger-codgen会自动集成,然后我们再基于其代码来集成便可,下次便不用费这么多功夫来解决集成的问题了。