Swagger2在项目上的应用,便捷的输出接口文档.
在解决高并发的学习中,接触到swagger2.是一个接口文档的解决方案.开始自己学习在已有的项目上进行部署.将学习到的与遇到的问题进行整理,希望对大家以及以后的工作有所帮助.
使用swagger2需要引入swagger2的pom坐标,特别注明,两个pom坐标的版本需要相同.
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger2.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger2.version}</version>
</dependency>
此处的swagger2.version可以直接RELEASE的版本,将自动使用最新版本.
在Spring boot上集成swagger2需要使用Configuration注解进行注入,此处给出一个范例.
package com.mingcloud.az.common;
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.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* @author Relic
* @desc swagger2配置类
* @date 2019-02-05 15:59
*/
@EnableSwagger2
@Configuration
public class Swagger2Configuration {
@Bean
public Docket controllerApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(new ApiInfoBuilder().title("xxxxx接口文档").description("前后端分离使用过的接口文档")
.contact(new Contact("Relic", null, null)).version("版本号:1.0").build())
.select().apis(RequestHandlerSelectors.basePackage("com.mingcloud.az.controller"))
.paths(PathSelectors.any()).build();
}
}
swagger通过注解表明该接口会生成文档,包括接口名、请求方法、参数、返回信息的等等。
- @Api:修饰整个类,描述Controller的作用
- @ApiOperation:描述一个类的一个方法,或者说一个接口
- @ApiParam:单个参数描述
- @ApiModel:用对象来接收参数(在实体类上进行注解)
- @ApiProperty:用对象接收参数时,描述对象的一个字段(在实体类的属性上进行注解)
- @ApiResponse:HTTP响应其中1个描述
- @ApiResponses:HTTP响应整体描述
- @ApiIgnore:使用该注解忽略这个API
- @ApiError :发生错误返回的信息
- @ApiImplicitParam:一个请求参数
- @ApiImplicitParams:多个请求参数
@Api:用在请求的类上,表示对类的说明
tags="说明该类的作用,可以在UI界面上看到的注解"
value="该参数没什么意义,在UI界面上也看到,所以不需要配置"
@ApiOperation:用在请求的方法上,说明方法的用途、作用
value="说明方法的用途、作用"
notes="方法的备注说明"
@ApiImplicitParams:用在请求的方法上,表示一组参数说明
@ApiImplicitParam:用在@ApiImplicitParams注解中,指定一个请求参数的各个方面
name:参数名
value:参数的汉字说明、解释
required:参数是否必须传
paramType:参数放在哪个地方
· header --> 请求参数的获取:@RequestHeader
· query --> 请求参数的获取:@RequestParam
· path(用于restful接口)--> 请求参数的获取:@PathVariable
· body(不常用)
· form(不常用)
dataType:参数类型,默认String,其它值dataType="Integer"
defaultValue:参数的默认值
@ApiResponses:用在请求的方法上,表示一组响应
@ApiResponse:用在@ApiResponses中,一般用于表达一个错误的响应信息
code:数字,例如400
message:信息,例如"请求参数没填好"
response:抛出异常的类
@ApiModel:用于响应类上,表示一个返回响应数据的信息
(这种一般用在post创建的时候,使用@RequestBody这样的场景,
请求参数无法使用@ApiImplicitParam注解进行描述的时候)
@ApiModelProperty:用在属性上,描述响应
此处需要引入一个Restful风格接口的概念.
URL定位资源,用HTTP动词(GET,POST,DELETE,DETC)描述操作。
识别(identify)、 表示(represent) 、交互(interact with)。
- 看Url就知道要什么
- 看http method就知道干什么
- 看http status code就知道结果如何
1. REST描述的是在网络中client和server的一种交互形式;REST本身不实用,实用的是如何设计 RESTful API(REST风格的网络接口);
2. Server提供的RESTful API中,URL中只使用名词来指定资源,原则上不使用动词。“资源”是REST架构或者说整个网络处理的核心。比如:
http://api.qc.com/v1/newsfeed: 获取某人的新闻推送;
http://api.qc.com/v1/friends: 获取某人的好友列表;
http://api.qc.com/v1/profile: 获取某人的详细信息;
3. 用HTTP协议里的动词来实现资源的添加,修改,删除等操作。即通过HTTP动词来实现资源的状态扭转:
GET 用来获取资源,
POST 用来新建资源(也可以用于更新资源),
PUT 用来更新资源,
DELETE 用来删除资源。比如:
DELETE http://api.qc.com/v1/friends: 删除某人的好友 (在http parameter指定好友id)
POST http://api.qc.com/v1/friends: 添加好友
UPDATE http://api.qc.com/v1/profile: 更新个人资料
4. Server和Client之间传递某资源的一个表现形式,比如用JSON,XML传输文本,或者用JPG,WebP传输图片等。当然还可以压缩HTTP传输时的数据(on-wire data compression)。
5. 用 HTTP Status Code传递Server的状态信息。比如最常用的 200 表示成功,500 表示Server内部错误等。
1、REST 是面向资源的,这个概念非常重要,而资源是通过 URI 进行暴露。
比如:左边是错误的设计,而右边是正确的
GET /rest/api/getDogs --> GET /rest/api/dogs 获取所有小狗狗
GET /rest/api/addDogs --> POST /rest/api/dogs 添加一个小狗狗
GET /rest/api/editDogs/:dog_id --> PUT /rest/api/dogs/:dog_id 修改一个小狗狗
GET /rest/api/deleteDogs/:dog_id --> DELETE /rest/api/dogs/:dog_id 删除一个小狗狗
2、REST很好地利用了HTTP本身就有的一些特征,如HTTP动词、HTTP状态码、HTTP报头等等。
- HTTP动词
GET 获取一个资源
POST 添加一个资源
PUT 修改一个资源
DELETE 删除一个资源
- HTTP状态码
200 OK
400 Bad Request
500 Internal Server Error
- HTTP报头
Authorization 认证报头
Cache-Control 缓存报头
Cnotent-Type 消息体类型报头
......
在控制层上加上注解.
package com.mingcloud.az.controller;
import com.mingcloud.az.common.ConfigurationTypeEnum;
import com.mingcloud.az.common.Result;
import com.mingcloud.az.entity.ConfigurationEntity;
import com.mingcloud.az.service.ConfigurationService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* @author xyc
*/
@Api("相关属性(时间.等)的配置")
@RestController
@RequestMapping("/configuration")
public class ConfigurationController {
@Resource
private ConfigurationService configurationService;
@ApiOperation("根据条件获取配置")
@GetMapping("/doGetConfig.do")
public Result getConfig(ConfigurationEntity entity) {
Result result;
try {
entity.setTypeId(ConfigurationTypeEnum.getConfigurationByType(entity.getTypeStr()));
result = configurationService.getConfig(entity);
} catch (Exception e) {
e.printStackTrace();
result = new Result(false, e.getMessage());
}
return result;
}
/**
* 更新配置参数接口,如需更新的typeId数据库没有,则新建,如果存在就更新
*
* @param entity 配置实体类
* @return com.mingcloud.az.common.Result
* @title updateConfig
* @date 2019/1/17 15:48
*/
@PutMapping("/doUpdateConfig.do")
public Result updateConfig(ConfigurationEntity entity) {
Result result;
try {
entity.setTypeId(ConfigurationTypeEnum.getConfigurationByType(entity.getTypeStr()));
result = configurationService.updateConfig(entity);
} catch (Exception e) {
e.printStackTrace();
result = new Result(false, e.getMessage());
}
return result;
}
}
实体类上添加上注解
package com.mingcloud.az.entity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import java.util.Date;
/**
* @author Relic
*/
@Getter
@Setter
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
@ApiModel("配置实体类")
public class ConfigurationEntity extends BaseEntity {
@ApiModelProperty(hidden = true)
private Long id;
@ApiModelProperty(value = "类型id")
private Integer typeId;
@ApiModelProperty("备注")
private String memo;
@ApiModelProperty(value = "额外id1")
private Integer extraId1;
@ApiModelProperty(value = "额外id2")
private Integer extraId2;
@ApiModelProperty(value = "额外id3")
private Integer extraId3;
@ApiModelProperty(value = "天数")
private Integer extraInt1;
@ApiModelProperty(value = "额外整数2")
private Integer extraInt2;
@ApiModelProperty(value = "额外整数3")
private Integer extraInt3;
@ApiModelProperty("额外字符串1")
private String extraVarChar1;
@ApiModelProperty("额外字符串2")
private String extraVarChar2;
@ApiModelProperty("额外字符串3")
private String extraVarChar3;
@ApiModelProperty("类型名称")
private String typeStr;
@ApiModelProperty("修改日期")
private Date modificationDate;
@ApiModelProperty(value = "修改用户id")
private Integer modificationUserId;
}
最后,启动项目,访问 http://ip:port/项目名/swagger-ui.html页面
swagger2一个很实用的功能就就是在测试接口功能上.点击接口上的try it out.然后填写参数,点击execute.
可以直接在编写前端代码之前直接进行测试.
下面说几个遇到的坑- -.
1.访问swagger2-ui.html的时候出现弹框.
一开始以为是context-path的问题.去掉context-path的确能够访问,但是不是长久之计.
后来发现只要清除缓存之后,即可解决这个问题.
2.访问swagger2-ui.html界面时,后台一直报错:Illegal DefaultValue null for parameter type integer
原因是由于swagger2的bug,在没有给定integer与long类型的变量默认值的情况下,默认是""值,所以强转失败.对程序本身没有什么影响,但是毕竟本人是个强迫症患者= =.所以在调高日志打印级别为error.
logging.level.io.swagger.models.parameters.AbstractSerializableParameter: error
顺利解决.