Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。总体目标是使客户端和文件系统作为服务器以同样的速度来更新。文件的方法,参数和模型紧密集成到服务器端的代码,允许API来始终保持同步。
Swagger2 集成
1. 依赖
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-bean-validators</artifactId>
<version>2.9.2</version>
</dependency>
2. 配置类
package com.zjw.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class Swagger2Config {
@Bean
public Docket buildDocket() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(buildApiInf()) // 将api的元信息设置为包含在json resourcelisting响应中
// .host("127.0.0.1:8080") //设置ip和端口,或者域名
.select() // 启动用于api选择的生成器
// .apis(RequestHandlerSelectors.any())
.apis(RequestHandlerSelectors.basePackage("com.zjw.controller")) // 指定controller路径
.paths(PathSelectors.any())
.build();
}
private ApiInfo buildApiInf() {
Contact contact = new Contact("筑梦之人", "https://www.zjwblog.com/", "cn.zjwblog@gmail.com");
return new ApiInfoBuilder()
.title("员工货物网上管理系统") // 文档标题
.description("员工货物网上管理系统用于简化公司工作流程,公司员工只需要进行线上申报和记录即可完成相关工作,此接口文档为系统前后端工作交接文档。")//文档描述
.contact(contact )// 联系人
.version("v1.0") // 版本号
.license("The Apache License, Version 2.0") // 更新此API的许可证信息
//.licenseUrl("") // 更新此API的许可证Url
//.termsOfServiceUrl("") // 更新服务条款URL
.build();
}
}
3. 在模型类中使用 Swagger 注解
package com.zjw.entity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 电视机实体
*/
@ApiModel(value = "Television", description = "电视机实体")
@Entity
@Table(name = "television")
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Television implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)//指定主键生成的方式,AUTO 指定 H2 数据库主键自动增长
@Column(name = "tv_id")
@ApiModelProperty(value = "电视ID,主键字段,采用自增", name = "tvId", dataType = "Integer", required = false, example = "1", hidden = false)
private Integer tvId; // 电视机Id
@ApiModelProperty(value = "电视机名称", name = "tvName", dataType = "String", required = false, example = "华为荣耀智慧屏S400", hidden = false)
@Column(name = "tv_name")
private String tvName; // 电视名称
@ApiModelProperty(value = "电视机价格", name = "tvPrice", dataType = "Float", required = false, example = "5999", hidden = false)
@Column(name = "tv_price")
private Float tvPrice; // 电视价格
@ApiModelProperty(value = "电视机生产日期", name = "dateProduction", dataType = "Date", required = false, example = "2019-11-13T02:30:00.000+0800", hidden = false)
@Column(name = "date_production")
private Date dateProduction; // 生产日期
}
4. 在 Controller 中使用 Swagger 注解
package com.zjw.controller;
import com.zjw.entity.Television;
import com.zjw.result.Result;
import com.zjw.result.ResultCode;
import com.zjw.service.TelevisionService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping(path = "/tv")
@Api(tags = {"电视机相关业务组"}, description = "电视机相关业务组接口描述信息.")
public class TVController {
private static final Logger logger = LoggerFactory.getLogger(TVController.class);
@Autowired
private TelevisionService televisionService;
@GetMapping("")
@ApiOperation(value = "获取所有电视机信息", notes = "获取所有电视机业务信息,正在调试中...", httpMethod = "GET")
public Result getAll() {
List<Television> televisions = null;
try {
televisions = televisionService.getAll();
} catch (Exception e) {
logger.error("查询失败: {}", e.getMessage());
}
return Result.success(televisions);
}
@GetMapping("/page")
@ApiOperation(value = "根据根据page(0开始)和size,按ID排序分页获取电视机数据", notes = "需要再调试!", httpMethod = "GET")
@ApiImplicitParams({
@ApiImplicitParam(name = "page", value = "页码", example = "0", required = true, dataType = "int", paramType = "query"),
@ApiImplicitParam(name = "size", value = "每页大小", example = "5", required = true, dataType = "int", paramType = "query")
})
public Result getAllWithPageable(
@RequestParam(name = "page", required = false) Integer page,
@RequestParam(name = "size", required = false) Integer size
) {
Page<Television> televisions = null;
try {
televisions = televisionService.getAllWithPageable(page, size);
} catch (Exception e) {
logger.error("查询失败: {}", e.getMessage());
}
return Result.success(televisions);
}
@GetMapping("{tvId}")
@ApiOperation(value = "根据tvId获取电视机信息", notes = "tvId必传", httpMethod = "GET")
@ApiImplicitParam(name = "tvId", value = "电视机id", example = "1", required = true, dataType = "int", paramType = "path", defaultValue = "2")
public Result getById(@PathVariable("tvId") Integer tvId) {
Television tv = null;
try {
tv = televisionService.getById(tvId);
} catch (Exception e) {
logger.error("查询失败: {}", e.getMessage());
}
return Result.success(tv);
}
@PostMapping("")
@ApiOperation(value = "修改电视机信息,要求tvId不能为空", notes = "正在调试中...", httpMethod = "POST")
public Result update(@RequestBody Television tv) {
try {
televisionService.saveOrUpdate(tv);
return Result.success(tv);
} catch (Exception e) {
logger.error("查询失败: {}", e.getMessage());
}
return Result.failure(ResultCode.PARAM_NOT_COMPLETE);
}
@PutMapping("")
@ApiOperation(value = "保存电视机信息,要求tvId为空", notes = "正在调试中...", httpMethod = "PUT")
public Result save(@RequestBody Television tv) {
try {
televisionService.saveOrUpdate(tv);
return Result.success(tv);
} catch (Exception e) {
logger.error("查询失败: {}", e.getMessage());
}
return Result.failure(ResultCode.PARAM_NOT_COMPLETE);
}
@DeleteMapping("{tvId}")
@ApiOperation(value = "根据tvId删除电视机信息", notes = "正在调试中...", httpMethod = "DELETE")
@ApiImplicitParam(name = "tvId", value = "电视机id", example = "1", required = true, dataType = "int", paramType = "path", defaultValue = "3")
public Result delete(@PathVariable("tvId") Integer tvId) {
try {
televisionService.deleteById(tvId);
return Result.success(tvId);
} catch (Exception e) {
logger.error("查询失败: {}", e.getMessage());
}
return Result.failure(ResultCode.PARAM_NOT_COMPLETE);
}
}
Swagger2常用Annotation
-
@Api: 用于类,表示标识这个类是swagger的资源.
-
@ApiOperation: 用于方法,表示一个http请求的操作
-
@ApiParam: 用于方法、参数、字段说明;表示对参数的添加元数据
-
@ApiModel: 用于类,表示对类进行说明,用于参数用实体类接受
-
@ApiModelProperty: 用于方法、字段,表示对model属性的说明或者数据操作更改
-
@ApiIgnore: 用于类、方法、方法参数,表示这个方法或者类被忽略,不在swagger-ui.html上显示
-
@ApiImplicitParam: 用于方法,表示单独的请求参数
-
@ApiImplicitParams: 用于方法,包含多个 @ApiImplicitParam
-
@ApiResponses: 用于类或者方法,描述操作的可能响应
-
@ApiResponse: 用于类或者方法,描述操作的可能响应
-
@ResponseHeader: 用于方法,响应头设置
1. @Api
-
tags 表示说明,tags如果有多个值,会生成多个列表
-
value 表示说明,可以使用tags替代
package com.zjw.controller;
@RestController
@RequestMapping(path = "/tv")
@Api(tags = {"电视机相关业务组"}, description = "电视机相关业务组接口描述信息.")
public class TVController {
}
2. @ApiOperation
-
value 用于方法描述
-
notes 用于提示内容
-
tags 用于API文档控制的标记列表,视情况而用,可以进行独立分组
package com.zjw.controller;
@RestController
@RequestMapping(path = "/tv")
@Api(tags = {"电视机相关业务组"}, description = "电视机相关业务组接口描述信息.")
public class TVController {
@Autowired
private TelevisionService televisionService;
@GetMapping("")
@ApiOperation(value = "获取所有电视机信息", notes = "获取所有电视机业务信息,正在调试中...", httpMethod = "GET")
public Result getAll() {
List<Television> televisions = null;
try {
televisions = televisionService.getAll();
} catch (Exception e) {
logger.error("查询失败: {}", e.getMessage());
}
return Result.success(televisions);
}
}
3. @ApiParam
-
name 参数名
-
value 参数说明
-
required 是否必填
package com.zjw.controller;
@RestController
@RequestMapping(path = "/tv")
@Api(tags = {"电视机相关业务组"}, description = "电视机相关业务组接口描述信息.")
public class TVController {
@DeleteMapping("{tvId}")
@ApiOperation(value = "根据tvId删除电视机信息", notes = "正在调试中...", httpMethod = "DELETE")
// @ApiImplicitParam(name = "tvId", value = "电视机id", example = "1", required = true, dataType = "int", paramType = "path", defaultValue = "3")
public Result delete(
@ApiParam(name = "tvId", value = "电视机id", required = true) @PathVariable("tvId") Integer tvId
) {
try {
televisionService.deleteById(tvId);
return Result.success(tvId);
} catch (Exception e) {
logger.error("查询失败: {}", e.getMessage());
}
return Result.failure(ResultCode.PARAM_NOT_COMPLETE);
}
}
4. @ApiModel
-
value 对象名
-
description 描述
package com.zjw.entity;
/**
* 电视机实体
*/
@ApiModel(value = "Television", description = "电视机实体")
@Entity
@Table(name = "television")
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Television implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)//指定主键生成的方式,AUTO 指定 H2 数据库主键自动增长
@Column(name = "tv_id")
@ApiModelProperty(value = "电视ID,主键字段,采用自增", name = "tvId", dataType = "Integer", required = false, example = "1", hidden = false)
private Integer tvId; // 电视机Id
@ApiModelProperty(value = "电视机名称", name = "tvName", dataType = "String", required = false, example = "华为荣耀智慧屏S400", hidden = false)
@Column(name = "tv_name")
private String tvName; // 电视名称
@ApiModelProperty(value = "电视机价格", name = "tvPrice", dataType = "Float", required = false, example = "5999", hidden = false)
@Column(name = "tv_price")
private Float tvPrice; // 电视价格
@ApiModelProperty(value = "电视机生产日期", name = "dateProduction", dataType = "Date", required = false, example = "2019-11-13T02:30:00.000+0800", hidden = false)
@Column(name = "date_production")
private Date dateProduction; // 生产日期
}
5. @ApiModelProperty
-
value 字段说明
-
name 重写属性名
-
dataType 重写属性数据类型
-
required 是否必填
-
example 举例说明
-
hidden 隐藏
package com.zjw.entity;
/**
* 电视机实体
*/
@ApiModel(value = "Television", description = "电视机实体")
@Entity
@Table(name = "television")
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Television implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)//指定主键生成的方式,AUTO 指定 H2 数据库主键自动增长
@Column(name = "tv_id")
@ApiModelProperty(value = "电视ID,主键字段,采用自增", name = "tvId", dataType = "Integer", required = false, example = "1", hidden = false)
private Integer tvId; // 电视机Id
@ApiModelProperty(value = "电视机名称", name = "tvName", dataType = "String", required = false, example = "华为荣耀智慧屏S400", hidden = false)
@Column(name = "tv_name")
private String tvName; // 电视名称
@ApiModelProperty(value = "电视机价格", name = "tvPrice", dataType = "Float", required = false, example = "5999", hidden = false)
@Column(name = "tv_price")
private Float tvPrice; // 电视价格
@ApiModelProperty(value = "电视机生产日期", name = "dateProduction", dataType = "Date", required = false, example = "2019-11-13T02:30:00.000+0800", hidden = false)
@Column(name = "date_production")
private Date dateProduction; // 生产日期
}
5. @ApiImplicitParam
-
name 参数名
-
value 参数说明
-
dataType 数据类型
-
paramType 参数类型
-
example 举例说明
package com.zjw.controller;
@RestController
@RequestMapping(path = "/tv")
@Api(tags = {"电视机相关业务组"}, description = "电视机相关业务组接口描述信息.")
public class TVController {
@GetMapping("{tvId}")
@ApiOperation(value = "根据tvId获取电视机信息", notes = "tvId必传", httpMethod = "GET")
@ApiImplicitParam(name = "tvId", value = "电视机id", example = "1", required = true, dataType = "int", paramType = "path", defaultValue = "2")
public Result getById(@PathVariable("tvId") Integer tvId) {
Television tv = null;
try {
tv = televisionService.getById(tvId);
} catch (Exception e) {
logger.error("查询失败: {}", e.getMessage());
}
return Result.success(tv);
}
}
6. @ApiResponses @ApiResponse
-
code 响应的HTTP状态代码
-
message 响应附带的可读消息
7. @ResponseHeader
-
name 响应头名称
-
description 头描述
-
response 默认响应类 void
-
responseContainer 参考ApiOperation中配置
生成html pdf文档
- 新增插件
<plugins>
<plugin>
<groupId>io.github.swagger2markup</groupId>
<artifactId>swagger2markup-maven-plugin</artifactId>
<version>1.3.1</version>
<configuration>
<swaggerInput>http://127.0.0.1:8888/v2/api-docs</swaggerInput>
<outputDir>./docs/asciidoc/generated</outputDir>
<config>
<swagger2markup.markupLanguage>ASCIIDOC</swagger2markup.markupLanguage>
</config>
</configuration>
</plugin>
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<version>1.5.3</version>
<!-- <version>2.0.0-RC.1</version> -->
<!-- Include Asciidoctor PDF for pdf generation -->
<dependencies>
<dependency>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj-pdf</artifactId>
<version>1.5.0-alpha.10.1</version>
</dependency>
<dependency>
<groupId>org.jruby</groupId>
<artifactId>jruby-complete</artifactId>
<version>1.7.21</version>
</dependency>
</dependencies>
<configuration>
<sourceDirectory>./docs/asciidoc/generated</sourceDirectory>
<outputDirectory>./docs/html</outputDirectory>
<backend>html</backend>
<!--<outputDirectory>./docs/pdf</outputDirectory>-->
<!--<backend>pdf</backend>-->
<headerFooter>true</headerFooter>
<doctype>book</doctype>
<sourceHighlighter>coderay</sourceHighlighter>
<attributes>
<!-- 菜单栏在左边 -->
<toc>left</toc>
<!-- 多标题排列 -->
<toclevels>3</toclevels>
<!-- 自动打数字序号 -->
<sectnums>true</sectnums>
</attributes>
</configuration>
</plugin>
</plugins>
- 生成文档
-
【访问URL
http://localhost:8888/export/ascii和http://localhost:8888/export/asciiToFile】或者【运行swagger2markup插件】生成源文件 -
在子模块中运行
mvn asciidoctor:process-asciidoc生成pdf或者html -
访问
http://localhost:8888/export/markdownToFile和http://localhost:8888/export/markdown生成markdown文件