swagger介绍:
相信无论是前端还是后端开发,都被接口文档所折磨过,如今大多项目采用前后的分离,前端与后端的交互变成了接口文档,而维护接口文档也需要很多的时间,接口文档随着版本的更新迭代不能实时更新往往就跟不上代码了,发现了问题即而就要去解决,我们的swagger就能很好的解决这个问题。
swagger 是一个 api 文档维护组织,后来成为了 Open API 标准的主要定义者,现在最新的版本为17年发布的 Swagger3(Open Api3)。国内绝大部分人还在用过时的swagger2(17年停止维护并更名为swagger3)swagger2的包名为 io.swagger,而swagger3的包名为 io.swagger.core.v3。
使用 swagger3 注解代替 swagger2 的(可选)
这一步是可选的,因为改动太大,故 springfox对旧版的 swagger做了兼容处理。 但不知道未来会不会不兼容,这里列出如何用 swagger 3 的注解(已经在上面引入)代替 swagger 2 的 (注意修改 swagger 3 注解的包路径为io.swagger.v3.oas.annotations.)
对应关系为:
常用注解
Swagger注解 简单说明
@Api(tags = “xxx模块说明”) 作用在模块类上
@ApiOperation(“xxx接口说明”) 作用在接口方法上
@ApiModel(“xxxPOJO说明”) 作用在模型类上:如VO、BO @ApiModelProperty(value = “xxx属性说明”,hidden = true) 作用在类方法和属性上,hidden设置为true可以隐藏该属性
@ApiParam(“xxx参数说明”) 作用在参数、方法和字段上,类似@ApiModelProperty
使用上的区别
新版本和老版本的区别主要体现在以下 4 个方面:
1:依赖项的添加不同:新版本只需要添加一项,而老版本需要添加两项;
2:启动 Swagger 的注解不同:新版本使用的是 @EnableOpenApi,而老版本是 @EnableSwagger2;
3:Docket(文档摘要信息)的文件类型配置不同:新版本配置的是 OAS_3,而老版本是 SWAGGER_2;
4:Swagger UI 访问地址不同:启动项目,
访问地址:http://localhost:8080/swagger-ui/index.html
,(注意swagger2.x版本中访问的地址的为: http://localhost:8080/swagger-ui.html)
Ps:在使用swagger的时候,通常需要使用【@ApiParam】注解指定接口中参数的名字,特别是接口是post请求且参数使用了@RequestParam注解时
踩坑指南
使用springboot2.6.x版本与swagger使用时可能会有冲突会报一个错误documentationPluginsBootstrapper‘; java.lang.NullPointerException
解决思路:
1.降低springboot的版本可以避开这个错误
2.网上引用这个博主的解决方案可以成功解决02.Spring Boot 2.6.x整合Swagger启动失败报错问题解决(治标还治_这是王乃醒的博客-CSDN博客
话不多说上代码看效果:
一 .springboot2.52+swagger3.0使用
1.应用主类增加注解@EnableOpenApi
2.Maven项目中引入springfox-boot-starter依赖
<!--swagger3.0-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
3.创建配置文件
-
创建SwaggerConfiguration类配置文件 , 使用@EnableOpenApi注解,启用swagger配置,可以设置配置相关参数
package com.swaggerdemo.demo.config; import org.springframework.boot.SpringBootVersion; 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.oas.annotations.EnableOpenApi; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.Contact; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import java.util.Arrays; import java.util.LinkedHashSet; import java.util.Set; @EnableOpenApi @Configuration public class SwaggerConfiguration { private final SwaggerProperties swaggerProperties; public SwaggerConfiguration(SwaggerProperties swaggerProperties) { this.swaggerProperties = swaggerProperties; } @Bean public Docket createRestApi() { return new Docket(DocumentationType.OAS_30).pathMapping("/") // 定义是否开启swagger,false为关闭,可以通过变量控制 .enable(swaggerProperties.getEnable()) // 将api的元信息设置为包含在json ResourceListing响应中。 .apiInfo(apiInfo()) // 接口调试地址 .host(swaggerProperties.getTryHost()) // 选择哪些接口作为swagger的doc发布 .select() .apis(RequestHandlerSelectors.any()) .paths(PathSelectors.any()) .build() // 支持的通讯协议集合 .protocols(newHashSet("https", "http")); } /** * API 页面上半部分展示信息 */ private ApiInfo apiInfo() { return new ApiInfoBuilder().title(swaggerProperties.getApplicationName() + " Api Doc") .description(swaggerProperties.getApplicationDescription()) .contact(new Contact("lighter", null, "123456@gmail.com")) .version("Application Version: " + swaggerProperties.getApplicationVersion() + ", Spring Boot Version: " + SpringBootVersion.getVersion()) .build(); } @SafeVarargs private final <T> Set<T> newHashSet(T... ts) { if (ts.length > 0) { return new LinkedHashSet<>(Arrays.asList(ts)); } return null; } }
如需要详细配置文件配置请参考:
一个完整详细的springfox swagger配置示例:
import io.swagger.models.auth.In;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.springframework.boot.SpringBootVersion;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import java.lang.reflect.Field;
import java.util.*;
@EnableOpenApi
@Configuration
public class SwaggerConfiguration implements WebMvcConfigurer {
private final SwaggerProperties swaggerProperties;
public SwaggerConfiguration(SwaggerProperties swaggerProperties) {
this.swaggerProperties = swaggerProperties;
}
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.OAS_30).pathMapping("/")
// 定义是否开启swagger,false为关闭,可以通过变量控制
.enable(swaggerProperties.getEnable())
// 将api的元信息设置为包含在json ResourceListing响应中。
.apiInfo(apiInfo())
// 接口调试地址
.host(swaggerProperties.getTryHost())
// 选择哪些接口作为swagger的doc发布
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build()
// 支持的通讯协议集合
.protocols(newHashSet("https", "http"))
// 授权信息设置,必要的header token等认证信息
.securitySchemes(securitySchemes())
// 授权信息全局应用
.securityContexts(securityContexts());
}
/**
* API 页面上半部分展示信息
*/
private ApiInfo apiInfo() {
return new ApiInfoBuilder().title(swaggerProperties.getApplicationName() + " Api Doc")
.description(swaggerProperties.getApplicationDescription())
.contact(new Contact("lighter", null, "123456@gmail.com"))
.version("Application Version: " + swaggerProperties.getApplicationVersion() + ", Spring Boot Version: " + SpringBootVersion.getVersion())
.build();
}
/**
* 设置授权信息
*/
private List<SecurityScheme> securitySchemes() {
ApiKey apiKey = new ApiKey("BASE_TOKEN", "token", In.HEADER.toValue());
return Collections.singletonList(apiKey);
}
/**
* 授权信息全局应用
*/
private List<SecurityContext> securityContexts() {
return Collections.singletonList(
SecurityContext.builder()
.securityReferences(Collections.singletonList(new SecurityReference("BASE_TOKEN", new AuthorizationScope[]{new AuthorizationScope("global", "")})))
.build()
);
}
@SafeVarargs
private final <T> Set<T> newHashSet(T... ts) {
if (ts.length > 0) {
return new LinkedHashSet<>(Arrays.asList(ts));
}
return null;
}
/**
* 通用拦截器排除swagger设置,所有拦截器都会自动加swagger相关的资源排除信息
*/
@SuppressWarnings("unchecked")
@Override
public void addInterceptors(InterceptorRegistry registry) {
try {
Field registrationsField = FieldUtils.getField(InterceptorRegistry.class, "registrations", true);
List<InterceptorRegistration> registrations = (List<InterceptorRegistration>) ReflectionUtils.getField(registrationsField, registry);
if (registrations != null) {
for (InterceptorRegistration interceptorRegistration : registrations) {
interceptorRegistration
.excludePathPatterns("/swagger**/**")
.excludePathPatterns("/webjars/**")
.excludePathPatterns("/v3/**")
.excludePathPatterns("/doc.html");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
4.自定义swagger配置类SwaggerProperties
package com.swaggerdemo.demo.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties("swagger")
public class SwaggerProperties {
/**
* 是否开启swagger,生产环境一般关闭,所以这里定义一个变量
*/
private Boolean enable;
/**
* 项目应用名
*/
private String applicationName;
/**
* 项目版本信息
*/
private String applicationVersion;
/**
* 项目描述信息
*/
private String applicationDescription;
/**
* 接口调试地址
*/
private String tryHost;
public Boolean getEnable() {
return enable;
}
public void setEnable(Boolean enable) {
this.enable = enable;
}
public String getApplicationName() {
return applicationName;
}
public void setApplicationName(String applicationName) {
this.applicationName = applicationName;
}
public String getApplicationVersion() {
return applicationVersion;
}
public void setApplicationVersion(String applicationVersion) {
this.applicationVersion = applicationVersion;
}
public String getApplicationDescription() {
return applicationDescription;
}
public void setApplicationDescription(String applicationDescription) {
this.applicationDescription = applicationDescription;
}
public String getTryHost() {
return tryHost;
}
public void setTryHost(String tryHost) {
this.tryHost = tryHost;
}
}
6.编写测试接口(采用的lombok插件):
实体类编写:
package com.swaggerdemo.demo.entity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Schema(name = "demo实体类")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Demo {
@Schema(name = "id")
private Integer id;
@Schema(name = "name")
private String name;
}
Controller类:
package com.swaggerdemo.demo.Controller;
import com.swaggerdemo.demo.config.JsonResult;
import com.swaggerdemo.demo.entity.Demo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Tag(name = "test接口类")
@RestController
public class TestController {
@Operation(summary = "test接口描述")
@RequestMapping("/test")
public String test(){
return "success";
}
@GetMapping("/get/{id}")
@Operation(summary = "根据用户唯一标识获取用户信息")
public JsonResult<Demo> getUserInfo( @Parameter(description = "用户唯一标识") Integer id) {
// 模拟数据库中根据id获取User信息
Demo user = new Demo( id,"123456");
return new JsonResult(user);
}
}
实现效果:
资料
swagger 官网:swagger.io(https://swagger.io/) springfox 官网:springfox(http://springfox.github.io/springfox/) springfox Github 仓库:springfox / springfox(https://github.com/springfox/springfox) springfox-demos Github 仓库:springfox / springfox-demos(https://github.com/springfox/springfox-demos) springfox Maven 仓库:Home » io.springfox(https://mvnrepository.com/artifact/io.springfox)
Swagger2.0使用
采用springboot2.52+swagger2.9.2
1.导入maven依赖:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
2.编写swagger2.0的配置文件
package com.wq.springbootdemo.config;
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;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
// 指定构建api文档的详细信息的方法:apiInfo()
.apiInfo(apiInfo())
.select()
// 指定要生成api接口的包路径,这里把controller作为包路径,生成controller中的所有接口
.apis(RequestHandlerSelectors.basePackage("com.wq.springbootdemo.Controller"))
.paths(PathSelectors.any())
.build();
}
/**
* 构建api文档的详细信息
* @return
*/
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
// 设置页面标题
.title("Spring Boot集成Swagger2接口总览")
// 设置接口描述
.description("Spring Boot集成Swagger2测试")
// 设置联系方式
.contact("wq," + "qq: 2964906495")
// 设置版本
.version("1.0")
// 构建
.build();
}
}
3.编写实体类
package com.wq.springbootdemo.entity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@ApiModel(value = "demo实体类")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Demo {
@ApiModelProperty(value = "id")
private Integer id;
@ApiModelProperty(name = "name")
private String name;
}
}
4.编写controller
package com.wq.springbootdemo.Controller;
import com.wq.springbootdemo.config.JsonResult;
import com.wq.springbootdemo.entity.Demo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@Api(value = "测试Controller")
@RestController
public class TestController {
@GetMapping("/get/{id}")
@ApiOperation(value = "根据用户唯一标识获取用户信息")
public JsonResult<Demo> getUserInfo(@PathVariable @ApiParam(value = "用户唯一标识") Integer id) {
// 模拟数据库中根据id获取User信息
Demo user = new Demo(id, "123456");
return new JsonResult(user);
}
}