一、Swagger简介
Swagger 是一个规范和完整的框架,是一款RESTFUL接口的、基于YAML、JSON语言的文档在线自动生成、代码自动生成的工具。它用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。它提供了一个方法,使我们可以用指定的 JSON 或者 YAML 摘要来描述你的 API文档接口。
使用Swagger的好处:
Swagger 可以生成一个具有互动性的API控制台,开发者可以用来快速学习和测试API接口。
Swagger 可以生成客户端SDK代码用于各种不同的平台上的实现。
Swagger 文件可以在许多不同的平台上从代码注释中自动生成。
Swagger 有一个强大的社区,里面有许多强悍的贡献者。
二、Swagger开源组件介绍
1. Swagger-tools:提供各种与Swagger进行集成和交互的工具。例如模式检验、Swagger 1.2文档转换成Swagger 2.0文档等功能。
2. Swagger-core: 用于Java/Scala的的Swagger实现。与JAX-RS(Jersey、Resteasy、CXF...)、Servlets和Play框架进行集成。
3. Swagger-js: 用于JavaScript的Swagger实现。
4. Swagger-node-express: Swagger模块,用于node.js的Express web应用框架。
5. Swagger-ui:一个无依赖的HTML、JS和CSS集合,可以为Swagger兼容API动态生成优雅文档。是一套 HTML/CSS/JS 框架用于解析遵守 Swagger spec 的 JSON 或 YML 文件,并且生成API文档的UI导航。它可以将你的规格文档转换成Swagger Petsotre-like UI。
6. Swagger-codegen:一个模板驱动引擎,通过分析用户Swagger资源声明以各种语言生成客户端代码。它为不同的平台生成客户端 SDK(比如 Java、JavaScript、Python 等)。这些客户端代码帮助开发者在一个规范平台中整合 API ,并且提供了更多健壮的实现,可能包含了多尺度、线程,和其他重要的代码。SDK 是用于支持开发者使用 REST API 的工具。
7. Swagger-Editor: 在线编辑器,用于验证你的 YML 格式的内容是否违反 Swagger spec 。YML 是一种句法,依赖于空格和嵌套。Swagger 编辑器会标出错误并且给你格式提醒(Swagger spec 文件可以使用 JSON 或者 YAML 中的任意一种格式)。
三、引入Swagger依赖
在与项目整合(包含SpringBoot项目)时,需要引入相关Swagger依赖,有两种依赖方式:
(1)使用第三方依赖
<!-- https://mvnrepository.com/artifact/com.spring4all/swagger-spring-boot-starter --> <dependency> <groupId>com.spring4all</groupId> <artifactId>swagger-spring-boot-starter</artifactId> <version>1.8.0.RELEASE</version> </dependency>
(2)使用官方依赖
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency>
目前最新版本是2.9.2的
四、编写Swagger配置类
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; 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; /** * @ClassName: SwaggerConfig * @Desc: swagger文档配置 * @Author: liuhefei * @Date: 2019/3/11 10:29 */ @Configuration @EnableSwagger2 @Profile(value = {"dev", "test"}) //指定运行环境(开发,测试) public class SwaggerConfig { @Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("你项目的包名")) .paths(PathSelectors.any()) .build(); } private ApiInfo apiInfo() { return new ApiInfoBuilder().title("Api接口接口") .description("api接口描述信息") .contact(new Contact("作者", "url", "email")) .termsOfServiceUrl("https://swagger.io/swagger-ui/") .version("1.0") .build(); } }
五、Swagger相关注解说明
swagger通过注解表明该接口会生成文档,包括接口名、请求方法、参数、返回信息的等等。
(1) @Api:修饰整个类,描述Controller的作用。比如:@Api(value = "/userlist", description = "用户列表API")
(2) @ApiModelProperty: 用在出入参数对象的字段上,比如:@ApiModelProperty(value = "记录创建时间", notes = "", example = "")
(3) @ApiOperation:描述一个类的一个方法,或者说一个接口,以说明它的作用,用在controller的方法上。比如:@ApiOperation(value = "",notes = "",response = Order,tags = {""})
(4) @ApiParam:单个参数描述,比如:@ApiParam(value = "用户", required = true) User user)
(5) @ApiModel:用对象来接收参数,用在返回对象类上,比如:@ApiModel(value="用户对象模型")
(6) @ApiProperty:用对象接收参数时,描述对象的一个字段
(7) @ApiResponse:HTTP响应其中1个描述,用在 @ApiResponses里边,比如:@ApiResponse(code = 400, message = "Invalid user supplied")
(8) @ApiResponses:HTTP响应整体描述,用在controller的方法上,比如:@ApiResponses({ @ApiResponse(code = 400, message = "Invalid Order") })
(9) @ApiIgnore:使用该注解忽略这个API
(10) @ApiError :发生错误返回的信息
(11) @ResponseHeader:响应头设置,比如:@ResponseHeader(name="openid",description="用户openid")
(12) @ApiImplicitParam:一个请求参数,用在@ApiImplicitParams的方法里边
(13) @ApiImplicitParams:多个请求参数,用在controller的方法上
其中@ApiImplicitParam的参数说明如下:
属性:paramType ,用于查询参数类型,其值为:path/query/body/header/form,含义如下:
path 以地址的形式提交数据
query 直接跟参数完成自动映射赋值
body 以流的形式提交 仅支持POST
header 参数在request headers 里边提交
form 以form表单的形式提交 仅支持POST
属性:dataType ,指定参数的数据类型(Long,String) 只作为标志说明,并没有实际验证
属性:name ,接收参数名(必须与方法中参数名一致)
属性:value ,接收参数的意义描述(描述信息)
属性:required ,参数是否必填,其值为:true(必填),false(非必填)
属性:defaultValue ,为参数设置默认值
实例代码:
import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; import java.util.Date; /** * @ClassName: ActivityList * @Desc: 活动管理列表 * @Author: liuhefei * @Date: 2019/3/11 15:16 */ @Data @AllArgsConstructor @NoArgsConstructor @Builder public class ActivityList implements Serializable { private static final long serialVersionUID = -2323114201346199834L; @ApiModelProperty(value = "活动列表id",notes = "主键id不可更改",example = "1") private Integer id; @ApiModelProperty(value = "图片缩略图", notes = "", example = "") private String imageUrl; @ApiModelProperty(value = "标题", notes = "", example = "") private String title; @ApiModelProperty(value = "跳转链接", notes = "", example = "") private String jumpUrl; @ApiModelProperty(value = "运营文案", notes = "", example = "") private String content; @ApiModelProperty(value = "发布时间", notes = "", example = "") private Date releaseTime; @ApiModelProperty(value = "编辑者", notes = "", example = "") private String editAuthor; @ApiModelProperty(value = "审核者", notes = "", example = "") private String auditor; @ApiModelProperty(value = "活动状态:0:已结束;1:进行中", notes = "", example = "") private Integer activityStatus; @ApiModelProperty(value = "状态信息:1:草稿; 2:待审核; 3:未通过; 4:待发布; 5:发布中; 6:已下线", notes = "", example = "") private Integer statusInfo; @ApiModelProperty(value = "排序", notes = "", example = "1") private Integer sort; @ApiModelProperty(value = "记录创建时间", notes = "", example = "") private Date createTime; @ApiModelProperty(value = "记录更新时间", notes = "", example = "") private Date updateTime; }
import com.chuangzhan.fuwuhao.entity.ActivityList; import com.chuangzhan.fuwuhao.pojo.ActivityListParam; import com.chuangzhan.fuwuhao.service.ActivityListService; import com.chuangzhan.fuwuhao.utils.CommonResponse; import com.chuangzhan.fuwuhao.utils.PageData; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import org.jfaster.mango.plugin.page.Page; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.Date; import java.util.List; /** * @ClassName: ActivityListController * @Desc: 活动列表api接口 * @Author: liuhefei * @Date: 2019/3/12 11:01 */ @Api(tags="活动列表API后台管理接口") @RestController @RequestMapping("/activity") public class ActivityListController { final Logger logger = LoggerFactory.getLogger(this.getClass()); @Autowired ActivityListService activityListService; @ApiOperation(value = "添加或更新活动", notes="活动信息") @RequestMapping(value = "/addAcitivity", method = RequestMethod.POST) public CommonResponse<String> addActivityInfo(@RequestParam(value = "id",required = false) @ApiParam("活动编号id,添加活动时,不填;更新活动时,必填")Integer id, @RequestBody ActivityListParam activityListParam){ ActivityList activityList = new ActivityList(); if(id != null){ activityList.setId(id); //更新活动时,才传此参数 } activityList.setTitle(activityListParam.getTitle()); activityList.setImageUrl(activityListParam.getImageUrl()); activityList.setJumpUrl(activityListParam.getJumpUrl()); activityList.setContent(activityListParam.getContent()); Long releaseTime = activityListParam.getReleaseTime(); Date reTime = (releaseTime==null)?null:new Date(releaseTime); activityList.setReleaseTime(reTime); activityList.setEditAuthor(activityListParam.getEditAuthor()); activityList.setAuditor(activityListParam.getAuditor()); activityList.setActivityStatus(activityListParam.getActivityStatus()); activityList.setStatusInfo(activityListParam.getStatusInfo()); Integer num = null; try { if(id == null){ num = activityListService.insertActivityList(activityList); //保存活动信息,id自增 }else { num = activityListService.updateActivityList(activityList); //更新活动信息,需要传id } }catch (Exception e){ logger.info("保存活动信息时发生异常{}", e.getMessage()); } if(num > 1){ return CommonResponse.ok(1).setMsg("活动信息保存成功"); }else { return CommonResponse.fail(-1).setMsg("活动信息保存失败"); } } @ApiOperation(value = "根据时间/标题查询活动(活动配置查询)") @RequestMapping(value = "/queryAcitivity", method = RequestMethod.GET) public CommonResponse<PageData<ActivityList>> getActivityList(@RequestParam(value = "startTime",required = false) @ApiParam("发布时间")Long startTime, @RequestParam(value = "endTime",required = false) @ApiParam("发布时间")Long endTime, @RequestParam(value = "title",required = false) @ApiParam("活动标题")String title, @RequestParam(value = "pageNum",defaultValue = "1")int pageNum, @RequestParam(value = "pageSize",defaultValue = "5")int pageSize){ if((startTime!=null)^(endTime!=null)){ return CommonResponse.fail(-1).setMsg("时间区间不全"); } Date begin = (startTime==null)?null:new Date(startTime); Date end = (endTime==null)?null:new Date(endTime); PageData<ActivityList> pageData = new PageData<>(); Page page = Page.create(pageNum,pageSize); List<ActivityList> activityLists = activityListService.getActivityList(begin, end, title, page); pageData.setData(activityLists); pageData.setTotalCount(new Long(page.getTotal())); return CommonResponse.ok(0).setData(pageData); } @ApiOperation(value = "活动列表排序") @RequestMapping(value = "/sort", method = RequestMethod.GET) public CommonResponse<PageData<ActivityList>> activityListSort(@PathVariable Integer[] ids){ ActivityList activityList = new ActivityList(); Integer id = null; Integer sortId = null; Integer num = null; for(int i=0; i < ids.length; i++){ id = i; sortId = ids[i]; num = activityListService.updateActivitySort(sortId, id); } if(num > 0){ return CommonResponse.ok(0).setMsg("排序成功"); }else { return CommonResponse.fail("-1").setMsg("排序失败"); } } @ApiOperation(value = "根据时间/标题查询活动(活动顺序查询)") @RequestMapping(value = "/queryAcitivitySort", method = RequestMethod.GET) public CommonResponse<PageData<ActivityList>> getActivityListSort(@RequestParam(value = "startTime",required = false) @ApiParam("发布时间")Long startTime, @RequestParam(value = "endTime",required = false) @ApiParam("发布时间")Long endTime, @RequestParam(value = "title",required = false) @ApiParam("活动标题")String title, @RequestParam(value = "pageNum",defaultValue = "1")int pageNum, @RequestParam(value = "pageSize",defaultValue = "5")int pageSize){ if((startTime!=null)^(endTime!=null)){ return CommonResponse.fail(-1).setMsg("时间区间不全"); } Date begin = (startTime==null)?null:new Date(startTime); Date end = (endTime==null)?null:new Date(endTime); PageData<ActivityList> pageData = new PageData<>(); Page page = Page.create(pageNum,pageSize); List<ActivityList> activityLists = activityListService.getActivityListSort(begin, end, title, page); pageData.setData(activityLists); pageData.setTotalCount(new Long(page.getTotal())); return CommonResponse.ok(0).setData(pageData); } @ApiOperation(value = "根据活动编号id删除活动") @RequestMapping(value = "/deleteActivity", method = RequestMethod.GET) public CommonResponse<String> removeActivity(@RequestParam(value = "id",required = false) @ApiParam("活动编号id")Integer id){ Integer num = null; /*if(statusInfo == 1 || statusInfo == 3 || statusInfo == 4 || statusInfo == 6){ }else { return CommonResponse.fail(-1).setMsg("不能删除该条记录"); }*/ num = activityListService.deleteActivityListById(id); if(num > 0){ return CommonResponse.ok(1).setMsg("删除成功"); }else { return CommonResponse.fail(-1).setMsg("删除失败"); } } }
启动SpringBoot项目,访问Swagger文档:http://localhost:8820/swagger-ui.html#/
效果如图:
六、Swagger相关学习资源
Swagger官网:https://swagger.io/
Swagger 编辑网址:http://editor.swagger.io/#/
swagger-codegen
spring-boot-starter-swagger
更多关于Swagger文档相关的知识,请自行查阅!