zoukankan      html  css  js  c++  java
  • Spring Boot 入门实战(9)--使用 knife4j 构建 API 文档

    Knife4j 是为 Java MVC 框架集成 Swagger 生成 Api 文档的增强解决方案,其提供的页面更符合国人的使用习惯,并提供了很多额外的功能特性,官网地址为:https://doc.xiaominfo.com。本文主要介绍 Spring Boot 与 Knife4j 的结合使用,文中所使用到的软件版本:Spring Boot 2.4.4、jdk1.8.0_181、Knife4j 3.0.2。

    1、Swagger基本使用

    Knife4j 是基于 Swagger 开发改造的,所以有必要先了解下 Swagger 的使用方法;具体可参考 Spring Boot 入门实战(8)--使用 Swagger 构建 API 文档

    2、Spring Boot 整合 Knife4j

    Spring Boot 环境下 Knifie 和 Swagger 的使用基本差不多,除了引入的 jar 包及配置等少许地方不一样,其他方面基本都一样。

    2.1、引入依赖

    <dependency>
        <groupId>com.github.xiaoymin</groupId>
        <artifactId>knife4j-spring-boot-starter</artifactId>
        <version>3.0.2</version>
    </dependency>

    2.2、Swagger 配置

    package com.abc.demo.config;
    
    import com.github.xiaoymin.knife4j.spring.extension.OpenApiExtensionResolver;
    import io.swagger.annotations.ApiOperation;
    import io.swagger.models.auth.In;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import springfox.documentation.builders.*;
    import springfox.documentation.oas.annotations.EnableOpenApi;
    import springfox.documentation.service.*;
    import springfox.documentation.spi.DocumentationType;
    import springfox.documentation.spi.service.contexts.SecurityContext;
    import springfox.documentation.spring.web.plugins.Docket;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    @Configuration
    @EnableOpenApi
    public class SwaggerConfig {
        private static final String AUTH_HEADER_NAME = "token";
    
        //Knife4j扩展对象
        @Autowired
        private OpenApiExtensionResolver openApiExtensionResolver;
    
        @Bean
        public Docket docket() {
            return new Docket(DocumentationType.OAS_30)
                    .apiInfo(apiInfo())
                    .select()
                    //加了ApiOperation注解的方法,才生成接口文档
                    .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                    //特定包下的类,才生成接口文档
                    //.apis(RequestHandlerSelectors.basePackage("com.abc.demo.controller"))
                    .paths(PathSelectors.any())
                    .build()
                    .extensions(openApiExtensionResolver.buildExtensions("default"))
                    //设置全局token
                    .securitySchemes(securitySchemes())
                    .securityContexts(securityContexts());
                    //每个接口传token
                    //.globalRequestParameters(globalRequestParameters());
        }
    
        private ApiInfo apiInfo() {
            return new ApiInfoBuilder()
                    .title("XXX系统")
                    .description("XXX系统接口文档")
                    .termsOfServiceUrl("https://www.abc.com")
                    .contact(new Contact("Jack", "https://www.cnblogs.com/jack", "123456@qq.com"))
                    .version("1.0.0")
                    .build();
        }
    
        private List<SecurityScheme> securitySchemes() {
            return Arrays.asList(new ApiKey(AUTH_HEADER_NAME, "auth", In.HEADER.name()));
        }
    
        private List<SecurityContext> securityContexts() {
            List<SecurityContext> securityContexts = new ArrayList<>();
            securityContexts.add(SecurityContext
                    .builder()
                    .securityReferences(securityReferences())
                    .operationSelector(operationContext -> operationContext.requestMappingPattern().startsWith("/api/"))
                    .build());
            return securityContexts;
        }
    
        private List<SecurityReference> securityReferences() {
            AuthorizationScope[] authorizationScopes = new AuthorizationScope[] {new AuthorizationScope("global", "accessEverything")};
            List<SecurityReference> securityReferences = new ArrayList<>();
            securityReferences.add(new SecurityReference(AUTH_HEADER_NAME, authorizationScopes));
            return securityReferences;
        }
    
        private List<RequestParameter> globalRequestParameters() {
            return Arrays.asList(new RequestParameterBuilder()
                    .name(AUTH_HEADER_NAME)
                    .description("access token")
                    .in(ParameterType.HEADER)
                    .required(false)
                    .build());
        }
    
    }

    2.3、编写Controller

    package com.abc.demo.controller;
    
    import com.abc.demo.annotation.Login;
    import com.abc.demo.entity.R;
    import com.abc.demo.entity.Student;
    import com.abc.demo.form.StudentForm;
    import io.swagger.annotations.Api;
    import io.swagger.annotations.ApiImplicitParam;
    import io.swagger.annotations.ApiOperation;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.web.bind.annotation.*;
    
    import java.util.*;
    
    @RestController
    @RequestMapping("/api/student")
    @Api(tags = "学生相关接口")
    public class StudentController {
        private static Logger logger = LoggerFactory.getLogger(StudentController.class);
    
        @PostMapping("add")
        @ApiOperation("增加学生(json方式提交)")
        public R<Long> add(@RequestBody StudentForm studentForm) {
            logger.info("studentForm={}", studentForm);
            //TODO: service调用
    
            return R.ok(new Random().nextLong());
        }
    
        @PostMapping("add2")
        @ApiOperation("增加学生(form方式提交)")
        public R<Long> add2(StudentForm studentForm) {
            logger.info("studentForm={}", studentForm);
            //TODO: service调用
    
            return R.ok(new Random().nextLong());
        }
    
        @GetMapping("get")
        @ApiOperation("根据姓名查询学生")
        @ApiImplicitParam(name = "name", value = "学生姓名", dataTypeClass = String.class, required = true)
        public R<Student> get(String name) {
            logger.info("name={}", name);
            //TODO: service调用
    
            return R.ok(new Student(new Random().nextLong(), "杜甫", 21, 175));
        }
    
    
        @Login
        @GetMapping("list")
        @ApiOperation("获取学生列表")
        public R<List<Student>> list() {
            //TODO: service调用
            List<Student> students = new ArrayList(){{
               add(new Student(new Random().nextLong(), "杜甫", 21, 175));
               add(new Student(new Random().nextLong(), "李商隐", 22, 175));
            }};
            return R.ok(students);
        }
    
    }

    Controller 用到的参数实体类 StudentForm:

    package com.abc.demo.form;
    
    import io.swagger.annotations.ApiModel;
    import io.swagger.annotations.ApiModelProperty;
    import lombok.Data;
    import lombok.ToString;
    
    @Data
    @ToString
    @ApiModel(value = "学生表单")
    public class StudentForm {
        @ApiModelProperty(value = "姓名", example = "李白")
        private String name;
    
        @ApiModelProperty(value = "年龄", example = "20")
        private Integer age;
    
        @ApiModelProperty(value = "身高", example = "175")
        private Integer height;
    }

    Controller用到的实体类Student:

    package com.abc.demo.entity;
    
    import io.swagger.annotations.ApiModel;
    import io.swagger.annotations.ApiModelProperty;
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    import lombok.ToString;
    
    @NoArgsConstructor
    @AllArgsConstructor
    @Data
    @ToString
    @ApiModel(value = "学生信息")
    public class Student {
        @ApiModelProperty(value = "学生id", example = "1234")
        private Long id;
    
        @ApiModelProperty(value = "学生姓名", example = "李白")
        private String name;
    
        @ApiModelProperty(value = "年龄", example = "20")
        private Integer age;
    
        @ApiModelProperty(value = "身高", example = "175")
        private Integer height;
    }

    Controller 用到的返回对象R:

    package com.abc.demo.entity;
    
    
    /**
     * 返回数据
     */
    public class R<T> {
        /**
         * 返回码
         * 0 正常,其他异常
         */
        private int returnCode = 0;
    
        /**
         * 描述
         */
        private String description = "OK";
    
        /**
         * 结果数据
         */
        private T result;
    
        public int getReturnCode() {
            return returnCode;
        }
        public String getDescription() {
            return description;
        }
        public T getResult() {
            return result;
        }
    
        public static R ok() {
            return new R();
        }
    
        public static <T> R<T> ok(T result) {
            R<T> r = new R<>();
            r.result = result;
            return r;
        }
        
        public static <T> R<T> error() {
            R<T> r = new R();
            r.returnCode = -1;
            r.description = "未知异常,请联系管理员";
            return r;
        }
    
        public static <T> R<T> error(String description) {
            R<T> r = new R();
            r.returnCode = -1;
            r.description = description;
            return r;
        }
        
        public static <T> R<T> error(int returnCode, String description) {
            R<T> r = new R();
            r.returnCode = returnCode;
            r.description = description;
            return r;
        }
    
    }
    R.java

    2.4、查看接口信息

    访问 http://localhost:8080/doc.html,可以看到文档页面更加的美观好用:

  • 相关阅读:
    markdownPad2 绿色破解版安装
    解决idea 控制台中文乱码
    PS CC 破解安装教程(亲测可用)
    mp4文件格式之fragment mp4
    音视频技术总结
    ffmpeg的内部Video Buffer管理和传送机制
    OMX Codec详细解析
    Gstreamer的一些基本概念与A/V同步分析
    stagefright omx小结
    OMXCodec与OMX事件处理流程
  • 原文地址:https://www.cnblogs.com/wuyongyin/p/14653401.html
Copyright © 2011-2022 走看看