文章目录
Swagger 的使用
前言
后端时代
- 前端:只用管理静态页面:html。
- 后端:模板引擎 JSP,后端是主力
前后端分离时代
主流框架:Vue + SpringBoot
- 后端:后端控制层,服务层,数据访问层【后端团队】
- 前端:前端控制层,视图层【前端团队】 - 伪造后端数据:json假数据。不需要请求后端,仅前端工程已经可以启动并操作。
前后端通过 API 接口进行交互,相对独立,松耦合,可以部署在不同的服务器上
前端后分离存在的问题:
- 前后端集成联调,前端人员和后端人员无法做到“及时协商,尽早解决”,最终导致问题集中爆发;
解决方案:
- 首先制定
schema
(计划的提纲),试试更新最新API
,降低集成风险; - 早期:制定word计划文档;
- 前后端分离: - 后端接口测试工具:
postman
- 后端向前端提供接口,需要实时更新罪行的消息及改动!
Swagger 简介
- 号称世界上最流程的
Api
框架; - 在线自动生成
RestFul Api
文档,该文档与Api
接口信息同步更新; - 直接运行,可在线测试
Api
接口; - 支持多种语言:
Java、Php ...
官网:
https://swagger.io/
使用:
- 在项目中使用 Swagger 需要两个 springfox 依赖: -
springfox-swagger2
-springfox-swagger-ui
SpringBoot 集成 Swagger 2.x
- 新建一个
SpringBoot
项目(web
项目); - 导入依赖
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 --><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.2</version><exclusions><exclusion><!-- io.springfox:springfox-swagger2:2.9.2中依赖了swagger-models的1.5.20版本, 通过排除springfox-swagger2中的swagger-models依赖,导入io.swagger:swagger-models的1.5.22版本. 解决io.swagger.models.parameters.AbstractSerializableParameter实例化参数时example为空字符串""而报错的问题. 因为1.5.20的example只判断是否为null,1.5.22判断了是否为null和"" --><groupId>io.swagger</groupId><artifactId>swagger-models</artifactId></exclusion></exclusions></dependency><!-- https://mvnrepository.com/artifact/io.swagger/swagger-models --><dependency><groupId>io.swagger</groupId><artifactId>swagger-models</artifactId><version>1.5.22</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>
- 编写一个
Hello
工程; - 在主程序上添加注解,开启
Swagger2``````@SpringBootApplication//开启 Swagger2@EnableSwagger2publicclassSwaggerDemoApplication{publicstaticvoidmain(String[] args){SpringApplication.run(SwaggerDemoApplication.class, args);}}
- 测试运行,访问 Swagger UI 界面
http://localhost:8080/swagger-ui.html
SpringBoot 集成 Swagger 3.0
- 新建一个 SpringBoot 项目(web项目);
- 导入依赖
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-boot-starter --><dependency><groupId>io.springfox</groupId><artifactId>springfox-boot-starter</artifactId><version>3.0.0</version></dependency>
- 编写一个
Hello
工程; - 在主程序上添加注解,开启Swagger
@SpringBootApplication//开启 Swagger@EnableOpenApipublicclassSwaggerDemoApplication{publicstaticvoidmain(String[] args){SpringApplication.run(SwaggerDemoApplication.class, args);}}
- 测试运行,访问 Swagger UI 界面 注意:路径同
Swagger 2.x
不同http://localhost:8080/swagger-ui/index.html
配置 Swagger
配置文档信息
Swagger 的 bean 实例:
Docket
Docket.apiInfo(ApiInfo apiInfo)方法
具体配置
@ConfigurationpublicclassSwaggerConfig{/**
* 配置 Swagger Docket 的 bean实例
*
* @return Docket 的 bean实例
*/@BeanpublicDocketdocket(){returnnewDocket(DocumentationType.SWAGGER_2).apiInfo(apiInfo());}/**
* 配置 swagger 的信息:ApiInfo
*
* @return ApiInfo 的 bean实例
*/publicApiInfoapiInfo(){//作者信息Contact contact =newContact("小聪","https://blog.csdn.net/weixin_52610802?type=blog","[email protected]");returnnewApiInfo("Aladdin的SwaggerAPI文档","不负韶华,未来可期","V1.0","https://blog.csdn.net/weixin_52610802?type=blog",
contact,"Apache 2.0","http://www.apache.org/licenses/LICENSE-2.0",newArrayList());}}
配置扫描接口
Docket.select()方法
具体配置
/**
* 配置 Swagger Docket 的 bean实例
*
* @return Docket 的 bean实例
*/@BeanpublicDocketdocket(){returnnewDocket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select()/*
RequestHandlerSelectors 配置扫描接口的方式
basePackage():指定要扫描的包(通常指定包扫描)
any():扫描全部
none():不扫描
withMethodAnnotation():扫描方法上的注解
withClassAnnotation():方法类上的注解
*/.apis(RequestHandlerSelectors.basePackage("com.aladdin.swagger.controller"))/*
PathSelectors 请求路径匹配的方式
regex():正则匹配
any():扫描全部
none():不扫描
ant():路径匹配
*/.paths(PathSelectors.ant("/aladdin/**")).build();}
配置功能是否启动
Docket.enable(boolean externallyConfiguredFlag)方法
具体配置
/**
* 配置 Swagger Docket 的 bean实例
*
* @return Docket 的 bean实例
*/@BeanpublicDocketdocket(){returnnewDocket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())//是否启动 Swagger,如果为 false,则 UI界面提示:【😱 Could not render e, see the console.】,无法在浏览器中访问 Swagger.enable(false).select().apis(RequestHandlerSelectors.basePackage("com.aladdin.swagger.controller")).paths(PathSelectors.ant("/aladdin/**")).build();}
实用案例
- 根据服务环境动态配置 Swagger 是否开启。
/**
* 配置 Swagger Docket 的 bean实例
*
* @return Docket 的 bean实例
*/@BeanpublicDocketdocket(Environment environment){//配置要显示 Swagger 的环境Profiles profiles =Profiles.of("dev","test");//通过environment.acceptsProfiles()方法判断当前是否处在自己设定的环境中boolean flag = environment.acceptsProfiles(profiles);returnnewDocket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())//是否开启 Swagger,如果为 false,则 UI界面提示:【😱 Could not render e, see the console.】,无法在浏览器中访问 Swagger.enable(flag).select().apis(RequestHandlerSelectors.basePackage("com.aladdin.swagger.controller")).paths(PathSelectors.ant("/aladdin/**")).build();}
配置 API 文档的分组
Docket.groupName(String groupName)方法
具体配置
/**
* 配置 Swagger Docket 的 bean实例
*
* @return Docket 的 bean实例
*/@BeanpublicDocketdocket(Environment environment){returnnewDocket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).enable(true)//设置组名称,一个 Docket bean 对应一个组名称.groupName("阿拉丁").apis(RequestHandlerSelectors.basePackage("com.aladdin.swagger.controller"))//.paths(PathSelectors.ant("/aladdin/**")).build();}
配置多个分组
配置多个分组,需配置多个
Docket bean
,每个
bean
配置各自的
groupName
。
packagecom.aladdin.swagger.config;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.core.env.Environment;importorg.springframework.core.env.Profiles;importspringfox.documentation.builders.RequestHandlerSelectors;importspringfox.documentation.service.ApiInfo;importspringfox.documentation.service.Contact;importspringfox.documentation.spi.DocumentationType;importspringfox.documentation.spring.web.plugins.Docket;importjava.util.ArrayList;@ConfigurationpublicclassSwaggerConfig{/**
* 配置 Swagger Docket 的 bean实例
*
* @return Docket 的 bean实例
*/@BeanpublicDocketdocket(Environment environment){returnnewDocket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).enable(true).groupName("阿拉丁").select().apis(RequestHandlerSelectors.basePackage("com.aladdin.swagger.controller"))//.paths(PathSelectors.ant("/aladdin/**")).build();}/**
* 配置 swagger 的信息:ApiInfo
*
* @return ApiInfo 的 bean实例
*/publicApiInfoapiInfo(){//作者信息Contact contact =newContact("阿拉丁","https://blog.csdn.net/weixin_52610802?type=blog","[email protected]");returnnewApiInfo("Aladdin的SwaggerAPI文档","不负韶华,未来可期","V1.0","https://blog.csdn.net/weixin_52610802?type=blog",
contact,"Apache 2.0","http://www.apache.org/licenses/LICENSE-2.0",newArrayList());}@BeanpublicDocketdocket1(){returnnewDocket(DocumentationType.SWAGGER_2).groupName("分组1");}@BeanpublicDocketdocket2(){returnnewDocket(DocumentationType.SWAGGER_2).groupName("分组2");}@BeanpublicDocketdocket3(){returnnewDocket(DocumentationType.SWAGGER_2).groupName("分组3");}}
模型类模块(Models)
Swagger
页面Models
模块为实体类信息- 如果
Swagger
分组扫描的接口返回值存在实体类,则此实体类就会被扫描到该分组中1. 新建实体类publicclassUser{privateString username;privateString password;...}
2. 增加返回值为User
类的接口@RestControllerpublicclassHelloController{@GetMapping("/hello")publicStringhello(){return"Hello";}@PostMapping("/user")publicUseruser(){returnnewUser("123","qwe");}}
3. 重启项目,访问Swagger
页面,则会看见Models
中加载了User
实体类
文档注释
可使用
Swagger
注解为生成的
Api
在线文档添加注释信息
作用范围API使用位置描述返回对象的意义@ApiModel用在返回对象类上对象属性@ApiModelProperty用在出入参数对象的字段上作用范围API使用位置协议集描述@Api用于controller类上协议描述@ApiOperation用在controller的方法上Response集@ApiResponses用在controller的方法上Response@ApiResponse用在 @ApiResponses里边非对象参数集@ApiImplicitParams用在controller的方法上非对象参数描述@ApiImplicitParam用在@ApiImplicitParams的方法里边
@Api
:用在controller上,对controller进行注释;@ApiOperation
:用在API方法上,对该API做注释,说明API的作用;@ApiResponses
:通常用来包含接口的一组响应注解,可以简单的理解为响应注解的集合声明;@ApiResponse
:用在@ApiResponses中,一般用于表达一个错误的响应信息;- code:即httpCode,例如400;- message:信息,例如"请求参数没填好";> 即使只有一个@ApiResponse,也需要使用@ApiResponses包住。@ApiImplicitParams
:用来包含API的一组参数注解,可以简单的理解为参数注解的集合声明;@ApiImplicitParam
:用在 @ApiImplicitParams 注解中,也可以单独使用,说明一个请求参数的各个方面,该注解包含的常用选项有:属性取值作用paramType查询参数类型path以地址的形式提交数据query直接跟参数完成自动映射赋值body以流的形式提交 仅支持POSTheader参数在request headers 里边提交form以form表单的形式提交,仅支持POSTdataType参数的数据类型 只作为标志说明,并没有实际验证LongStringname接收参数名value接收参数的意义描述required参数是否必填true必填false非必填defaultValue默认值代码> 1. form域中的值需要使用@RequestParam获取> 2. header域中的值需要使用@RequestHeader来获取> 3. path域中的值需要使用@PathVariable来获取> 4. body域中的值使用@RequestBody来获取,否则可能出错;而且如果paramType是body,name就不能是body,否则有问题,与官方文档中的“If paramType is "body", the name should be "body"
不符。
Swagger Demo
部分示范代码
packagecom.aladdin.swagger.pojo;importio.swagger.annotations.ApiModel;importio.swagger.annotations.ApiModelProperty;@ApiModel("用户实体类")publicclassUser{@ApiModelProperty(value ="用户名", example ="123123", required =true)privateString username;@ApiModelProperty(value ="密码", example ="aaa123", required =true)privateString password;...}
packagecom.aladdin.swagger.controller;importcom.aladdin.swagger.pojo.User;importio.swagger.annotations.*;importorg.springframework.http.MediaType;importorg.springframework.web.bind.annotation.*;@Api("Hello 控制类")@RestControllerpublicclassHelloController{@ApiOperation("测试query")@ApiResponses({@ApiResponse(code =1000, message ="操作成功"),@ApiResponse(code =9999, message ="系统异常"),@ApiResponse(code =8888, message ="权限不足")})@ApiImplicitParams({@ApiImplicitParam(paramType ="query", dataType ="String", name ="str", value ="字符串", required =true)})@GetMapping("/hello")publicStringhello(String str){return"Hello: "+ str;}@ApiOperation("测试path")@ApiImplicitParams({@ApiImplicitParam(paramType ="path", dataType ="Long", name ="id", value ="信息id", required =true)})@GetMapping("/hello2/{id}")publicStringhello2(@PathVariable("id")Long id){return"Hello: "+ id;}@ApiOperation("测试header")@ApiImplicitParams({@ApiImplicitParam(paramType ="header", dataType ="Long", name ="id", value ="信息id", required =true)})@GetMapping("/hello3")publicStringhello3(@RequestHeader("id")Long id){return"Hello: "+ id;}@ApiOperation("测试form")@ApiImplicitParams({@ApiImplicitParam(paramType ="form", dataType ="Long", name ="id", value ="信息id", required =true)})@PostMapping(value ="/hello4", consumes =MediaType.APPLICATION_FORM_URLENCODED_VALUE)publicStringhello4(@RequestParam("id")Long id){return"Hello: "+ id;}@ApiOperation("测试body")@ApiImplicitParams({@ApiImplicitParam(paramType ="body", dataType ="User", name ="user", value ="用户信息参数", required =true)})@PostMapping("/user")publicUseruser(@RequestBodyUser user){return user;}}
总结
- 可通过 Swagger 给一些比较难理解的属性或者接口增加注释信息;
- 接口文档实时更新;
- 可以在线测试。
注意:出于安全考虑,在正式发布的时候,关闭 Swagger,同时也会节省运行内存。
版权归原作者 不负韶华 未来可期 所有, 如有侵权,请联系我们删除。