使用 Knife4j(Swagger)工具自动生成 API 接口文档
现在的项目开发,绝大多数都已经采用前后端分离,前后端开发人员必须依靠接口文档进行协作。当前最流行的文档生成工具就是 Swagger,它是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。但是本篇博客介绍的是 Knife4j ,它是集 Swagger 和 OpenAPI 为一体的增强解决方案,拥有更多更强大的功能。本篇博客通过做 Demo 演示如何使用 Knife4j ,在本篇博客的最后会提供源代码下载。
Swagger 官网地址:https://swagger.io
Knife4j 官网地址:https://doc.xiaominfo.com
一、搭建工程
搭建一个 SpringBoot 工程,具体结构如下:
如果想使用 Knife4j ,首先需要在 pom 文件中引入 knife4j-spring-boot-starter 依赖包。
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.4.5</version> </parent> <groupId>com.jobs</groupId> <artifactId>springboot_knife4j</artifactId> <version>1.0-SNAPSHOT</version> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <scope>compile</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.26</version> </dependency> <!--使用 knife4j 功能,只引入这一个依赖包即可--> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-spring-boot-starter</artifactId> <version>3.0.3</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.4.5</version> </plugin> </plugins> </build> </project>
下面列出 application.yml 配置文件的内容:
server: port: 8888 knife4j: # 是否启用增强版功能 enable: true # 如果是生产环境,将此设置为 true,然后就能够禁用了 knife4j 的页面 production: false
Knife4j 的一个非常不错的功能就是可以通过 knife4j.production 配置是否是生产环境,如果配置为 true 的话,那么就不会展示出接口文档的页面,确保生产环境的安全性。当然有关 knife4j 还有很多其它的实用配置项,详情可以参考官网。
Knife4j 在运行过程中,会自动生成一个 doc.html 静态页面,这个就是我们要访问的接口文档页面。默认情况下 SpringBoot 是不允许访问静态资源的,因此我们需要在 SpringBoot 中配置 Knife4j 的静态资源请求映射路径。
另外需要使用 @EnableOpenAPI 注解。由于我们的接口都是在 controller 类中进行编写,因此需要配置 Knife4j 需要扫描的 controller 包。本博客的具体代码细节都编写在了 WebMvcConfig 类中了,具体细节如下:
package com.jobs.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; 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.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; //需要添加这个注解 @EnableOpenApi @EnableOpenApi @Configuration public class WebMvcConfig extends WebMvcConfigurationSupport { //需要配置 knife4j 的静态资源请求映射地址 @Override protected void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/doc.html") .addResourceLocations("classpath:/META-INF/resources/"); registry.addResourceHandler("/webjars/**") .addResourceLocations("classpath:/META-INF/resources/webjars/"); } @Bean public Docket createDocket() { // 文档类型 return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("com.jobs.controller")) .paths(PathSelectors.any()) .build(); } private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("我的测试") .version("1.0") .description("我的测试接口文档") .build(); } }
在实际的项目中,绝大多数情况下,网站必须登录后才能查看页面,为了能够匿名查看 knife4j 的接口文档页面,我们必须放行 Knife4j 的静态资源文件。本篇博客采用自己编写的 filter 来验证用户登录,因此需要在 filter 中放行 Knife4j 的静态资源文件。
package com.jobs.filter; import com.fasterxml.jackson.databind.ObjectMapper; import com.jobs.entity.Result; import org.springframework.util.AntPathMatcher; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebFilter(filterName = "LoginCheckFilter", urlPatterns = "/*") public class LoginCheckFilter implements Filter { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; String requestURI = request.getRequestURI(); if (checkPassUri(requestURI)) { filterChain.doFilter(request, response); return; } Object uid = request.getSession().getAttribute("user"); if (uid != null) { filterChain.doFilter(request, response); return; } response.getWriter().write(new ObjectMapper().writeValueAsString(Result.fail(-99,"no login"))); } //路径匹配对象 private static final AntPathMatcher apm = new AntPathMatcher(); private boolean checkPassUri(String requestURI) { String[] uris = new String[]{ //放行用户登录接口 "/user/login", //放行用户退出接口 "/user/logout", //放行下面的 knifefj 的静态资源文件路径 "/doc.html", "/webjars/**", "/swagger-resources", "/v2/api-docs" }; for (String uri : uris) { boolean match = apm.match(uri, requestURI); if (match) { return true; } } return false; } }
为了能够是 filter 生效,需要在 SpringBoot 启动类上增加 @ServletComponentScan 注解。
package com.jobs; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletComponentScan; @Slf4j @ServletComponentScan @SpringBootApplication public class MainApp { public static void main(String[] args) { SpringApplication.run(MainApp.class, args); log.info("项目启动成功"); } }
OK,项目结构已经搭建完毕了,下面就看具体的代码吧。
二、代码细节查看
其实现在启动 SpringBoot 程序,访问 localhost:8888/doc.html 就已经可以看到接口文档了。但是文档中没有任何注释,为了能够让接口文档更容易看懂,需要在代码中增加以下相关的注解。
注解 | 位置 | 说明 |
---|---|---|
@Api | 类(Controller) | 加载 Controller类上表示对类的说明 |
@ApiModel | 类(实体类) | 描述实体类的作用 |
@ApiModelProperty | 属性(实体类) | 描述实体类的属性 |
@ApiOperation | 方法(接口) | 说明方法的用途、作用 |
@ApiImplicitParams | 方法(接口参数) | 表示一组参数说明 |
@ApiImplicitParam | 方法(接口参数) | 用在 @ApiImplicitParams 注解中,指定一个请求参数的各个方面的属性 |
下面就让我们把上面的注解,添加到具体的代码中,详情可下载源代码查看。
1 在实体类上使用 @ApiModel 和 @ApiModelProperty 注解
package com.jobs.entity; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.io.Serializable; @Data @ApiModel("用户") public class User implements Serializable { @ApiModelProperty("用户id") private Long id; @ApiModelProperty("用户名称") private String name; @ApiModelProperty("用户年龄") private Integer age; }
package com.jobs.entity; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.io.Serializable; import java.math.BigDecimal; @Data @ApiModel("订单") public class Order implements Serializable { @ApiModelProperty("订单id") private Long id; @ApiModelProperty("订单名称") private String name; @ApiModelProperty("订单价格") private BigDecimal price; @ApiModelProperty("订单数量") private Integer num; }
2 在 Controller 上使用 @Api 注解,在接口上使用 @ApiOperation、@ApiImplicitParams 和 @ApiImplicitParam 注解
package com.jobs.controller; import com.jobs.entity.Result; import com.jobs.entity.User; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; @Api(tags = "用户操作相关接口") @RequestMapping("/user") @RestController public class UserController { @ApiOperation("用户登录") @ApiImplicitParams({ @ApiImplicitParam(name = "name", value = "用户名", required = true), @ApiImplicitParam(name = "pwd", value = "密码", required = true) }) @PostMapping("/login") public Result<String> login(String name, String pwd, HttpServletRequest request) { if ("jobs".equals(name) && "123".equals(pwd)) { request.getSession().setAttribute("user", "jobs"); return Result.success("登录成功"); } else { return Result.fail(-1, "用户名或密码不正确"); } } @ApiOperation("用户退出") @PostMapping("/logout") public Result<String> logout(HttpServletRequest request) { request.getSession().removeAttribute("user"); return Result.success("退出成功"); } @ApiOperation("添加用户") @PostMapping public Result<User> Add(@RequestBody User user) { return Result.success(user); } }
package com.jobs.controller; import com.jobs.entity.Order; import com.jobs.entity.Result; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.*; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.Random; @Api(tags = "订单操作相关接口") @RequestMapping("/order") @RestController public class OrderController { @ApiOperation("添加订单") @PostMapping public Result<Order> add(@RequestBody Order order) { return Result.success(order); } @ApiOperation("根据id获取订单") @ApiImplicitParam(name = "id", value = "订单id", required = true) @GetMapping("/{id}") public Result<Order> get(@PathVariable("id") Long id) { Order order = new Order(); order.setId(id); order.setName("订单" + new Random().nextInt()); order.setPrice(new BigDecimal(new Random().nextInt(200)) .divide(new BigDecimal("3"), 2, RoundingMode.HALF_UP)); order.setNum(new Random().nextInt(100)); return Result.success(order); } @ApiOperation("修改订单") @PutMapping public Result<String> update(@RequestBody Order order) { return Result.success("修改成功"); } @ApiOperation("删除订单") @ApiImplicitParam(name = "id", value = "订单id", required = true) @DeleteMapping public Result<String> delete(Long id) { return Result.success("删除成功"); } }
OK,主要的代码已经添加好注解了,下面就可以启动 SpringBoot 程序,验证一下效果了。
三、验证效果
启动 SpringBoot 程序,访问 localhost:8888/doc.html 就可以看到文档接口页面了。
点击具体一个接口,可以查看接口详细信息:
可以进行接口的调用测试:
knife4j 还提供了导出离线文档的功能,如导出为 html 、markdown 以及 word 文档:
本篇博客的源代码下载地址为:https://files.cnblogs.com/files/blogs/699532/springboot_knife4j.zip
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
2022-05-03 SSM(Spring+SpringMvc+Mybatis)纯注解整合示例