官网:https://swagger.io/
我们后端在编写项目的时候,往往都会在代码上加上注释,方便自己以后的修改和维护,和方便别人的理解。但是对对前后端分离的项目
,前端人员写前端代码,后端人员编写后端的代码。这样的话当前端需要调用我们后端的接口的时候,就会来找我们询问参数以及请求的接口路径。如果每次都来问的话就会很繁琐。所以我们要讲我们自己编写的代码,生成一个api文档,里面描述了我们各种接口调用规则,我们只需要将这个api文档交给前端人员即可。前端人员就可以根据我们提供的文档获取到他们需要调用的接口路径以及参数信息。
Open API规范(OpenAPI Specification)以前叫做Swagger规范是RESTAPI的API描述格式。
Open API文件允许描述整个API,包括:
- 每个访问地址的类型。POST 或GET。I
- 每个操作的参数。包括输入输出参数。
- ·认证方法。
- 连接信息,声明,使用团队和其他信息。
Open API规范可以使用YAML或JSON格式进行编写。这样更利于我们和机器进行阅读。
swagger2 是一个规范和完整的框架,用于生成、描述、调用和可视化Restful风格的web服务
作用:
- 接口的文档在线自动生成
- 功能测试
用白话说就是:后端人员写完代码后,不想写开发文档,就嵌用api注解,代码启动,访问固定的路径: ip+端口+路径地址来访问代码。
1、Swagger Editor:基于浏览器编辑器,可以在里面编写Open API规范。类似
Markdown具有实时预览描述文件的功能。(还要自己写,需要会json或者yaml)
2、Swagger UI:将Open API规范呈现为交互式API文档。用可视化U展示描述文件。(注解)
3、Swagger Codegen:将OpenAPI规范生成为服务器存根和客户端库。通过Swagger
Codegen可以将描述文件生成html格式和 cwiki形式的接口文档;同时也可以生成多种
言语的客户端和服务端代码。
4、Swagger Hub:集成了上面所有项月的各个功能,你可以以项目和版本为单位,将你
的描述文件上传到Swagger Hub中。在Swagger Hub中可以完成上面项目的所有工作,
需要注册账号,分免费版和收费版。
使用Swagger时如果碰见版本更新或迭代时,只需要更改Swagger的描述文件即可。
但是在频繁的更新项目版本时很多开发人员认为即使修改描述文件( yml或json )也是一种负担,就直接改代码,这样开发文档的作用就没意义了。
作用:
Spring-fox是根据代码生成接口文档,所以正常的进行更新项目版本,修改代码即可,
而不需要跟随修改描述文件。
Spring-fox利用自身AOP 特性,把 Swagger集成进来,底层还是Swagger。但是使
用起来确方便很多。所以实际开发中使用springfox。
官网:http://springfox.github.io/springfox/
源码:https://github.com/springfox/springfox
▶导入依赖:pom.xml,自己库里的其他版本都行
io.springfox springfox-swagger-ui 2.9.2 io.springfox springfox-swagger2 2.9.2 compile
▶先写一个controller,里面有三种请求方法,自定义、get、post
@RestController//方法中所有的返回值都相当于加了一个@ResponseBody
@RequestMapping("/user")
public class MyController {@PostMapping("/getUserById")//post请求public String post(Integer id){return "post:根据id获取User";}@GetMapping("/getUsers")//get请求public String get(){return "get:获取所有的User";}@RequestMapping("/req")//这种请求方式是不限制请求方式的,任意请求方式都可以访问public String req(String m){return "request!!!";}
}
▶在启动类上注解@EnableSwagger2
@EnableSwagger2
springfox提供的注解,代表swagger2相关技术开启,会扫描当前类所在包,及子包中所有的类型中的注解,
▶运行启动类,访问路径:http://localhost:8080/swagger-ui.html
访问swagger-ui.html后可以在页面中着到所有需要生成接口文档的控制器名称
- basic-error-controller中:是springBoot内部的,关于错误提示的controller。
- MyController:自己写的。其中有get和post的请求,还有一个没有限制请求方式的方法。
- ……
【扫描我们编写的所有的控制器,扫描约束,显示在视图中(上面截图)】
@GetMapping("/get")
==这两个方法是等价的==
@RequestMapping(method = {RequestMethod. GET})
Swagger-UI:
- 显示控制器
- 显示控制器中的请求方法(路径地址的处理)、参数、名字等
- 简单测试请求,以及返回的响应结果描述
上面提到过在视图中有些东西可以修改,与本项目的内容无关,就需要通过配置类来实现修改
@Configuration
public class SwaggerConfig1 {/*** 创建Docket类型的对象。并使用spring容器管理。* Docket是Swagger中的全局配置对象。* @return docket*/@Beanpublic Docket createRestApi() {Docket docket = new Docket(DocumentationType.SWAGGER_2);//API帮助文档的描述信息ApiInfo apiInfo = new ApiInfoBuilder().contact( //配置swagger文档主体内容new Contact("简单示例Swagger的开发文档", //是文档的发布者名称"http://www/xxxx", //是文档发布者的网站地址。企业网站"admin@bjsxt.com") //文档发布者的电子邮箱).title("swagger文档标题").description("swagger2 是一个规范和完整的框架,用于生成、描述、调用和可视化Restful风格的web服务,开发帮助文档").version("1.1").build();docket.apiInfo(apiInfo);return docket;}
}
文档运行路径:http://localhost:8080/swagger-ui.html,对比上张图,观察上下文配置api描述信息都是修改的文档的哪个地方。
docket.select() //获取Docket中的选择器。返回ApiSelectorBuilder。构建选择器的。如:扫描什么包的注解.apis(RequestHandlerSelectors.basePackage("com.wxy.springboot_swagger.controller")); //规则,设定扫描哪个包(包含子包)
属性value定义具体的资源,常用:
- ElementType.METHOD可以定义在方法上
- EIementType.TYPE可以定义在类型上
- ElementType.FIELD可以定义在属性上
- ElementType.PARAMETER可以定义在方法参数上
- ……
属性value-定义具体的生效标记三个:
- RetentionPolicy.RUNTIME-运行时有效(常用)
- RetentionPolicy.SOURCE一源码中有效
- RetentionPolicy.CLASS-字节码有效
1.写一个自定义注解类
/*** @interface 代表当前是一个注解类*/
@Target(value = {ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotationSwagger {//自定义注解中的属性。相当于@MyAnnotationSwagger(value="")String value() default "";
}
2.自定义注解的使用:实现controller中“req()”方法不在文档视图中显示
要在controller中req()的方法上添加注解@MyAnnotationSwagger
在配置类中设置规则匹配器(内部是静态方法)
docket = docket.select() //获取Docket中的选择器。返回ApiSelectorBuilder。构建选择器的。如:扫描什么包的注解//.apis(RequestHandlerSelectors.basePackage("com.wxy.springboot_swagger2.controller")) //规则,设定扫描哪个包(包含子包).apis(Predicates.not( //取反:false->true true->falseRequestHandlerSelectors.withMethodAnnotation( //withMethodAnnotation:当方法上有注解时返回trueMyAnnotationSwagger.class)) //方法有什么注解的时候返回true).build(); //重新构建Docket对象
测试:只有get和post两个方法了
Predicates.and()
.paths(PathSelectors.regex("/swagger/.*") //使用正则表达式,约束生成API文档的路径地址。//控制器访问路径以swagger开头的。@RequestMapping("/swagger")
)
.paths(Predicates.or( //多个规则符合任意一个即可通过。PathSelectors.regex(pathRegex:"/swagger/.*"),PathSelectors.regex(pathRegex:"/swagger2/.*"),PathSelectors.regex(pathRegex:"/.*"))
)
swagger通过注解表明该接口会生成文档,包括接口名、请求方法、参数、返回信息的等等。
- @Api:修饰整个类,描述Controller的作用。
- tags:给当前类型定义别名,可以有多个。定义几个别名,在ui视图中就显示几个控制器访问菜单。
- description:定义描述
- @ApiOperation:描述一个类的一个方法,或者说一个接口
- @ApiParam:单个参数描述
- @ApiModel:描述实体类型,用对象来接收参数
- @ApiModelProperty:用对象接收参数时,描述对象的一个字段
- @ApiImplicitParam:在方法上描述方法的一个请求参数
- @ApiImplicitParams:多个请求参数
- @ApiIgnore:忽略当前注解描述的方法或类型,不生成api帮助文档
@RestController
@RequestMapping("/user")
@Api(tags = {"MyController","Swagger测试控制器"},description = "测试API类型描述信息")
public class MyController {……
}
@PostMapping("/getUserById")//post请求@ApiOperation(value = "post方法,执行新增操作", notes = "Swagger学习使用-处理POST请求的方法")public String post(Integer id){return "post:根据id获取User";}
@GetMapping("/test")
@ApiImplicitParam(name = "m", value = "m参数描述",required = false, paramType = "字符串",dataType = "明值对")
public String test(String m,String n){return "request!!!";
}
@ApiImplicitParams(value = {@ApiImplicitParam(name = "m", value = "m参数描述",required = false, paramType = "字符串",dataType = "明值对"),@ApiImplicitParam(name = "n", value = "n参数描述",required = true, paramType = "字符串",dataType = "明值对")})
/*** ApiModel 描述一个实体类型。这个实体类型如果成为任何一个生成api帮助文档方法的* 返回值类型的时候,此注解被解析。*/
@ApiModel(value = "自定义实体类",description = "MyEntity存储用户数据")
public class MyEntity implements Serializable {@ApiModelProperty(value = "主键",name = "主键(id)",required = false,example = "1",hidden = false)private String id;@ApiModelProperty(value = "姓名",name = "姓名(name)",required = true,example = "张三",hidden = false)private String name;@ApiModelProperty(value = "密码",name = "密码(password)",required = true,example = "123456",hidden = false)private String password;public MyEntity(){}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;MyEntity myEntity = (MyEntity) o;return Objects.equals(id, myEntity.id) && Objects.equals(name, myEntity.name) && Objects.equals(password, myEntity.password);}@Overridepublic int hashCode() {return Objects.hash(id, name, password);}
}
返回类型是实体类类型:
@RequestMapping("/testEntity")public MyEntity testEntity(){return new MyEntity();}