后台开发人员最痛苦的是什么,或许不是写接口,而是写接口文档。接口文档真是体力活,没有什么技术含量,粘贴复制还要心细,能把人累到吐血。呃,写接口文档的那些日子痛不欲生、苦不堪言。希望有那么一天,可以脱离写接口文档的苦海。
这样的一天很快到来了,那就是接触了swagger框架。刚开始,心里满满的兴奋,是不是稍微配置一下,就能摆脱写文档的苦海呢,事实却说,没这么简单,新接触一款工具,第一是要用起来。第二,就是用的好,只有用的好,才能发挥工具的真正价值。
在用的过程中,又发现了一系列问题,这些问题如果不能解决,就发挥不了一个接口文档的作用,还会增加沟通成本,又有哪些问题呢,一一列举下:
1. 基本使用,如何配置,在类、方法、参数上如何加注解,怎样加注解更好?
2. 接口采用了RESTFul风格,路径上的参数和实体中的参数重合了怎么办?
3. 这个接口文档仅仅是接口文档吗?希望能担当测试大任,这样就不用来回切换工具了,真的能如此吗?
4. 2.9.2版本的风格太low怎么办?
SpringBoot2.1.4.RELEASE整合swagger框架,下面一步一步来。
第一步,在pom文件中,引入swagger框架,刚开始使用的是2.2.2版本
io.springfox
springfox-swagger2
2.2.2
io.springfox
springfox-swagger-ui
2.2.2
第二步,添加配置文件
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.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* 在线文档生成,参考网址:https://hacpai.com/article/1534735914420
* https://blog.csdn.net/sanyaoxu_2/article/details/80555328
* @author 程就人生
* @date 2019年5月29日
*/
@Configuration
@EnableSwagger2
public class Swagger2 {
@Bean
public Docket createRestApi() {
ApiInfo apiInfo = new ApiInfoBuilder()
.title("服务接口文档范例")
.description("服务接口文档,严格遵循RESTful API设计规范。")
.contact("程就人生")
.version("1.0")
.build();
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo)
.select()
//以扫描包的方式
.apis(RequestHandlerSelectors.basePackage("com.example.demo.controller"))
.paths(PathSelectors.any())
.build();
}
}
说明:在配置文件中,已经设置了以扫描包的方式来生成接口文档。
这时启动项目,输入地址localhost:8080/swagger-ui.html,可以看到已经生成的接口文档,界面还是相当漂亮的,这只是加了配置,还未加注解的。
第三步,接下来,先了解一下,swagger里面都有哪些注解吧;如果一个注解不加,都是英文的,未免太粗糙,写接口的人能看得懂,对接的未必能看懂,把文档进一步细化一下;
@Api(value=”类的中文说明”, description=”类名称”),类注解,是加在类上的,当然api里面还有其他的参数,暂时没有用到,先忽略,2.9版本只认识tags不认识value
@ApiOperation(value=”方法名称说明”,tags=”方法描述”) 方法上的注解
@ApiImplicitParams({
@ApiImplicitParam(paramType="path", name = "userUid", value = "某个商友信息的uid", required = true, dataType = "String")
}) 方法上需要传递很多参数,可以使用这个进行配置,name必须和方法上的参数保持一致,否则会出现两条
@ApiParam(value=”参数中文名称”,required=true)也可以用这个注解直接在参数的前面增加注解,但是个人更建议使用上一个注解
@ApiIgnore 某个参数需要忽略时,可以使用这个注解
@ApiModel 加在实体类上
@ApiModelProperty(value=”参数中文名称”,required=true)加在实体中的属性上,给属性一个中文描述,让对接人员看得懂;
第四步,实际应用
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.entity.User;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
@Api(value="swagger测试", description="TestController")
@RequestMapping("/user")
@RestController
public class TestController {
@ApiOperation(value="获取用户",notes="根据id获取用户")
@ApiImplicitParams({
@ApiImplicitParam(paramType="path", name = "id", value = "用户id", required = true, dataType = "Integer")
})
@GetMapping("/{id}")
public Object get(@PathVariable Integer id){
User user = new User();
user.setUsername("程就人生");
user.setId(id);
return user;
}
@ApiOperation(value="新增用户")
@PostMapping
public Object add(User user){
return user;
}
@ApiOperation(value="修改用户",notes="根据id修改用户")
@ApiImplicitParams({
@ApiImplicitParam(paramType="path", name = "id", value = "用户id", required = true, dataType = "Integer")
})
@PutMapping("/{id}")
public Object update(@PathVariable Integer id, User user){
return user;
}
@ApiOperation(value="删除用户",notes="根据id删除用户")
@ApiImplicitParams({
@ApiImplicitParam(paramType="path", name = "id", value = "用户id", required = true, dataType = "Integer")
})
@DeleteMapping("/{id}")
public Object delete(@PathVariable Integer id){
return id;
}
}
第五步,查看效果,此时,每个方法上都有了说明,方法中的参数也有了说明,有的接口还可以进行测试;
但是实体类接收不到参数的呀,而且还不知道实体类中有哪些属性,需要手动输入,这个太太不友好了吧,不能算一个清晰的对接文档,这个有没有办法解决呢??
听说还有高级第一点的版本,那就试试吧!
第一步,把pom中的引入文件换成2.9.2版本的
io.springfox
springfox-swagger2
2.9.2
io.springfox
springfox-swagger-ui
2.9.2
第二步,迫不及待的看看效果如何
只想说,天哪,界面也太不友好了吧?但是有一点比较好,实体类里面的属性都是可见的,咦,能不能把功能留下,把界面样式换成2.2.2的呢,试一试吧,一试,效果还不错哟!
结果,配置文件就变成了这样的:
io.springfox
springfox-swagger2
2.9.2
io.springfox
springfox-swagger-ui
2.2.2
效果变成这样的,还是很不错的哟,看一看能不能用来测试,居然可以测试,四个接口都能够测试。
总结:
- 在使用PUT或其他方法的时候,路径上面传递了一个id,/{id}这种的,后面又有实体类的,这时,这个id参数的paramType必须为path,不可以为query,如果写成了query,在接受参数的时候,就会报String转integer的错误,这是因为使用query,把参数拼接在问号后面了,实体里面又有一个,提交给后台的就有两个了,paramType为path在提交后台时,框架默认就会把id封装到实体里面,不会报错了。
- 方法上的某个参数需要忽略时,可以使用@ApiIgnore进行注解,这样在文档里就不会展示了。
- 对于实体里面的属性,想添加描述的,可以在属性上增加@ApiModelProperty(value=”参数中文名称”,required=true),来对参数进行中文描述,还可以添加hidden=true,来设置某个属性不展示。
- 在2.9.2版本中,@Api不识别value,可以把value改成tags
- 如果把方法中的notes改成tags,那么每个方法都会单独展示,而不会显示在类的下面。
- 如果想加个header头,可以在@ApiImplicitParams注解里面,增加一行@ApiImplicitParam(paramType="header", name = "cookie", value = "cookie", required = true, dataType = "String"),设置paramType为header即可。
- 除了使用@ApiImplicitParam注解方法上的参数,还可以使用@ApiParam(value=”参数中文名称”,required=true)直接加在参数前面。
@ApiOperation(value="修改用户名",notes="根据id修改用户名")
@PutMapping
public Object updateUsername(@ApiParam(value="用户id",required=true)@RequestParam Integer id, @ApiParam(value="用户名称",required=true)@RequestParam String username, @ApiIgnore User user){
return user;
}
- 别用debug模式,否则会很慢很慢;
- 可能在某些浏览器下,不能正常展示;
- 不知道屏幕前的您还有什么高见,欢迎点评!