Swagger是一个用于设计、构建和文档化 RESTful API 的开源框架。它提供了一组工具,使得开发人员能够更轻松地定义、描述和测试API接口。
具体来说,Swagger包含以下几个核心组件:
Swagger规范(Swagger Specification): 定义了一种格式化的API规范,使用YAML或JSON格式,用于描述API的各种细节,包括路由、参数、返回值等。
Swagger编辑器(Swagger Editor): 提供了一个交互式的编辑界面,让开发人员能够方便地编写和验证Swagger规范文件。
Swagger UI: 一个动态生成的HTML文件,可以将Swagger规范文件渲染成一个美观易用的API文档网页。通过Swagger UI,开发人员可以直观地查看API接口的详细信息,包括请求示例、响应模型和参数说明。
Swagger Codegen: 一个自动生成API客户端代码的工具,根据Swagger规范文件,它可以生成多种编程语言的代码框架,帮助开发人员快速集成和调用API接口。
利用Swagger,开发团队可以在项目早期就定义和设计好API接口,并且在整个开发过程中保持与API文档的同步更新。这样做的好处包括:
总的来说,Swagger是一个强大的工具,可以帮助开发人员更好地构建、测试和文档化RESTful API,并提供了一系列的工具和库,支持在不同的编程语言和框架中使用。
io.springfox springfox-swagger2 2.9.2 io.springfox springfox-swagger-ui 2.9.2
自定义Swagger配置文件:SwaggerConfig
import java.util.ArrayList; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import io.swagger.annotations.ApiOperation; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.*; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spi.service.contexts.SecurityContext; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; /** * Swagger2的接口配置 * * @author alited */ @Configuration @EnableSwagger2 //标记项目启用 Swagger API 接口文档 public class SwaggerConfig { /** 是否开启swagger */ @Value("${swagger.enabled}") private boolean enabled; /** 设置请求的统一前缀 */ @Value("${swagger.pathMapping}") private String pathMapping; /** * 创建API */ @Bean public Docket createRestApi() { // 创建Docket对象 return new Docket(DocumentationType.SWAGGER_2) // 文档类型,使用Swagger2 // 是否启用Swagger .enable(enabled) // 用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息) // 设置Api信息 .apiInfo(apiInfo()) // 设置哪些接口暴露给Swagger展示 .select() // 扫描所有有注解的api,用这种方式更灵活 .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)) // 扫描指定包中的swagger注解 // .apis(RequestHandlerSelectors.basePackage("com.project.tool.swagger")) // 扫描所有 .paths(PathSelectors.any()) // 构建出 Docket 对象 .build() /* 设置安全模式,swagger可以设置访问token */ .securitySchemes(securitySchemes()) .securityContexts(securityContexts()) .pathMapping(pathMapping); } /** * 安全模式,这里指定token通过Authorization头请求头传递 */ private ListsecuritySchemes() { List apiKeyList = new ArrayList (); apiKeyList.add(new ApiKey("Authorization", "Authorization", "header")); return apiKeyList; } /** * 安全上下文 */ private List securityContexts() { List securityContexts = new ArrayList<>(); securityContexts.add( SecurityContext.builder() .securityReferences(defaultAuth()) .forPaths(PathSelectors.regex("^(?!auth).*$")) .build()); return securityContexts; } /** * 默认的安全上引用 */ private List defaultAuth() { AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything"); AuthorizationScope[] authorizationScopes = new AuthorizationScope[1]; authorizationScopes[0] = authorizationScope; List securityReferences = new ArrayList<>(); securityReferences.add(new SecurityReference("Authorization", authorizationScopes)); return securityReferences; } /** * 添加摘要信息 */ private ApiInfo apiInfo() { // 用ApiInfoBuilder进行定制 return new ApiInfoBuilder() // 设置标题 .title("标题:管理系统_接口文档") // 描述 .description("描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...") // 作者信息 .contact(new Contact("Wen先森", null, null)) // 版本 .version("版本号:1.0" ) .build(); } }
可以在Controller类及方法上添加Swagger相关注解,自动生成API文档。
/** * swagger 用户测试方法 * * @author alited */ @Api("用户信息管理") @RestController @RequestMapping("/test/user") public class TestController { private final static Mapusers = new LinkedHashMap (); { users.put(1, new UserEntity(1, "admin", "admin123", "15888888888")); users.put(2, new UserEntity(2, "ry", "admin123", "15666666666")); } @ApiOperation("获取用户列表") @GetMapping("/list") public AjaxResult userList() { List userList = new ArrayList (users.values()); return AjaxResult.success(userList); } @ApiOperation("获取用户详细") @ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path") @GetMapping("/{userId}") public AjaxResult getUser(@PathVariable Integer userId) { if (!users.isEmpty() && users.containsKey(userId)) { return AjaxResult.success(users.get(userId)); } else { return AjaxResult.error("用户不存在"); } } @ApiOperation("新增用户") @ApiImplicitParam(name = "userEntity", value = "新增用户信息", dataType = "UserEntity") @PostMapping("/save") public AjaxResult save(UserEntity user) { if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId())) { return AjaxResult.error("用户ID不能为空"); } return AjaxResult.success(users.put(user.getUserId(), user)); } @ApiOperation("更新用户") @ApiImplicitParam(name = "userEntity", value = "新增用户信息", dataType = "UserEntity") @PutMapping("/update") public AjaxResult update(UserEntity user) { if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId())) { return AjaxResult.error("用户ID不能为空"); } if (users.isEmpty() || !users.containsKey(user.getUserId())) { return AjaxResult.error("用户不存在"); } users.remove(user.getUserId()); return AjaxResult.success(users.put(user.getUserId(), user)); } @ApiOperation("删除用户信息") @ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path") @DeleteMapping("/{userId}") public AjaxResult delete(@PathVariable Integer userId) { if (!users.isEmpty() && users.containsKey(userId)) { users.remove(userId); return AjaxResult.success(); } else { return AjaxResult.error("用户不存在"); } } } @ApiModel("用户实体") class UserEntity { @ApiModelProperty("用户ID") private Integer userId; @ApiModelProperty("用户名称") private String username; @ApiModelProperty("用户密码") private String password; @ApiModelProperty("用户手机") private String mobile; public UserEntity() { } public UserEntity(Integer userId, String username, String password, String mobile) { this.userId = userId; this.username = username; this.password = password; this.mobile = mobile; } public Integer getUserId() { return userId; } public void setUserId(Integer userId) { this.userId = userId; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getMobile() { return mobile; } public void setMobile(String mobile) { this.mobile = mobile; } }
启动项目。然后浏览器访问 http://127.0.0.1:8080/swagger-ui.html (8080是你项目端口)地址,就可以看到 Swagger 生成的 API 接口文档。效果如下:
Swagger 提供了一套注解,用于在代码中标记和描述 API 接口的各种细节,帮助生成准确、详细的 API 文档。以下是 Swagger 常用的一些注解:
@Api 注解是 Swagger 中用于标记控制器类(Controller)的注解,表示该类包含了 API 接口。它具有以下常用属性:
@Api 注解的不常用属性,如下:
@RestController @Api(value = "User API", tags = "User Management", description = "APIs for managing users") @RequestMapping("/api/users") public class UserController { // API 接口方法... }
@ApiOperation 注解是 Swagger 中用于标记Controller类中方法的注解,表示该方法是一个 API 操作,并可以添加说明和备注信息。
@ApiOperation 注解具有以下常用属性:
@ApiOperation 不常用属性:
下面是一个示例:
@RestController @Api(value = "User API", tags = "User Management") @RequestMapping("/api/users") public class UserController { @ApiOperation(value = "Get user by ID", notes = "Retrieve user information based on the given ID") @GetMapping("/{id}") public UserDTO getUserById(@PathVariable("id") Long id) { // 实现代码... } }
在上述示例中,@ApiOperation 注解标记了 getUserById 方法,其中 value 属性指定了 API 操作的简要描述为 “Get user by ID”,notes 属性提供了关于该 API 操作的详细描述,tags 属性设置了该 API 操作所属的标签为 “User Management”。
通过使用 @ApiOperation 注解,Swagger 可以根据该方法中标记的 API 操作生成相应的文档。开发人员可以在注解的属性中提供接口的详细说明、备注信息等,帮助其他开发人员理解和使用这个接口。
需要注意的是,@ApiOperation 注解通常使用在具体的 API 接口方法上,可以为每个方法添加对应的注解。这样可以根据注解的信息来生成准确的文档描述,方便其他开发人员了解和使用接口。
@ApiParam 注解是 Swagger 中用于标记方法参数的注解,用于为 API 操作的参数添加描述和说明。
@ApiParam 注解具有以下常用属性:
下面是一个示例:
@RestController @Api(value = "User API", tags = "User Management") @RequestMapping("/api/users") public class UserController { @ApiOperation(value = "Update user", notes = "Update the user information") @PutMapping("/{id}") public void updateUser( @ApiParam(value = "User ID", required = true) @PathVariable("id") Long id, @ApiParam(value = "User data", required = true) @RequestBody UserDTO userDto ) { // 实现代码... } }
在上述示例中,@ApiParam 注解分别标记了 id 和 userDto 两个参数。其中,id 参数的 value 属性指定了参数的简要描述为 “User ID”,required 属性设置参数为必需,userDto 参数的 value 属性指定了参数的简要描述为 “User data”。
通过使用 @ApiParam 注解,Swagger 可以根据该参数的注解生成相应的文档。开发人员可以在注解的属性中提供参数的描述、是否必需、默认值、可接受值范围等信息,帮助其他开发人员理解和使用该 API 接口。
需要注意的是,@ApiParam 注解通常使用在具体的 API 接口方法的参数上,可以为每个参数添加对应的注解。这样可以根据注解的信息来生成准确的文档描述,方便其他开发人员了解和使用接口。
@ApiImplicitParam 注解是 Swagger 提供的用于描述 API 操作的参数的注解之一,用于标记方法参数,并提供参数的详细描述和说明。
@ApiImplicitParam 注解具有以下常用属性:
下面是一个示例:
@RestController @Api(value = "User API", tags = "User Management") @RequestMapping("/api/users") public class UserController { @ApiOperation(value = "Create user", notes = "Create a new user") @ApiImplicitParams({ @ApiImplicitParam(name = "name", value = "User name", dataType = "String", paramType = "query"), @ApiImplicitParam(name = "age", value = "User age", dataType = "int", paramType = "query") }) @PostMapping("/") public void createUser(HttpServletRequest request) { String name = request.getParameter("name"); int age = Integer.parseInt(request.getParameter("age")); // 实现代码... } }
在上述示例中,@ApiImplicitParams 注解标记了多个 @ApiImplicitParam 注解,用于描述 createUser 方法的两个参数 name 和 age。其中 name 参数的 value 属性指定了参数的简要描述为 “User name”,dataType 属性指定了参数的数据类型为 “String”,paramType 属性指定了参数的类型为查询参数(query)。
通过使用 @ApiImplicitParam 注解,Swagger 可以根据该参数的注解生成相应的文档。开发人员可以在注解的属性中提供参数的名称、描述、数据类型、类型等信息,帮助其他开发人员理解和使用该 API 接口。
需要注意的是,@ApiImplicitParam 注解通常使用在具体的 API 接口方法的参数上,可以为每个参数添加对应的注解。这样可以根据注解的信息来生成准确的文档描述,方便其他开发人员了解和使用接口。
@ApiParam 注解和 @ApiImplicitParam 注解都是 Swagger 提供的用于描述 API 操作参数的注解,它们有以下区别:
适用范围:
所属注解:
参数传递方式:
参数描述灵活性:
例如,使用 @ApiParam 注解时:
@PostMapping("/users/{id}") public void updateUser( @PathVariable("id") @ApiParam(value = "User ID", example = "1") Long userId, @RequestBody @ApiParam(value = "Updated user information") UserDto userDto) { // 实现代码... }
上述示例中,@ApiParam 注解用于对 userId 和 userDto 这两个参数进行详细的描述和说明。
而使用 @ApiImplicitParam 注解时:
@PostMapping("/users/{id}") @ApiImplicitParams({ @ApiImplicitParam(name = "id", value = "User ID", dataType = "Long", paramType = "path"), @ApiImplicitParam(name = "userDto", value = "Updated user information", dataType = "UserDto", paramType = "body") }) public void updateUser(@PathVariable("id") Long userId, @RequestBody UserDto userDto) { // 实现代码... }
上述示例中,@ApiImplicitParam 注解用于对 userId 和 userDto 这两个参数进行基本的描述和说明。
总而言之,@ApiParam 注解提供了更丰富的参数描述功能,并可以应用于更多的场景,而 @ApiImplicitParam 注解则相对简单,适合基本的参数描述。开发人员可以根据实际需求选择使用适当的注解来描述 API 操作的参数。
@ApiModel 注解是 Swagger 中用于标记类的注解,表示该类是一个用于 API 文档定义的模型。
@ApiModel 注解具有以下常用属性:
下面是一个示例:
@ApiModel(value = "User", description = "User object") public class UserDTO { @ApiModelProperty(value = "User ID", example = "1") private Long id; @ApiModelProperty(value = "Username", example = "john.doe") private String username; // 省略其他属性和方法... }
在上述示例中,@ApiModel 注解标记了 UserDTO 类,其中 value 属性指定了模型的名称为 “User”,description 属性提供了关于该模型的详细描述。
通过使用 @ApiModel 注解,Swagger 可以根据该类的注解生成相应的文档。开发人员可以在注解的属性中提供模型的名称、描述、父类等信息,帮助其他开发人员理解和使用该模型。
此外,还可以使用 @ApiModelProperty 注解标记模型中的属性,用于为属性添加描述和说明。@ApiModelProperty 注解具有类似于 @ApiParam 注解的属性,例如 value、example 等,用于提供属性的描述、示例值等信息。
需要注意的是,@ApiModel 注解通常使用在类上,用于标记该类是一个模型。而 @ApiModelProperty 注解通常使用在类的属性上,用于标记和描述属性。通过这些注解,Swagger 可以根据注解的信息生成准确的文档描述,方便其他开发人员了解和使用模型。
@ApiModelProperty 注解是 Swagger 提供的一个用于描述模型属性的注解。它可以用于类的字段或者 getter 方法上,用于提供更详细的属性描述和配置。
@ApiModelProperty 注解具有以下特点和用途:
属性说明:通过 value 属性可以为属性提供文本说明,描述该属性的含义和用途。
数据类型:通过 dataType 属性可以指定属性的数据类型,例如字符串、整数、布尔值等。
示例值:通过 example 属性可以设置属性的示例值,用于展示该属性在实际使用中的取值范例。
是否必需:通过 required 属性可以指定该属性是否是必需的,即是否需要在请求中提供该属性的值。
隐藏属性:通过 hidden 属性可以控制是否将该属性隐藏起来,不在生成的文档中显示。
其他配置:@ApiModelProperty 还提供了一些其他的属性,例如 allowableValues(限制属性的取值范围)、notes(额外的补充说明)等。这些属性可以根据需要进行配置。
下面是一个使用 @ApiModelProperty 注解的示例:
public class User { @ApiModelProperty(value = "用户ID", example = "12345") private Long id; @ApiModelProperty(value = "用户名", required = true) private String username; // 省略其他属性的定义和注解 // Getter 和 Setter 方法 }
在上述示例中,@ApiModelProperty 注解被应用于 id 和 username 这两个属性上,提供了属性的说明、示例值以及是否必需的信息。
通过使用 @ApiModelProperty 注解,我们可以更加清晰、详细地描述模型属性,使生成的 API 文档更加准确和友好。
@ApiResponse 注解是 Swagger 提供的一个用于描述 API 接口的响应信息的注解。它可以用于方法、类或者接口上,用于提供更详细的响应信息和配置。
@ApiResponse 注解具有以下特点和用途:
响应说明:通过 message 属性可以为响应提供文本说明,描述该响应的含义和用途。
响应码:通过 code 属性可以指定响应的状态码,例如 200、400、500 等。
响应模型:通过 response 属性可以指定响应的模型类型,通常是一个实体类,用于描述响应的数据结构。
多个响应:@ApiResponse 注解支持多个一起使用,可以用于描述一个接口方法可能返回的不同响应场景。可以使用 responseContainer 属性来指定响应数据的容器类型,例如 List、Map 等。
其他配置:@ApiResponse 还提供了一些其他的属性,例如 reference(引用其他定义的响应模型)、responseHeaders(响应头信息)等。这些属性可以根据需要进行配置。
下面是一个使用 @ApiResponse 注解的示例:
@GetMapping("/users/{id}") @ApiResponse(code = 200, message = "成功", response = User.class) @ApiResponse(code = 404, message = "用户不存在") public User getUserById(@PathVariable("id") Long id) { // 实现代码... }
在上述示例中,@ApiResponse 注解被应用于 getUserById 方法上,提供了两个不同的响应场景:一个是 code 为 200 的成功响应,返回的是一个 User 类型的实体对象;另一个是 code 为 404 的用户不存在的错误响应。
通过使用 @ApiResponse 注解,我们可以更加清晰、详细地描述 API 接口的响应信息,使生成的 API 文档更加准确和全面。
@ApiResponses 注解是 Swagger 提供的一个用于描述 API 接口多个响应情况的注解。它可以用于方法、类或者接口上,用于提供更详细的响应信息和配置。
@ApiResponses 注解具有以下特点和用途:
响应说明:通过 value 属性可以为多个响应情况提供文本说明,描述每个响应的含义和用途。
响应列表:通过数组形式,使用 @ApiResponse 注解来描述每个响应情况。每个 @ApiResponse 注解包含 code、message、response 等属性,用于指定响应的状态码、说明和对应的响应模型。
其他配置:@ApiResponses 还提供了一些其他的属性,例如 reference(引用其他定义的响应模型)、responseHeaders(响应头信息)等。这些属性可以根据需要进行配置。
下面是一个使用 @ApiResponses 注解的示例:
@GetMapping("/users/{id}") @ApiResponses(value = { @ApiResponse(code = 200, message = "成功", response = User.class), @ApiResponse(code = 404, message = "用户不存在") }) public ResponseEntitygetUserById(@PathVariable("id") Long id) { // 实现代码... }
在上述示例中,@ApiResponses 注解被应用于 getUserById 方法上,提供了两个不同的响应情况:一个是 code 为 200 的成功响应,返回的是一个 User 类型的实体对象;另一个是 code 为 404 的用户不存在的错误响应。
通过使用 @ApiResponses 注解,我们可以更加清晰、详细地描述 API 接口的多个响应情况,使生成的 API 文档更加准确和全面。
@ApiIgnore 是 Swagger 提供的一个注解,用于指示 Swagger 忽略某个特定的类、方法或字段,不生成对应的 API 文档。
使用 @ApiIgnore 注解的场景包括但不限于:
忽略整个类:将 @ApiIgnore 注解应用于类上,表示 Swagger 忽略该类的所有 API 接口,不生成对应的文档信息。
忽略单个方法:将 @ApiIgnore 注解应用于方法上,表示 Swagger 忽略该方法对应的 API 接口,不生成对应的文档信息。
忽略字段:将 @ApiIgnore 注解应用于字段上,表示 Swagger 忽略该字段,不在生成的模型中包含该字段的信息。
下面是几个使用 @ApiIgnore 注解的示例:
@Api(tags = "用户管理") @RestController public class UserController { @ApiOperation("获取用户列表") @GetMapping("/users") public ListgetUsers() { // 实现代码... } @ApiIgnore @GetMapping("/admin/users") public List getAdminUsers() { // 实现代码... } }
在上述示例中,getUsers 方法被 Swagger 生成为 API 文档的一部分,因为它没有被标记为 @ApiIgnore。而 getAdminUsers 方法被标记为 @ApiIgnore,因此 Swagger 将忽略它,不会生成对应的 API 文档。
使用 @ApiIgnore 注解可以方便地控制 Swagger 生成的 API 文档内容,特别是在某些情况下需要隐藏或排除一些不需要展示的接口或字段时非常有用。
Knife4j 是一个基于 Swagger 的 API 文档生成和展示工具,它提供了一种更加强大和灵活的方式来生成和管理 API 文档。
与传统的 Swagger UI(Swagger-UI 是 Swagger 官方提供的前端 UI 库)相比,Knife4j 在功能和样式上都有一些创新和改进,使得 API 文档更加易用、美观和强大。
Knife4j 提供的主要特性包括:
界面美观:Knife4j 提供了漂亮的界面主题和样式,使得生成的 API 文档更加专业和吸引人。
接口分组:Knife4j 支持将接口按照一定的规则进行分组,方便用户对接口进行组织和管理。
接口测试:Knife4j 提供了在线的接口测试功能,使得开发人员可以在文档页面直接进行接口测试,而无需另外打开其他工具。
文档扩展:Knife4j 支持在 API 文档中嵌入自定义的 Markdown 格式文档,方便开发人员添加额外的说明和示例。
参数校验和模拟测试:Knife4j 支持对接口请求参数进行校验,并提供了模拟测试的功能,方便开发人员在不依赖后端接口实现的情况下进行接口调试。
总之,Knife4j 是一个功能强大、界面美观的 Swagger 扩展工具,通过提供更多的功能和改进的样式,使得 API 文档更易用、美观和强大。它在提供标准的 Swagger 功能的同时,还增加了一些额外的特性,方便开发人员更好地管理和使用 API 接口文档。
com.github.xiaoymin knife4j-spring-boot-starter 2.0.7
@Configuration public class ResourcesConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { /** swagger配置 */ registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/"); registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/"); } }
启动项目。然后浏览器访问 http://127.0.0.1:8080/doc.html (8080是你项目端口)地址,就可以看到 Swagger 生成的 API 接口文档。效果如下: