一、简介
(A)、介绍
Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。Swagger的目标是对REST API定义一个标准的和语言无关的接口,可让人和计算机无需访问源码、文档或网络流量监测就可以发现和理解服务的能力。当通过Swagger进行正确定义,用户可以理解远程服务并使用最少实现逻辑与远程服务进行交互。与为底层编程所实现的接口类似,Swagger消除了调用服务时可能会有的猜测。
Swagger是一组开源项目,其中主要要项目如下:
Swagger-tools:提供各种与Swagger进行集成和交互的工具。例如模式检验、Swagger 1.2文档转换成Swagger 2.0文档等功能。
Swagger-core: 用于、Servlets和Play框架进行集成。
Swagger-js: 用于JavaScript的Swagger实现。
Swagger-node-express: Swagger模块,用于node.js的Express web应用框架。
Swagger-ui:一个无依赖的HTML、JS和CSS集合,可以为Swagger兼容API动态生成优雅文档。
Swagger-codegen:一个模板驱动引擎,通过分析用户Swagger资源声明以各种语言生成客户端代码。
Swagger-editor:可让使用者在浏览器里以YAML格式编辑Swagger API规范并实时预览文档。可以生成有效的Swagger JSON描述,并用于所有Swagger工具(代码生成、文档等等)中。
除了Swagger项目自身支持的Java、Scala和JavaScript语言,Swagger社区中还提供了很多支持其他语言的第三方工具,覆盖了Clojure、ColdFusion / CFML、Eiffel、Go、Groovy、.Net、Perl、PHP、Python、Ruby等各种编程语言。
SwaggerAPI文档工具可以满足下列需求:
●支持API自动生成同步的在线文档
●这些文档可用于项目内部API审核
●方便测试人员了解API
●这些文档可作为客户产品文档的一部分进行发布
●支持API规范生成代码,生成的客户端和服务器端骨架代码可以加速开发和测试速度
(B)、swagger-ui 和 springfox-swagger-ui 的关系是?
Swagger Spec 是一个规范。
Swagger Api 是 Swagger Spec 规范 的一个实现,它支持 jax-rs, restlet, jersey 等等。
Springfox libraries 是 Swagger Spec 规范 的另一个实现,专注于 spring 生态系统。
Swagger.js and Swagger-ui 是 javascript 的客户端库,能消费该规范。
springfox-swagger-ui 仅仅是以一种方便的方式封装了 swagger-ui ,使得 Spring 服务可以提供服务。
总结为:
Swagger 是一种规范。
Springfox-swagger 是基于 Spring 生态系统的该规范的实现。
Springfox-swagger-ui 是对 swagger-ui 的封装,使得其可以使用 Spring 的服务。
Swagger地址为:https://github.com/swagger-api/swagger-ui
Springfox地址为:https://github.com/springfox/springfox
二、使用
首先引入Maven依赖,这里用的是最新的2.8版本:
<!--Swagger UI--> <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> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-bean-validators</artifactId> <version>2.8.0</version> </dependency>
然后创建Swagger配置类:
/** * projectName: xxxx * fileName: SwaggerConfig.java * packageName: com.xxx.common.config * date: 2018-02-01 1:14 * copyright(c) 2017-2020 xxx公司 */ package com.fendo.mybatis.plus.config; import springfox.documentation.service.Contact; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import springfox.documentation.annotations.ApiIgnore; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; /** * @version: V1.0 * @author: fendo * @className: SwaggerConfig * @packageName: com.fendo.mybatis.plus.config * @description: Swagger配置文件 * @data: 2018-02-01 1:14 **/ @Configuration @EnableSwagger2 public class SwaggerConfig { public static final String VERSION = "1.0.0"; public static final String AUTHOR = "fendo"; @Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) //.groupName("基础模块") .select() //加了ApiOperation注解的方法,生成接口文档 .apis(RequestHandlerSelectors.basePackage("com.fendo.mybatis.plus")) //可以根据url路径设置哪些请求加入文档,忽略哪些请求 .paths(PathSelectors.any()) .build() .ignoredParameterTypes(ApiIgnore.class) .enableUrlTemplating(true); } @Bean public Docket createMonitorRestApi() { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .groupName("权限模块") .select() .apis(RequestHandlerSelectors.basePackage("com.fendo.mybatis.plus")) .paths(PathSelectors.any()) .build(); } private ApiInfo apiInfo() { return new ApiInfoBuilder() //设置文档的标题 .title("API文档") //设置文档的描述 .description("mybatis-plus项目API文档") .termsOfServiceUrl("http://blog.csdn.net/u011781521?viewmode=contents") //设置文档的版本信息 .version(VERSION) //作者信息 .contact(new Contact(AUTHOR, "http://blog.csdn.net/u011781521", "2312892206@qq.com")) //设置文档的License信息 .termsOfServiceUrl("http://blog.csdn.net/u011781521?viewmode=contents") .license("The Apache License, Version 2.0") .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html") .build(); } }
然后创建实体类,并添加注解:
/** * projectName: mybatis-plus * fileName: UserEntity.java * packageName: com.fendo.mybatis.plus.entity.enums * date: 2018-03-24 18:11 * copyright(c) 2017-2020 xxx公司 */ package com.fendo.mybatis.plus.entity; import com.baomidou.mybatisplus.annotations.TableName; import com.fendo.mybatis.plus.common.persistent.BaseEntity; import com.fendo.mybatis.plus.entity.enums.AgeEnum; import com.fendo.mybatis.plus.entity.enums.GenderEnum; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import javax.validation.constraints.Max; import javax.validation.constraints.Min; /** * @version: V1.0 * @author: fendo * @className: UserEntity * @packageName: com.fendo.mybatis.plus.entity.enums * @description: 用户类 * @data: 2018-03-24 18:11 **/ @TableName("user") @ApiModel(value="User对象",description="用户信息") public class UserEntity extends BaseEntity<UserEntity> { /** * 名称 */ @ApiModelProperty(value = "用户姓名",name="name",example="fendo") private String name; /** * 年龄 */ @ApiModelProperty(value = "用户年龄",name="age",example="2") @Max(150) @Min(1) private AgeEnum age; /** * 性别 */ @ApiModelProperty(value = "用户性别",name="sex",example="1") private GenderEnum sex; public String getName() { return name; } public void setName(String name) { this.name = name; } public AgeEnum getAge() { return age; } public void setAge(AgeEnum age) { this.age = age; } public GenderEnum getSex() { return sex; } public void setSex(GenderEnum sex) { this.sex = sex; } public UserEntity() { } public UserEntity(String name, AgeEnum age, GenderEnum sex) { this.name = name; this.age = age; this.sex = sex; } public UserEntity(String id, String name, AgeEnum age, GenderEnum sex) { this.setId(id); this.name = name; this.age = age; this.sex = sex; } }
然后创建分页封装类:
package com.fendo.mybatis.plus.common.utils; import com.baomidou.mybatisplus.plugins.Page; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import java.util.List; /** * @version: V1.0 * @author: fendo * @className: CustomPage * @packageName: com.fendo.mybatis.plus.common.utils * @description: 自定义分页数据 * @data: 2018-03-27 9:23 **/ @ApiModel public class CustomPage<T> { //当前页数 @ApiModelProperty(value = "当前页数") private int pageNo; //每页显示数量 @ApiModelProperty(value = "每页显示数量") private int pageSize; @ApiModelProperty(value = "总条数") private int totalRecord; //数据列表 @ApiModelProperty(value = "数据列表") private List<T> parameterType; //总页数 @ApiModelProperty(value = "总页数") private int totalPage; //排序字段 @ApiModelProperty(value = "排序字段") private String orderByField; //是否升序 @ApiModelProperty(value = "是否升序") private boolean isAsc; public int getPageNo() { return pageNo; } public void setPageNo(int pageNo) { this.pageNo = pageNo; } public int getPageSize() { return pageSize; } public void setPageSize(int pageSize) { this.pageSize = pageSize; } public int getTotalRecord() { return totalRecord; } public void setTotalRecord(int totalRecord) { this.totalRecord = totalRecord; } public List<T> getParameterType() { return parameterType; } public void setParameterType(List<T> parameterType) { this.parameterType = parameterType; } public int getTotalPage() { return totalPage; } public void setTotalPage(int totalPage) { this.totalPage = totalPage; } public String getOrderByField() { return orderByField; } public void setOrderByField(String orderByField) { this.orderByField = orderByField; } public boolean isAsc() { return isAsc; } public void setAsc(boolean isAsc) { this.isAsc = isAsc; } public CustomPage(){} @SuppressWarnings("deprecation") public CustomPage(Page<T> page){ this.pageNo = page.getCurrent(); this.pageSize = page.getSize(); this.totalRecord = (int) page.getTotal(); this.parameterType = page.getRecords(); this.totalPage = (int) page.getPages(); this.orderByField = page.getOrderByField(); this.isAsc = page.isAsc(); } }
统一返回数据类:
/** * projectName: mybatis-plus * fileName: ResultData.java * packageName: com.fendo.mybatis.plus.common.utils * date: 2018-03-27 10:38 * copyright(c) 2017-2020 xxx公司 */ package com.fendo.mybatis.plus.common.utils; import com.fendo.mybatis.plus.entity.UserEntity; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import java.io.Serializable; /** * @version: V1.0 * @author: fendo * @className: ResultData * @packageName: com.fendo.mybatis.plus.common.utils * @description: 返回数据 * @data: 2018-03-27 10:38 **/ @ApiModel public class ResultData <T> implements Serializable { private static final long serialVersionUID = -7424426799887924229L; @ApiModelProperty(value = "错误码") private String code; @ApiModelProperty(value = "数据对象") private T data; @ApiModelProperty(value = "错误码描述") private String message; public ResultData(CustomPage<UserEntity> customPage) { } public ResultData(String code, String message) { this.code = code; this.message = message; } public ResultData(SimpleCode simpleCode) { this.code = simpleCode.getCode(); this.message = simpleCode.getMessage(); } public ResultData(String code, String message, T data) { this.code = code; this.message = message; this.data = data; } public ResultData(SimpleCode simpleCode, T data) { this.code = simpleCode.getCode(); this.message = simpleCode.getMessage(); this.data = data; } public ResultData(Boolean falg, T data) { if(falg){ this.code = SimpleCode.SUCCESS.getCode(); this.message = SimpleCode.SUCCESS.getMessage(); this.data = data; }else { this.code = SimpleCode.ERROR.getCode(); this.message = SimpleCode.ERROR.getMessage(); this.data = data; } } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public T getData() { return data; } public void setData(T data) { this.data = data; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } @Override public String toString() { return "JSONResult [code=" + code + ", data=" + data + ", message=" + message + "]"; } }创建Controller类:
/** * projectName: mybatis-plus * fileName: UserController.java * packageName: com.fendo.mybatis.plus.controller * date: 2018-03-27 10:26 * copyright(c) 2017-2020 xxx公司 */ package com.fendo.mybatis.plus.controller; import com.baomidou.mybatisplus.plugins.Page; import com.fendo.mybatis.plus.common.utils.*; import com.fendo.mybatis.plus.common.web.BaseController; import com.fendo.mybatis.plus.entity.UserEntity; import com.fendo.mybatis.plus.entity.enums.AgeEnum; import com.fendo.mybatis.plus.entity.enums.GenderEnum; import com.fendo.mybatis.plus.request.UserRequest; import com.fendo.mybatis.plus.service.UserService; import io.swagger.annotations.*; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.stereotype.Controller; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import java.util.List; import java.util.Map; /** * @version: V1.0 * @author: fendo * @className: UserController * @packageName: com.fendo.mybatis.plus.controller * @description: 用户Controller * @data: 2018-03-27 10:26 **/ @Controller @RequestMapping("/user") @Api(value = "/user", description = "用户操作接口") @Validated public class UserController extends BaseController{ @Autowired protected UserService userService; /** * 用户新增与更新 * @param data * @return */ @PostMapping("/save") @ResponseBody @ApiOperation(value = "更新用户信息", notes = "更新或者保存用户信息") @ApiResponses(value = {@ApiResponse(code = 405, message = "invalid input")}) public ResultData<CustomPage<UserEntity>> save(@RequestBody @ApiParam(name="用户对象",value="传入JSON格式",required=true) UserRequest data) { ResultData<CustomPage<UserEntity>> result = null; CustomPage<UserEntity> customPage = null; if(validates(validator, data)!=null){ result = new ResultData<CustomPage<UserEntity>>(SimpleCode.ERROR.getCode(), validates(validator, data)); } UserEntity userEntity = new UserEntity(); BeanUtils.copyProperties(data,userEntity); if(StringUtils.isNotEmpty(userEntity.getId())){ userEntity.updateById(); }else { userEntity.insert(); } Page<UserEntity> userEntityPage = userEntity.selectPage(new Page<UserEntity>(0, 12), null); customPage = new CustomPage<UserEntity>(userEntityPage); result = new ResultData<CustomPage<UserEntity>>(SimpleCode.SUCCESS, customPage); return result; } /** * 删除用户 * @param id * @return */ @ApiOperation(value = "删除用户", notes = "通过用户id删除用户", httpMethod = "GET") @ApiResponses({ @ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "服务器内部异常"), @ApiResponse(code = 405, message = "权限不足") }) @GetMapping("/delete") @ResponseBody public ResultData<String> delete(@NotEmpty(message = "用户ID不能为空") @ApiParam(value = "用户ID)", required = true) @RequestParam String id){ ResultData<String> result; UserEntity userEntity = new UserEntity(); userEntity.setId(id); result = new ResultData(userEntity.deleteById(),"用户删除"); return result; } /** * 根据用户ID获取用户 * @param id * @return */ @GetMapping("/get") @ResponseBody @ApiOperation(value = "获取用户信息", notes = "更新ID获取用户信息") public ResultData<UserEntity> get(@NotEmpty(message = "用户ID不能为空") @ApiParam(value = "用户ID)", required = true) @RequestParam String id){ UserEntity userEntity = userService.selectById(id); return new ResultData<UserEntity>(SimpleCode.SUCCESS,userEntity); } /** * 参数模式分页 * @param page * @return */ @GetMapping("/list") @ResponseBody @ApiImplicitParams({ @ApiImplicitParam(name = "size", value = "一页大小", required = false, dataType = "String", paramType = "query"), @ApiImplicitParam(name = "current", value = "当前页码", required = false, dataType = "String", paramType = "query"), }) @ApiOperation(value = "自带分页", notes = "分页获取数据") public ResultData<CustomPage<UserEntity>> lis(Page page) { CustomPage<UserEntity> customPage = new CustomPage<UserEntity>(userService.selectPage(page)); return new ResultData<CustomPage<UserEntity>>(SimpleCode.SUCCESS, customPage); } /** * 分页 * @param frontPage * @return */ @PostMapping("/page") @ResponseBody @ApiOperation(value = "自定义分页", notes = "分页获取数据") public ResultData<CustomPage<Map<String,Object>>> page(@ApiParam(required = false, value = "分页参数") @RequestBody(required=false) FrontPage<UserRequest> frontPage) { CustomPage<Map<String,Object>> customPage = new CustomPage<Map<String,Object>>(userService.getPage(frontPage.getPagePlus(),frontPage.getParam())); return new ResultData<CustomPage<Map<String,Object>>>(SimpleCode.SUCCESS, customPage); } }
运行效果如下:
测试分页返回数据如下:
三、Swagger常用注解
API详细说明
作用范围 | API | 使用位置 |
---|---|---|
对象属性 | @ApiModelProperty | 用在出入参数对象的字段上 |
协议集描述 | @Api | 用于controller类上 |
协议描述 | @ApiOperation | 用在controller的方法上 |
Response集 | @ApiResponses | 用在controller的方法上 |
Response | @ApiResponse | 用在 @ApiResponses里边 |
非对象参数集 | @ApiImplicitParams | 用在controller的方法上 |
非对象参数描述 | @ApiImplicitParam | 用在@ApiImplicitParams的方法里边 |
描述返回对象的意义 | @ApiModel | 用在返回对象类上 |
忽略某类/方法/参数的文档 @ApiIgnore 用在类/方法/参数上
1. api标记
Api 用在类上,说明该类的作用。可以标记一个Controller类做为swagger 文档资源,使用方式
@Api(value = "/user", description = "Operations about user")
与Controller注解并列使用。 属性配置:
属性名称 | 备注 |
---|---|
value | url的路径值 |
tags | 如果设置这个值、value的值会被覆盖 |
description | 对api资源的描述 |
basePath | 基本路径可以不配置 |
position | 如果配置多个Api 想改变显示的顺序位置 |
produces | For example, "application/json, application/xml" |
consumes | For example, "application/json, application/xml" |
protocols | Possible values: http, https, ws, wss. |
authorizations | 高级特性认证时配置 |
hidden | 配置为true 将在文档中隐藏 |
在SpringMvc中的配置如下:
@Controller @RequestMapping(value = "/api/pet", produces = {APPLICATION_JSON_VALUE, APPLICATION_XML_VALUE}) @Api(value = "/pet", description = "Operations about pets") public class PetController { }
2. ApiOperation标记
ApiOperation:用在方法上,说明方法的作用,每一个url资源的定义,使用方式:
@ApiOperation( value = "Find purchase order by ID", notes = "For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions", response = Order, tags = {"Pet Store"})
与Controller中的方法并列使用。
属性名称 | 备注 |
---|---|
value | url的路径值 |
tags | 如果设置这个值、value的值会被覆盖 |
description | 对api资源的描述 |
basePath | 基本路径可以不配置 |
position | 如果配置多个Api 想改变显示的顺序位置 |
produces | For example, "application/json, application/xml" |
consumes | For example, "application/json, application/xml" |
protocols | Possible values: http, https, ws, wss. |
authorizations | 高级特性认证时配置 |
hidden | 配置为true 将在文档中隐藏 |
response | 返回的对象 |
responseContainer | 这些对象是有效的 "List", "Set" or "Map".,其他无效 |
httpMethod | "GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS" and "PATCH" |
code | http的状态码 默认 200 |
extensions | 扩展属性 |
在SpringMvc中的配置如下:
@RequestMapping(value = "/order/{orderId}", method = GET) @ApiOperation( value = "Find purchase order by ID", notes = "For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions", response = Order.class, tags = { "Pet Store" }) public ResponseEntity<Order> getOrderById(@PathVariable("orderId") String orderId) throws NotFoundException { Order order = storeData.get(Long.valueOf(orderId)); if (null != order) { return ok(order); } else { throw new NotFoundException(404, "Order not found"); } }
3. ApiParam标记
ApiParam请求属性,使用方式:
public ResponseEntity<User> createUser(@RequestBody @ApiParam(value = "Created user object", required = true) User user)与Controller中的方法并列使用。
属性配置:
属性名称 | 备注 |
---|---|
name | 属性名称 |
value | 属性值 |
defaultValue | 默认属性值 |
allowableValues | 可以不配置 |
required | 是否属性必填 |
access | 不过多描述 |
allowMultiple | 默认为false |
hidden | 隐藏该属性 |
example | 举例子 |
public ResponseEntity<Order> getOrderById( @ApiParam(value = "ID of pet that needs to be fetched", allowableValues = "range[1,5]", required = true) @PathVariable("orderId") String orderId)
4. ApiResponse
ApiResponse:响应配置,使用方式:
@ApiResponse(code = 400, message = "Invalid user supplied")
与Controller中的方法并列使用。 属性配置:
属性名称 | 备注 |
---|---|
code | http的状态码 |
message | 描述 |
response | 默认响应类 Void |
reference | 参考ApiOperation中配置 |
responseHeaders | 参考 ResponseHeader 属性配置说明 |
responseContainer | 参考ApiOperation中配置 |
在SpringMvc中的配置如下:
@RequestMapping(value = "/order", method = POST) @ApiOperation(value = "Place an order for a pet", response = Order.class) @ApiResponses({ @ApiResponse(code = 400, message = "Invalid Order") }) public ResponseEntity<String> placeOrder( @ApiParam(value = "order placed for purchasing the pet", required = true) Order order) { storeData.add(order); return ok(""); }
5. ApiResponses
ApiResponses:响应集配置,使用方式:
@ApiResponses({ @ApiResponse(code = 400, message = "Invalid Order") })
与Controller中的方法并列使用。 属性配置:
属性名称 | 备注 |
---|---|
value | 多个ApiResponse配置 |
@RequestMapping(value = "/order", method = POST) @ApiOperation(value = "Place an order for a pet", response = Order.class) @ApiResponses({ @ApiResponse(code = 400, message = "Invalid Order") }) public ResponseEntity<String> placeOrder( @ApiParam(value = "order placed for purchasing the pet", required = true) Order order) { storeData.add(order); return ok(""); }
6. ResponseHeader
@ResponseHeader(name="head1",description="response head conf")
与Controller中的方法并列使用。 属性配置:
属性名称 | 备注 |
---|---|
name | 响应头名称 |
description | 头描述 |
response | 默认响应类 Void |
responseContainer | 参考ApiOperation中配置 |
@ApiModel(description = "群组")
属性 | 取值 | 作用 |
---|---|---|
paramType | 查询参数类型 | |
path | 以地址的形式提交数据 | |
query | 直接跟参数完成自动映射赋值 | |
body | 以流的形式提交 仅支持POST | |
header | 参数在request headers 里边提交 | |
form | 以form表单的形式提交 仅支持POST | |
dataType | 参数的数据类型 只作为标志说明,并没有实际验证 | |
Long | ||
String | ||
name | 接收参数名 | |
value | 接收参数的意义描述 | |
required | 参数是否必填 | |
true | 必填 | |
false | 非必填 | |
defaultValue | 默认值 |
@RequestMapping(value = "/findById1/{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) @PathVariable(name = "id") Long id
2.Body
@ApiImplicitParams({ @ApiImplicitParam(paramType = "body", dataType = "MessageParam", name = "param", value = "信息参数", required = true) }) @RequestMapping(value = "/findById3", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE) @RequestBody MessageParam param
提交的参数是这个对象的一个json,然后会自动解析到对应的字段上去,也可以通过流的形式接收当前的请求数据,但是这个和上面的接收方式仅能使用一个(用@RequestBody之后流就会关闭了)
3.Header
@ApiImplicitParams({ @ApiImplicitParam(paramType = "header", dataType = "Long", name = "id", value = "信息id", required = true) }) String idstr = request.getHeader("id"); if (StringUtils.isNumeric(idstr)) { id = Long.parseLong(idstr); }
@ApiImplicitParams({ @ApiImplicitParam(paramType = "form", dataType = "Long", name = "id", value = "信息id", required = true) }) @RequestMapping(value = "/findById5", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
@ApiImplicitParams:用在方法上包含一组参数说明;
@ApiImplicitParam:用在@ApiImplicitParams注解中,指定一个请求参数的各个方面
●paramType:参数放在哪个地方
●name:参数代表的含义
●value:参数名称
●dataType: 参数类型,有String/int,无用
●required : 是否必要
●defaultValue:参数的默认值
@ApiResponses:用于表示一组响应;
@ApiResponse:用在@ApiResponses中,一般用于表达一个错误的响应信息;
●code: 响应码(int型),可自定义
●message:状态码对应的响应信息
@ApiModel:描述一个Model的信息(这种一般用在post创建的时候,使用@RequestBody这样的场景,请求参数无法使用@ApiImplicitParam注解进行描述的时候;
@ApiModelProperty:描述一个model的属性。
Swagger2Markup是Github上的一个开源项目。该项目主要用来将Swagger自动生成的文档转换成几种流行的格式以便于静态部署和使用,比如:AsciiDoc、Markdown、Confluence。
项目主页: https://github.com/Swagger2Markup/swagger2markup
生成AsciiDoc的方式有两种:
4.1.1、通过Java代码来生成
第一步:编辑pom.xml增加需要使用的相关依赖和仓库
<dependency> <groupId>io.github.swagger2markup</groupId> <artifactId>swagger2markup</artifactId> <version>1.3.1</version> </dependency>
第二步:编写一个单元测试用例来生成执行生成文档的代码
@RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) public class SwaggerApplicationTests { @Test public void generateAsciiDocs() throws Exception { // 输出Ascii格式 Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder() .withMarkupLanguage(MarkupLanguage.ASCIIDOC) .build(); Swagger2MarkupConverter.from(new URL("http://localhost:8080/v2/api-docs")) .withConfig(config) .build() .toFolder(Paths.get("src/docs/asciidoc/generated")); } }
src --docs ----asciidoc ------generated --------definitions.adoc --------overview.adoc --------paths.adoc --------security.adoc
生成出了4个不同的静态文件。
<plugin> <groupId>io.github.swagger2markup</groupId> <artifactId>swagger2markup-maven-plugin</artifactId> <version>1.3.1</version> <configuration> <swaggerInput>http://localhost:8080/v2/api-docs</swaggerInput> <outputDir>src/docs/asciidoc/generated</outputDir> <config> <swagger2markup.markupLanguage>ASCIIDOC</swagger2markup.markupLanguage> </config> </configuration> </plugin>
4.2、生成HTML
完成了从Swagger文档配置文件到AsciiDoc的源文件转换之后,就是如何将AsciiDoc转换成可部署的HTML内容了。引入一个Maven插件来完成。
<plugin> <groupId>org.asciidoctor</groupId> <artifactId>asciidoctor-maven-plugin</artifactId> <version>1.5.6</version> <configuration> <sourceDirectory>src/docs/asciidoc/generated</sourceDirectory> <outputDirectory>src/docs/asciidoc/html</outputDirectory> <backend>html</backend> <sourceHighlighter>coderay</sourceHighlighter> <attributes> <toc>left</toc> </attributes> </configuration> </plugin>
执行该插件的
mvn asciidoctor:process-asciidoc
参考文章:
http://blog.didispace.com/swagger2markup-asciidoc/
https://leongfeng.github.io/2017/02/20/springboot-springfox-swagger2markup-spring-restdoc/