使用 SwaggerUI 生成接口文档(配示例)

在项目开发中,接口文档一直是个头疼的问题。本来项目开发时间就紧张,还需要另外写文档给调用方看,但是不写又不行,无法沟通,写了还要随着项目迭代一直更新,费时费力。

那有没有工具能够识别我们的代码自动生成接口文档呢?答案是有的。这篇文章就介绍市面上常用的接口文档生成框架:Swagger-UI 的简单使用。

讲 Swagger-UI 前需先了解下 Swagger,https://swagger.io/,Swagger 是一个常用的接口工具。

官方给自己的定义是:THE WORLD’S MOST POPULAR API TOOLING。

Swagger-UI 只是其中的一块,主要是通过代码里的注解,生成在线的接口文档界面,以便沟通。

除了 Swagger-UI,Swagger 还有 Swagger Editor(在线编辑接口文档)和 Swagger Codegen(根据接口文档生成代码,可以生成各种语言的代码,厉害吧!)。

先看效果

首先来两张高清大图,看看生成的效果。

生成效果

生成效果

整合接入步骤

(以一个普通的 SpringMVC 项目为例)

加入必须的依赖包(maven)

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.8.0</version>
</dependency>

代码方式添加相关配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package com.zhangzw.swagger.spring;

import io.swagger.annotations.ApiOperation;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletResponse;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.builders.ResponseMessageBuilder;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ResponseMessage;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@ComponentScan("com.zhangzw.swagger")
@EnableWebMvc
@EnableSwagger2
public class SpringConfiguration extends WebMvcConfigurerAdapter {

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
super.addResourceHandlers(registry);
registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
registry.addResourceHandler("/swagger/**").addResourceLocations("classpath:/swagger/");
}

@Bean
public Docket docket() {
List<ResponseMessage> responseMessages = new ArrayList<ResponseMessage>();
responseMessages.add(new ResponseMessageBuilder().code(HttpServletResponse.SC_OK).message("操作成功").build());
responseMessages.add(new ResponseMessageBuilder().code(HttpServletResponse.SC_NOT_FOUND).message("资源不存在").build());
responseMessages.add(new ResponseMessageBuilder().code(HttpServletResponse.SC_INTERNAL_SERVER_ERROR).message("服务器异常").build());

return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.useDefaultResponseMessages(false)
.globalResponseMessage(RequestMethod.GET, responseMessages)
.globalResponseMessage(RequestMethod.POST, responseMessages)
.globalResponseMessage(RequestMethod.DELETE, responseMessages)
.select()
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.paths(PathSelectors.any())
.build();
}

private ApiInfo apiInfo() {
return new ApiInfoBuilder().title("测试项目").version("1.0.0").description("这是项目描述").build();
}
}

修改 Controller 接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.zhangzw.swagger.web;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@Api(tags="订单模块") // Swagger-UI 描述在类上面,可以做分组。
public class OrderController {

@RequestMapping(method = RequestMethod.GET, value = "/order/orderInfo/{orderId:.+}")
@ResponseBody
@ApiOperation(value = "获取订单") // 让 Swagger-UI 解析这个接口。
public OrderInfo getOrderInfo(String orderId) {
return new OrderInfo();
}

@RequestMapping(method = RequestMethod.DELETE, value = "/order/delOrder.do")
@ResponseBody
@ApiOperation(value = "删除订单")
public BaseResponse delOrder(String orderId) {
return new BaseResponse();
}

@RequestMapping(method = RequestMethod.POST, value = "/order/queryOrderList.do")
@ResponseBody
@ApiOperation(value = "查询订单列表")
public QueryOrderListResponse getOrderInfo(@RequestBody QueryOrderListRequest req) {
return new QueryOrderListResponse();
}
}

如果接口使用 DTO 接收和返回数据,可以在 DTO 上加入注解,如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package com.zhangzw.swagger.web;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

import java.util.Date;

@ApiModel(description = "订单实体")
public class OrderInfo {

@ApiModelProperty(value = "订单号", example = "201701011234", notes = "订单的编号")
private String orderNo;

@ApiModelProperty("创建时间")
private Date createTime;

@ApiModelProperty("中介公司编码")
private String agencyCode;

@ApiModelProperty("中介公司名称")
private String agencyName;

@ApiModelProperty("门店 ID")
private String storeId;

@ApiModelProperty("门店名称")
private String storeName;

public String getOrderNo() {
return orderNo;
}

public void setOrderNo(String orderNo) {
this.orderNo = orderNo;
}

public Date getCreateTime() {
return createTime;
}

public void setCreateTime(Date createTime) {
this.createTime = createTime;
}

public String getAgencyCode() {
return agencyCode;
}

public void setAgencyCode(String agencyCode) {
this.agencyCode = agencyCode;
}

public String getAgencyName() {
return agencyName;
}

public void setAgencyName(String agencyName) {
this.agencyName = agencyName;
}

public String getStoreId() {
return storeId;
}

public void setStoreId(String storeId) {
this.storeId = storeId;
}

public String getStoreName() {
return storeName;
}

public void setStoreName(String storeName) {
this.storeName = storeName;
}

}

结束

这样就可以了,是不是很简单?只需要加入一些注解,文档就生成了,对代码侵入很小,保证了文档与代码的同步,最重要的是效率高啊!^_^

相关链接

Swagger-UI 官网

官方 DEMO