swagger2官网
Swagger 是一个规范和完整的框架,用于生成、描述、功能调用测试和可视化 RESTful 风格的在线的接口文档工具。
Swagger 是一套基于 OpenAPI 规范(OpenAPI Specification,OAS)构建的开源工具。
Swagger 提供了一套通过代码和注解自动生成可视化的 RESTful 风格的API文档,符合 RESTful API设计的行业标准。
OAS本身是一个API规范,它用于描述一整套API接口,包括一个接口是哪种请求方式、哪些参数、哪些header等,都会被包括在这个文件中。它在设计的时候通常是YAML格式,这种格式书写起来比较方便,而在网络中传输时又会以json形式居多,因为json的通用性比较强。
由于 Spring的流行,Marty Pitt编写了一个基于 Spring的组件 swagger-springmvc,用于将 Swagger集成到 SpringMVC中来,而 Springfox则是从这个组件发展而来。
通常 Spring Boot项目整合 Swagger2需要用到两个依赖:springfox-swagger2和springfox-swagger-ui,用于自动生成swagger文档。
<dependency>
<groupId>com.github.xiaoymingroupId>
<artifactId>swagger-bootstrap-uiartifactId>
<version>1.9.6version>
dependency>
更多注解和使用说明,请查看Github:https://github.com/swagger-api/swagger-core/wiki/Annotations
@Api:用在请求的类上,表示对类的说明(不配置默认是按类名驼峰变下划线显示)
value:该参数没什么意义,在UI界面上也看到,所以不需要配置"
tags:说明该类的作用,可以在UI界面上看到的注解
description:对api资源的描述
basePath:基本路径
position:如果配置多个Api 想改变显示的顺序位置
produces:如 “application/json, application/xml”
consumes:如 “application/json, application/xml”
protocols:协议类型,如: http, https, ws, wss.
authorizations:高级特性认证时配置
hidden:配置为true ,将在文档中隐藏
@ApiOperation:用在请求的方法上,说明方法的用途、作用
value:说明方法的用途、作用
tags:如果设置这个值、value的值会被覆盖
notes:方法的备注说明
description:对api资源的描述
@ApiImplicitParams:用在请求的方法上,表示一组参数说明
@ApiImplicitParam:用在@ApiImplicitParams注解中,指定一个请求参数的各个方面
name:参数名
value:参数的汉字说明、解释
required:参数是否必须传
paramType:参数放在哪个地方
· header --> 请求参数的获取:@RequestHeader
· query --> 请求参数的获取:@RequestParam
· path(用于restful接口)--> 请求参数的获取:@PathVariable
· div(不常用)
· form(不常用)
dataType:参数类型,默认String,其它值dataType="Integer"
defaultValue:参数的默认值
@ApiParam() 用于方法,参数,字段说明;表示对参数的添加元数据(说明或是否必填等)
name:参数名
value:参数说明
required:是否必填
@ApiResponses:用在请求的方法上,表示一组响应
@ApiResponse:用在@ApiResponses中,一般用于表达一个错误的响应信息
code:数字,例如400
message:信息,例如"请求参数没填好"
response:抛出异常的类
@ApiModel:用于pojo类上,描述一个Model的信息
(一般用在请求参数无法使用@ApiImplicitParam注解进行描述的时候,比如使用@RequestBody这样的场景)
@ApiModelProperty:用在属性上,描述一个model的属性
@ApiIgnore:注解类、参数、方法,注解后将不在Swagger UI中显示
SpringBoot 2.3.12.RELEASE版本项目集成 Swagger2的步骤:
<dependency>
<groupId>io.springfoxgroupId>
<artifactId>springfox-swagger2artifactId>
<version>2.9.2version>
dependency>
<dependency>
<groupId>io.springfoxgroupId>
<artifactId>springfox-swagger-uiartifactId>
<version>2.9.2version>
dependency>
在项目中开启了 Swagger的功能:添加一个@EnableSwagger2注解接口。可以添加在SpringBoot的启动类上或者Swagger2配置类上。
在config文件夹下,添加一个Swagger2Config类。
添加 @EnableSwagger2注解。
使用 @Bean,在启动时初始化,返回实例 Docket(Swagger API 摘要对象)配置相关映射路径和要扫描的接口的位置等信息
@EnableSwagger2
@Configuration
public class Swagger2Config {
/**
* 访问官方文档 UI界面:http://127.0.0.1:18080/swagger-ui.html
*
* 增强版 UI界面:http://127.0.0.1:18080/doc.html
*/
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2) // SWAGGER_2
.apiInfo(apiInfo())
.select()
// 此处自行修改为自己的 Controller 包路径
.apis(RequestHandlerSelectors.basePackage("com.charge.xxx.controller"))
.paths(PathSelectors.any())
.build()
.globalOperationParameters(setGlobalParameters());
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder().title("XXX 项目接口文挡")
.description("本文档描述 XXX平项目接口定义")
.version("1.0")
.termsOfServiceUrl("") //文档生成的主页地址
.contact(new Contact("author", null, "[email protected]"))
.build();
}
/**
* 设置全局参数
*
* @return
*/
private List<Parameter> setGlobalParameters() {
List<Parameter> globalParameterList = new ArrayList<>();
//Header中必需 token参数。非必填,传空也可以,一般业务登录拦截器校验 token是否合法
ParameterBuilder tokenBuilder = new ParameterBuilder();
tokenBuilder.name("token").description("用户 TOKEN参数")
.required(false)// 非必填
.modelRef(new ModelRef("string"))
.parameterType("header");
globalParameterList.add(tokenBuilder.build());
return globalParameterList;
}
}
看具体项目具体配置
package com.open.web.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.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class Swagger2Config {
@Bean
public Docket getDocket(){
//创建Docket对象
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.enable(true)
.apiInfo(apiInfo())//指定API接口文件首页信息
.select()//初始化并返回一个API选择构造器
.apis(RequestHandlerSelectors.any())//为任何接口生成API文档
.paths(PathSelectors.any())//可以根据url路径设置哪些请求加入文档,忽略哪些请求
.build(); //创建API文档
return docket;
}
private ApiInfo apiInfo(){
//创建作者 对象
Contact contact = new Contact("尼古拉斯","http://www.baidu.com","[email protected]");
ApiInfo apiInfo = new ApiInfoBuilder()
.title("后端接口文档》") //文档标题
.description("文档的描述信息...")//文档描述
.contact(contact)//文档作者
.version("V1.0")//文档版本
.build(); //构建
return apiInfo;
}
}
@Bean
public Docket createRestApi() {
Predicate<RequestHandler> predicate = new Predicate<RequestHandler>() {
@Override
public boolean test(RequestHandler input) {
Class<?> declaringClass = input.declaringClass();
if (declaringClass == BasicErrorController.class)// 排除
return false;
if (declaringClass.getTypeName().indexOf("com.yubin.cn") <= -1)
return false;
if (declaringClass.isAnnotationPresent(RestController.class)) // 被注解的类
return true;
if (declaringClass.isAnnotationPresent(Controller.class)) // 被注解的类
return true;
if (input.isAnnotatedWith(ResponseBody.class)) // 被注解的方法
return true;
return false;
}
};
return new Docket(DocumentationType.SWAGGER_2).enable(swaggerSwitch).apiInfo(apiInfo())
.useDefaultResponseMessages(false).select().apis(predicate).build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder().title("接口服务")// 大标题
.version("1.0.0").description("V1.0.0 初始版本\r\n")// 版本
.build();
}
(1)controller
ags:tags不同,表示UI的主页下的接口归类目录不同。
@RestController
@RequestMapping("/sys/user")
@Api(value = "SysUserController", tags = {"用户管理相关操作接口"})
public class SysUserController {
@Autowired
private SysUserService sysUserService;
@PostMapping("/pageQuery")
@ApiOperation(value = "用户分页查询接口", notes = "notes用户分页查询接口")
public WebResult<BasePageResult<SysUserDTO>> pageQuery(@RequestBody SysUserPageQueryRequest pageQueryRequest) {
BasePageResult basePageResult = sysUserService.pageQuery(pageQueryRequest);
return WebResult.ok(basePageResult);
}
@DeleteMapping("/{id}")
@ApiOperation("根据id删除用户的接口")
@ApiImplicitParam(name = "id", value = "用户id", dataType = "Integer", defaultValue = "10", required = true)
@ApiResponses({
@ApiResponse(code = 200, message = "删除成功"),
@ApiResponse(code = 500, message = "删除成功")
})
public void delete(@PathVariable Integer id) {
System.out.println("删除成功:" + id);
}
@PutMapping("/update/{id}")
@ApiOperation(value = "更新用户", notes = "根据用户id更新用户名接口")
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "用户id", dataType = "Integer", defaultValue = "10", required = true),
@ApiImplicitParam(name = "username", value = "用户名", dataType = "String", defaultValue = "lisi", required = true)
})
public User update(@PathVariable Integer id, String username) {
User user = new User();
user.setId(id);
user.setUsername(username);
return user;
}
}
(2)实体类
@Data
@ApiModel("系统用户分页查询请求体")
public class SysUserPageQueryRequest extends BasePageRequest {
//@Serial
private static final long serialVersionUID = -7586253215056854970L;
@ApiModelProperty("创建时间开始")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTimeStart;
@ApiModelProperty("创建时间结束")
private Date createTimeEnd;
}
启动项目。Swagger2官方UI界面访问地址:http://ip:port/项目路径/swagger-ui.html
我们引入 swagger-bootstrap-ui依赖,移除官方 UI依赖。
<dependency>
<groupId>io.springfoxgroupId>
<artifactId>springfox-swagger2artifactId>
<version>2.9.2version>
dependency>
<dependency>
<groupId>com.github.xiaoymingroupId>
<artifactId>swagger-bootstrap-uiartifactId>
<version>1.9.6version>
dependency>
重新启动项目。替换官方 UI界面之后,新 UI界面访问地址:http://ip:port/项目路径/doc.html
Swagger也支持对 API分组展示的功能。其实很简单,我们只需要重新定义一个 Docket的 bean,在其中指定另外接口层的包路径即可。通过 groupName设置组名,默认是default。
注意:Docket和 Swagger注解中 tags的区别:
这里简单点,重新复制一个 Docket的配置信息,其他信息一样。重启项目访问 UI。
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2) // SWAGGER_2
.groupName("后端管理平台")
.apiInfo(apiInfo())
.select()
// 此处自行修改为自己的 Controller 包路径
.apis(RequestHandlerSelectors.basePackage("com.charge.xxx.controller"))
.paths(PathSelectors.any())
.build()
.globalOperationParameters(setGlobalParameters());
}
@Bean
public Docket createRestApi2() {
return new Docket(DocumentationType.SWAGGER_2) // SWAGGER_2
.groupName("后端管理平台2")
.apiInfo(apiInfo())
.select()
// 此处自行修改为自己的 Controller 包路径
.apis(RequestHandlerSelectors.basePackage("com.charge.xxx.controller"))
.paths(PathSelectors.any())
.build()
.globalOperationParameters(setGlobalParameters());
}
项目中我们经常会添加拦截器,所以需要对 Swagger相关资源进行放行。
通常添加一个 WebMvcConfig配置类,在里面添加一下 Swagger相关配置即可
@Component
@Slf4j
public class LoginTokenInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("LoginTokenInterceptor -> preHandle 请求方式={},url = {}, ", request.getMethod(), request.getRequestURI());
String token = request.getHeader("token");
if (StringUtils.isBlank(token)) {
token = request.getParameter("token");
}
if (StringUtils.isBlank(token)) {
log.info("token 为空");
}
log.info("token = {}", token);
return super.preHandle(request, response, handler);
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("LoginTokenInterceptor -> postHandle 请求方式={},url = {}, ", request.getMethod(), request.getRequestURI());
super.postHandle(request, response, handler, modelAndView);
}
}
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private LoginTokenInterceptor loginTokenInterceptor;
/**
* 配置登录拦截器
*
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginTokenInterceptor)
.addPathPatterns("/**")
// Swagger2放行。 /doc.html/**为新UI路径放行。
.excludePathPatterns("/swagger-resources/**", "/webjars/**",
"/v2/**", "/swagger-ui.html/**", "/doc.html/**");
}
/**
* 配置静态资源访问拦截
*
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
// swagger-bootstrap-ui依赖
registry.addResourceHandler("doc.html")
.addResourceLocations("classpath:/META-INF/resources/");
}
/**
* 配置 CORS跨域问题
*
* @param registry
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedHeaders("*")
.allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
.allowCredentials(true)
.maxAge(3600);
}
}
重新启动项目。新 UI界面访问地址:http://ip:port/项目路径/doc.html。测试接口OK。