swagger笔记
简介
前后端分离
主流:前端Vue+后端SpringBoot
- 后端:后端控制层,服务层,数据访问层【后端团队】
- 前端:前端控制层,视图层【前端团队】
- 前后端如何交互?==> API
- 前后端相对独立,松耦合
- 前后端甚至可以部署在不同的服务器上;
遇到的问题:
- 前后端集成联调,前端人员和后端人员无法做到“及时协商,尽早解决”,最终导致问题集中爆发
解决方案:
- 首先制定schema【计划的提纲】,事实更新最新API,降低集成的风险
- 早些年:制定word计划文档
- 前后端分离:
- 前端测试后端接口:postman
- 后端提供接口,需要实时更新最新的消息及改动
新的问题:
- 前端经常抱怨后端给的接口文档与实际情况不一致
- 后端编写和维护接口文档很麻烦,经常来不及更新
- swagger提供了解决方案
Swagger
- 号称世界上最流行的Api框架
- RestFul Api 文档在线自动生成工具 => API文档和API定义同步更新
- 直接运行,在线测试API接口
- 支持多种语言(java、php…)
我们可以使用swagger工具帮助我们团队和企业,更简单地进行API接口开发。
官网:https://swagger.io/
SpringBoot集成
第一步: 新建一个SpringBoot—Web项目
第二步: 引入依赖(最新版是3.0版本,但和前面版本有不少区别,而且2.9用的人最多)
<!-- 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>
第三步: 编写一个hello工程
第四步: 配置Swagger ==> config
@Configuration
@EnableSwagger2 // 开启swagger2
public class SwaggerConfig {
}
**第五步 ** 测试运行:http://localhost:8080/swagger-ui.html
配置Swagger
配置Swagger信息
Swagger有一个bean实例:Docket
@Configuration
@EnableSwagger2
public class SwaggerConfig {
// 配置了swagger的bean实例
@Bean
public Docket docket() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo());
}
// 配置Swagger文档信息=apiInfo, 覆盖了默认的信息
private ApiInfo apiInfo() {
// contact: 作者信息
Contact contact = new Contact(
"重明鸟",
"https://blog.csdn.net/Chongming_bird?spm=1000.2115.3001.5343",
"2428028346@qq.com"
);
return new ApiInfo(
"重明鸟的Swagger笔记", // 重要的信息
"这是一个描述", // 重要的信息
"v1.0",
"www.baidu.com",
contact,
"Apache 2.0",
"http://www.apahce.org/licenses/LICENSE-2.0",
new ArrayList()
);
}
}
运行结果:
配置扫描接口
让swagger扫描特定的接口:Docket.select()
// 配置了swagger的bean实例
@Bean
public Docket docket() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
// RequestHandlerSelectors,配置扫描接口的方式
.apis(RequestHandlerSelectors.basePackage("com.dm.swagger.controller"))
.build();
}
测试结果:
.basePackage()
:指定包扫描
.any()
:扫描全部
.none()
:全部扫描
.withClassAnnotation()
:扫描类上的注解
-
.withMethodAnnotation(RestContorller.class)
即只扫描带有@RestController注解的类 -
.withMethodAnnotation()
:扫描方法上的注解 -
paths()
:过滤什么路径\paths(PathSelectors.ant("/dm/**"))
:/dm下的类全都不扫描
配置Swagger启动
@Bean
public Docket docket() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
// 重点 ↓
.enable(true)
// 重点 ↑
.select()
.apis(RequestHandlerSelectors.basePackage("com.dm.swagger.controller"))
.build();
}
Docket(DocumentationType.SWAGGER_2).enable(true)
:如果为false,则swagger不启用
如果希望swagger在生产环境中使用,在发布的时候不使用:
- 判断是不是生产环境 flag = flase
- 注入
enable(flag)
方法:
-
配置springboot的配置文件:
application.properties
开发环境配置文件:
application-dev.properties
发布环境配置文件:
application-pro.properties
#此时的使用的环境是application-dev.properties
spring.profiles.active=dev
- 在
SwaggerConfig
中获取项目的环境
@Bean
// 传入了Environment
public Docket docket(Environment environment) {
// 设置要显示的swagger环境
Profiles profiles = Profiles.of("dev");
//获取项目的环境:通过环境监听判断是否处在自己设定的环境当中
boolean b = environment.acceptsProfiles(profiles);
...
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
// 重点 ↓ 这里传入判断的环境是否为dev来选择是否开启swagger
.enable(b)
// 重点 ↑
.select()
.apis(RequestHandlerSelectors.basePackage("com.dm.swagger.controller"))
.build();
}
SpringBoot绕过拦截器
public void addInterceptors(InterceptorRegistry registry) {
// 定义排除swagger访问的路径配置
String[] swaggerExcludes = {"/swagger-ui.html","/swagger-resources/**","/webjars/**"};
// 自定义去除的路径
String[] myExcludes = {"/index.html","/","/user/login","/asserts/**"};
registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/**").excludePathPatterns(swaggerExcludes).excludePathPatterns(myExcludes);
}
配置分组
return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) // 重点↓ .groupName("重明鸟") // 重点↑ .enable(true) .select() .apis(RequestHandlerSelectors.basePackage("com.dm.swagger.controller")) .build();
测试:
如何配置多个组:
配置多个docket实例
@Bean public Docket docketA() { return new Docket(DocumentationType.SWAGGER_2).groupName("分组A"); } @Bean public Docket docketB() { return new Docket(DocumentationType.SWAGGER_2).groupName("分组B"); } @Bean public Docket docketB() { return new Docket(DocumentationType.SWAGGER_2).groupName("分组C"); }
测试结果:
配置实体类
- 编写实体类
// @ApiModel和@ApiModelProperty来给生成的文档添加注释信息@ApiModel("用户实体类")@Datapublic class User { @ApiModelProperty("用户名") private String username; @ApiModelProperty("密码") private String password;}
- 编写controller
// 只要我们的接口中,返回值中存在实体类,他就会被扫描到swagger中@RequestMapping(value = "/user")public User user(){ return new User();}
测试结果:
- 不加注释信息
- 加入注释信息
配置携带Token和去除自带状态码
@Bean public Docket docket(Environment environment) { // 配置带token测试 ParameterBuilder ticketPar = new ParameterBuilder(); List<Parameter> pars = new ArrayList<Parameter>(); //Token 名 ticketPar.name(AnswerConstant.HTTP_HEADER_ANSWER_ACCESS_TOKEN).description("token") .modelRef(new ModelRef("string")).parameterType("header") //header中的token参数非必填,传空也可以 .required(false).build(); pars.add(ticketPar.build()); Profiles profiles = Profiles.of("meng"); /* true 表示再 false 表示不在 */ boolean open = environment.acceptsProfiles(profiles); return new Docket(DocumentationType.SWAGGER_2) ... // 配置携带token访问 .globalOperationParameters(pars) // 去掉swagger自带的状态码 .useDefaultResponseMessages(false) ; }
常用注解
类
controller层
-
@Api()
用于类
表示标识这个类是swagger的资源@Api(tags = "这是一个Hello接口")@RestControllerpublic class UserController {}
实体类
-
@ApiModel()
用于类
表示对类进行说明,用于参数用实体类接收 -
@ApiModelProperty()
用于方法,字段
表示对model属性的说明或者数据操作更改
-
方法
-
@ApiOperation()
用于方法
描述一个请求的操作@ApiOperation(value = "简单描述方法", notes = "详细描述方法") @GetMapping(value = "/hello") public String hello(){}
参数
-
@ApiParam()
用于方法,参数,字段说明;
- name–参数名
- value–参数说明
- required–是否必填
public String hello(@ApiParam(name ="用户名", value = "这是用户名", required = true) String username){ return "hello"; }
-
@ApiIgnore()
用于类,方法,方法参数
表示这个方法或者类被忽略,即不在文档中显显示 -
@ApiImplicitParam()
用于方法
表示单独的请求参数- name–参数名
- value–参数说明
- dataType–数据类型
- paramType–参数类型
- example–举例说明
-
@ApiImplicitParams()
用于方法,包含多个 @ApiImplicitParam
@GetMapping(value = "/user") @ApiImplicitParams( { @ApiImplicitParam(name = "name", value = "用户名", dataType = "String", paramType = "query", example = "重明鸟"), @ApiImplicitParam(name = "age", value = "年龄", dataType = "int", paramType = "query", example = "20") } ) public User user(String name, int age){ return new User(); }
状态码
注意:注解配置状态码前请先去掉自带的状态码!
去掉自带的状态码:
new Docket() //More config .useDefaultResponseMessages(false) //<-- this should be false...;
@ApiResponse(code = xxx, message = "xxx")
@ApiResponses()
@ApiResponses({ @ApiResponse(code = 1000, message = "非HTTP状态码,返回值JSON code字段值,描述:成功"), @ApiResponse(code = 401, message = "非HTTP状态码,返回值JSON code字段值,描述:无token") })
- 设置全局状态码
打开SWAGGER配置类
,找到初始化DOCKET
的地方。添加如下代码
弄懂了再写
Swagger接口测试
像postman那样用就好了
总结
- swagger可以帮我们生成接口文档,方便前端调阅测试
- swagger可以帮我们测试接口
- 正式发布的时候一定一定一定要记得关闭swagger,不然被用户访问到会很不安全!
配置文件模板
以后做项目直接复制粘贴
/** * @author HaiPeng Wang * @date 2021/7/14 16:28 * @Description: */@EnableSwagger2 //开启Swagger 注解@Configurationpublic class SwaggerConfig { //配置Swagger 的Docket 信息 @Bean public Docket docket(Environment environment) { // 配置带token测试 ParameterBuilder ticketPar = new ParameterBuilder(); List<Parameter> pars = new ArrayList<Parameter>(); //Token 名 ticketPar.name(AnswerConstant.HTTP_HEADER_ANSWER_ACCESS_TOKEN).description("token") .modelRef(new ModelRef("string")).parameterType("header") //header中的token参数非必填,传空也可以 .required(false).build(); pars.add(ticketPar.build()); Profiles profiles = Profiles.of("meng"); /* true 表示再 false 表示不在 */ boolean open = environment.acceptsProfiles(profiles); return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) //配置文档信息 .groupName("ChongMing") // 配置分组 .enable(open) //wang是我的开发环境,如果是这个环境的话就打开swagger,而是不是这个环境是再spring.profiles.active 配置的 .select() .apis(RequestHandlerSelectors.basePackage("com.yvnze.ydyp.modules.user.controller")) .paths(PathSelectors.ant("/**")) //允许访问所有映射下的接口 .build() // 去掉swagger自带的状态码 .useDefaultResponseMessages(false) // 配置携带token .globalOperationParameters(pars) ; } private ApiInfo apiInfo() { /** * ApiInfo 对象并没有构造方法所以必须用构造器 */ //作者信息 Contact DEFAULT_CONTACT = new Contact("云泽", "http://没有.com", "baizhouWHP@163.com"); return new ApiInfo( "云牍云篇", //Swagger APi文档标题 "云顶书院云牍云篇项目API文档",//Api 文档描述 "1.1", //文档版本 "云泽项目组", (Contact) DEFAULT_CONTACT, "Apache 2.0",//开源版本号 "http://www.apache.org/licenses/LICENSE-2.0", new ArrayList<>() ); }}