文章目录
Spring Boot Test 系列5 - 用Swagger2来管理API文档和测试API
前言
本文为Spring Boot Test系列的第五篇的用Swagger2来管理API文档和测试API。
引入Swagger依赖
引入Swagger依赖:
<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>
说明:
springfox-swagger2
为Swagger2的核心包。springfox-swagger-ui
为SwaggerUI的包,用来展示API文档和测试API的Web界面。
配置Swagger
新增一个Swagger配置类:
package cn.xdevops.springboot.testdemo.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 SwaggerConfig {
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.ant("/api/**"))
.build()
.apiInfo(apiInfo());
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Spring Boot Test Demo")
.description("Spring Boot Test Demo - TDD Kata and API Testing")
.version("1.0")
.contact(new Contact("William", "https://github.com/cookcodeblog", "william@xdevops.cn"))
.license("")
.licenseUrl("")
.build();
}
}
说明:
.apis(RequestHandlerSelectors.any())
表示匹配任意的类路径,也可指定类路径。.paths(PathSelectors.ant("/api/**"))
表示匹配前缀为/api/
的URI,/api/**
为Ant pattern匹配,也可以采用正则表达式匹配。apiInfo()
中定义了API spec的基本信息。
访问Swagger
SwaggerUI web界面:
Swagger2 API docs:
为API添加描述
使用Swagger注解来为API添加描述。
描述API:
@Api
描述一类API@ApiOperation
- 描述一个API@ApiImplicitParams
- 描述API的入参@ApiResponses
- 描述API的返回值
描述Model:
@ApiModel
- 描述一个Model@ApiModelProperty
- 描述Model的一个字段
Controller代码示例:
@RestController
@RequestMapping("/api/users")
@Api(tags = {"User APIs"})
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping
@ApiOperation(value = "Get all users")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Get all users successfully")
})
public List<User> getAllUsers() {
return userService.getAllUsers();
}
@PostMapping
@ApiOperation("Create a new user")
@ApiResponses(value = {
@ApiResponse(code = 201, message = "Created a new user successfully"),
@ApiResponse(code = 400, message = "The user already exist")
})
public ResponseEntity<Void> createNewUser(@RequestBody @Valid User user, UriComponentsBuilder builder) {
User addedUser = userService
.addNewUser(user)
.orElseThrow(() -> new ResponseStatusException(HttpStatus.BAD_REQUEST,
String.format("User with id [%s] already exist", user.getId())));
URI location = builder.path("/api/users/{id}").buildAndExpand(addedUser.getId()).toUri();
return ResponseEntity.created(location).build();
}
@GetMapping("/{id}")
@ApiOperation(value = "Get user by id")
@ApiImplicitParams(
@ApiImplicitParam(name = "id", value="User ID", required = true)
)
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Found the user by id"),
@ApiResponse(code = 404, message = "User not found")
})
public User getUserById(@PathVariable("id") Long id) {
return userService
.getUserById(id)
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND,
String.format("User with id [%s] not found", id)));
}
@DeleteMapping("/{id}")
@ApiOperation(value = "Delete user by id")
@ApiImplicitParams(
@ApiImplicitParam(name = "id", value="User ID", required = true)
)
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Delete the user by id successfully")
})
public void deleteByUserId(@PathVariable("id") Long id) {
userService.deleteById(id);
}
}
Model代码示例:
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel
public class User {
@NotNull(message = "Id is mandatory")
@ApiModelProperty(value = "User Id", required = true)
private Long id;
@NotBlank(message = "Name is mandatory")
@ApiModelProperty(value = "Name", required = true)
private String name;
@ApiModelProperty(value = "Tags", required = false)
private Set<String> tags;
}
测试API
点击API的“Try it out"按钮即可测试API。
集成Spring Security
集成Spring Security后需要将SwaggerUI的URI加入到Spring Security的路径白名单中。
SwaggerUI的URI包括:
// -- Swagger UI v2
"/v2/api-docs",
"/swagger-resources",
"/swagger-resources/**",
"/configuration/ui",
"/configuration/security",
"/swagger-ui.html",
"/webjars/**",
// -- Swagger UI v3 (OpenAPI)
"/v3/api-docs/**",
"/swagger-ui/**"
参见:
在生产上禁用Swagger
出于安全原因,有时需要在生产上禁用Swagger。
在SwaggerConfig
类上添加@Profile
注解指定在符合条件时才启用Swagger。
-
默认启用Swagger,除了生产环境外。
@Profile({"!prod"})
-
默认不启用Swagger,只有在
swagger
proflie时才启用,且生产环境始终不启用。@Profile({"!prod && swagger"})
参见:
Swagger与Yapi或Postman集成
如果采用了Yapi来管理API文档,可以将Swagger API docs同步给Yapi。
既可以在代码中维护API文档,又可以通过一个比较友好的Web界面管理API文档和测试API。
Yapi:
类似地,也可以将Swagger与Postman集成。