首页 > 其他分享 >使用 Knife4j(Swagger)工具自动生成 API 接口文档

使用 Knife4j(Swagger)工具自动生成 API 接口文档

时间:2023-05-03 21:33:41浏览次数:57  
标签:Knife4j springframework API Result org import Swagger com public

现在的项目开发,绝大多数都已经采用前后端分离,前后端开发人员必须依靠接口文档进行协作。当前最流行的文档生成工具就是 Swagger,它是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。但是本篇博客介绍的是 Knife4j ,它是集 Swagger 和 OpenAPI 为一体的增强解决方案,拥有更多更强大的功能。本篇博客通过做 Demo 演示如何使用 Knife4j ,在本篇博客的最后会提供源代码下载。

Swagger 官网地址:https://swagger.io

Knife4j 官网地址:https://doc.xiaominfo.com


一、搭建工程

搭建一个 SpringBoot 工程,具体结构如下:

image

如果想使用 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 就可以看到文档接口页面了。

image

点击具体一个接口,可以查看接口详细信息:

image

可以进行接口的调用测试:

image

knife4j 还提供了导出离线文档的功能,如导出为 html 、markdown 以及 word 文档:

image


本篇博客的源代码下载地址为:https://files.cnblogs.com/files/blogs/699532/springboot_knife4j.zip

标签:Knife4j,springframework,API,Result,org,import,Swagger,com,public
From: https://www.cnblogs.com/studyjobs/p/17369710.html

相关文章

  • SpringBoot定义优雅全局统一Restful API 响应框架二
    这里解决之前留下来的问题,当程序没有正常返回时候就是程序由于运行时异常导致的结果,有些异常我们可,能无法提前预知,不能正常走到我们return的R对象返回。这个时候该如何处理在SpringBoot中,可以使用@ControllerAdvice注解来启用全局异常处理。通过使用@ControllerAdvice注解,可以捕......
  • 关于pandas.ExcelWriter()对象在执行.save()时报错FutureWarning: save is not part o
    有时使用pandas将多份数据,写入到Excel中不同的Sheet,可能会用到pandas.ExcelWriter("xxxx.xlsx")对象这样在结束时,就会对对象进行.save()和close(),当然这也是从大部分网站上看到的使用方法但是笔者在实际使用过程中,按这个过程,遇到报错:FutureWarning:saveisnotpartofthepu......
  • OpenAI API keys 的申请和测试小结
    申请准备工作,申请OpenAIAPIkeys首先需要准备三件套:1.VPN(登录Google和OpenAI)2.GoogleGmail邮箱账号3.国外手机(接收验证码,可用接码平台代替) 接下来,开启申请OpenAIAPIkeys之旅。 首先,开启VPN全局代理模式,同时将代理服务器的地址改为香港以外的国家,这样避免......
  • 常见问题——关于.net WebApi使用Swagger报错:HTTP Error 403.14 - Forbidden
    问题:.netWebApi项目使用Swagger报错:HTTPError403.14-Forbidden解放方案:换一个端口即可推荐——删除解决方案下的.vs文件夹,重新生成即可参考:https://stackoverflow.com/questions/34970088/swagger-gives-me-http-error-403-14-forbidden/53863456......
  • 对外提供的api保证接口的幂等 (先select 再 update innodb是行级锁, mysam是表级的
    额外的状态字段,这个状态值一般只会单流程变更,不管通过什么消息传递,目前申万宏源的每一个业务大部分都走流程,走的过程就有唯一的业务字段配合工作流workflow服务来进行业务流转个人观点解决幂等只有两种方式第一种依赖上游带过来的唯一标志,然后我们给这个唯一标志加锁保证请......
  • SpringBoot定义优雅全局统一Restful API 响应框架
    假如现在有一个Java项目,老板让你做项目组长,定义项目基础框架,系统技术架构选型,你应该如何设计一个规范的统一的RestfulAPI响应框架呢思考目前项目开发,都是基于前后端分离模式开发的,基于后端模板引擎那一套,可能已经不适用一些项目开发流程,和当下开发模式了,尤其在要写比......
  • SpringBoot定义优雅全局统一Restful API 响应框架
    假如现在有一个Java项目,老板让你做项目组长,定义项目基础框架,系统技术架构选型,你应该如何设计一个规范的统一的RestfulAPI响应框架呢思考目前项目开发,都是基于前后端分离模式开发的,基于后端模板引擎那一套,可能已经不适用一些项目开发流程,和当下开发模式了,尤其在要写......
  • 理解 Java8 的时间API(二)时间
    理解Java8的时间API:java.time上一篇介绍了Java8里新的时区API。这一篇介绍新的时间API:LocalDateTime,LocalDate,LocalTime类。三、Java8中的时间最常用的应该是java.time.LocalDateTime,java.time.LocalDate,java.time.LocalTime,java.time.Instant这几个类。3.1LocalDateTim......
  • 手机操作API
    目录手机操作API获取手机分辨率手机截图获取和设置手机网络发送键到设备操作手机通知栏总结手机操作API获取手机分辨率应用场景自动化测试可能会需要根据当前设备的屏幕分辨率来计算一些点击或者滑动的坐标核心代码#获取手机分辨率print(driver.get_window_size())执行结......
  • 如何通过 API 查看 cnblogs 博客访问量和博客积分与排名 All In One
    如何通过API查看cnblogs博客访问量和博客排名AllInOne开启配置https://i.cnblogs.com/preference博客访问量APIhttps://www.cnblogs.com/`username`/ajax/blogStats博客排名APIhttps://www.cnblogs.com/`username`/ajax/sidecolumn.aspxdemos博客访问量......