Skip to content
🔴🟠🟡🟢🔵🟣🟤⚫⚪

(八)knife4j接口文档组件

基础项目地址:

https://gitee.com/springzb/admin-boot

一、引入maven依赖

xml
<!--swagger  knife4j 最新的稳定版本-->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <version>2.0.9</version>
        </dependency>
         <!--google工具类-->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>30.0-jre</version>
        </dependency>

swagger配置类SwaggerProperties.java

java
package cn.mesmile.admin.common.config.swagger;

import cn.mesmile.admin.common.constant.AdminConstant;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Swagger配置类
 *
 * @author zb
 * @Description
 */
@ConfigurationProperties("swagger")
public class SwaggerProperties {

    private List<String> basePackages = new ArrayList(Collections.singletonList(AdminConstant.BASE_PACKAGE));
    private List<String> basePath = new ArrayList();
    private List<String> excludePath = new ArrayList();
    private String title = "Admin 接口文档系统";
    private String description = "Admin 接口文档系统";
    private String version = "1.0.0.RELEASE";
    private String license = "Powered By Admin";
    private String licenseUrl = "https://www.mesmile.cn";
    private String termsOfServiceUrl = "https://www.mesmile.cn";
    private String host = "";
    private SwaggerProperties.Contact contact = new SwaggerProperties.Contact();
    private SwaggerProperties.Authorization authorization = new SwaggerProperties.Authorization();


    public List<String> getBasePackages() {
        return this.basePackages;
    }

    public List<String> getBasePath() {
        return this.basePath;
    }

    public List<String> getExcludePath() {
        return this.excludePath;
    }

    public String getTitle() {
        return this.title;
    }

    public String getDescription() {
        return this.description;
    }

    public String getVersion() {
        return this.version;
    }

    public String getLicense() {
        return this.license;
    }

    public String getLicenseUrl() {
        return this.licenseUrl;
    }

    public String getTermsOfServiceUrl() {
        return this.termsOfServiceUrl;
    }

    public String getHost() {
        return this.host;
    }

    public SwaggerProperties.Contact getContact() {
        return this.contact;
    }

    public SwaggerProperties.Authorization getAuthorization() {
        return this.authorization;
    }

    public void setBasePackages(final List<String> basePackages) {
        this.basePackages = basePackages;
    }

    public void setBasePath(final List<String> basePath) {
        this.basePath = basePath;
    }

    public void setExcludePath(final List<String> excludePath) {
        this.excludePath = excludePath;
    }

    public void setTitle(final String title) {
        this.title = title;
    }

    public void setDescription(final String description) {
        this.description = description;
    }

    public void setVersion(final String version) {
        this.version = version;
    }

    public void setLicense(final String license) {
        this.license = license;
    }

    public void setLicenseUrl(final String licenseUrl) {
        this.licenseUrl = licenseUrl;
    }

    public void setTermsOfServiceUrl(final String termsOfServiceUrl) {
        this.termsOfServiceUrl = termsOfServiceUrl;
    }

    public void setHost(final String host) {
        this.host = host;
    }

    public void setContact(final SwaggerProperties.Contact contact) {
        this.contact = contact;
    }

    public void setAuthorization(final SwaggerProperties.Authorization authorization) {
        this.authorization = authorization;
    }

    @Data
    public static class AuthorizationApiKey {
        private String name = "";
        private String keyName = "";
        private String passAs = "";
    }

    @Data
    public static class AuthorizationScope {
        private String name = "";
        private String scope = "";
        private String description = "";
    }

    public static class Authorization {
        private String name = "";
        private String authRegex = "^.*$";
        private List<SwaggerProperties.AuthorizationScope> authorizationScopeList = new ArrayList();
        private List<SwaggerProperties.AuthorizationApiKey> authorizationApiKeyList = new ArrayList();
        private List<String> tokenUrlList = new ArrayList();

        public String getName() {
            return this.name;
        }

        public String getAuthRegex() {
            return this.authRegex;
        }

        public List<SwaggerProperties.AuthorizationScope> getAuthorizationScopeList() {
            return this.authorizationScopeList;
        }

        public List<SwaggerProperties.AuthorizationApiKey> getAuthorizationApiKeyList() {
            return this.authorizationApiKeyList;
        }

        public List<String> getTokenUrlList() {
            return this.tokenUrlList;
        }

        public void setName(final String name) {
            this.name = name;
        }

        public void setAuthRegex(final String authRegex) {
            this.authRegex = authRegex;
        }

        public void setAuthorizationScopeList(final List<SwaggerProperties.AuthorizationScope> authorizationScopeList) {
            this.authorizationScopeList = authorizationScopeList;
        }

        public void setAuthorizationApiKeyList(final List<SwaggerProperties.AuthorizationApiKey> authorizationApiKeyList) {
            this.authorizationApiKeyList = authorizationApiKeyList;
        }

        public void setTokenUrlList(final List<String> tokenUrlList) {
            this.tokenUrlList = tokenUrlList;
        }

    }

    @Data
    public static class Contact {
        private String name = "admin";
        private String url = "https://gitee.com/springzb/admin-boot";
        private String email = "admin@163.com";
    }
}

SwaggerConfiguration 配置

java
package cn.mesmile.admin.common.config.swagger;

import cn.mesmile.admin.common.constant.AdminConstant;
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import com.github.xiaoymin.knife4j.spring.extension.OpenApiExtensionResolver;
import com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
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.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.EnableSwagger2WebMvc;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * Swagger配置类
 *
 * @author zb
 * @Description
 */
@EnableConfigurationProperties({SwaggerProperties.class})
@Configuration
@EnableSwagger2WebMvc
@EnableKnife4j
@RequiredArgsConstructor
public class SwaggerConfiguration {

    /**
     * 引入swagger配置类
     */
    private final SwaggerProperties swaggerProperties;

    /**
     * 引入Knife4j扩展类
     */
    private final OpenApiExtensionResolver openApiExtensionResolver;


    @Bean
    public Docket sysDocket() {
        return docket("系统模块",
                Arrays.asList(AdminConstant.BASE_PACKAGE + ".admin.modules.system"));
    }

//  @Bean
//  public Docket flowDocket() {
//    return docket("工作流模块", Collections.singletonList(AdminConstant.BASE_PACKAGE + ".flow"));
//  }

    private Docket docket(String groupName, List<String> basePackages) {
        return new Docket(DocumentationType.SWAGGER_2)
                .groupName(groupName)
                .apiInfo(apiInfo())
//      .ignoredParameterTypes(AdminUser.class)
                .select()
                .apis(SwaggerUtil.basePackages(basePackages))
                .paths(PathSelectors.any())
                .build().securityContexts(securityContexts()).securitySchemes(securitySchemas())
                .extensions(openApiExtensionResolver.buildExtensions(groupName));
    }

    private List<SecurityContext> securityContexts() {
        return Collections.singletonList(SecurityContext.builder()
                .securityReferences(defaultAuth())
                .forPaths(PathSelectors.regex("^.*$"))
                .build());
    }

    List<SecurityReference> defaultAuth() {
        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverywhere");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        return Lists.newArrayList(new SecurityReference(SwaggerUtil.clientInfo().getName(), authorizationScopes),
                new SecurityReference(SwaggerUtil.adminAuth().getName(), authorizationScopes),
                new SecurityReference(SwaggerUtil.adminTenant().getName(), authorizationScopes));
    }

    private List<SecurityScheme> securitySchemas() {
        return Lists.newArrayList(SwaggerUtil.clientInfo(), SwaggerUtil.adminAuth(), SwaggerUtil.adminTenant());
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title(swaggerProperties.getTitle())
                .description(swaggerProperties.getDescription())
                .license(swaggerProperties.getLicense())
                .licenseUrl(swaggerProperties.getLicenseUrl())
                .termsOfServiceUrl(swaggerProperties.getTermsOfServiceUrl())
                .contact(new Contact(swaggerProperties.getContact().getName(), swaggerProperties.getContact().getUrl(), swaggerProperties.getContact().getEmail()))
                .version(swaggerProperties.getVersion())
                .build();
    }

}

SwaggerUtil 工具类型,新增请求头

java
package cn.mesmile.admin.common.config.swagger;

import com.google.common.base.Function;
import com.google.common.base.Optional;
import springfox.documentation.RequestHandler;
import springfox.documentation.service.ApiKey;

import java.util.Iterator;
import java.util.List;
import java.util.function.Predicate;

/**
 * Swagger工具类
 *
 * @author zb
 * @Description
 */
public class SwaggerUtil {

    public static Predicate<RequestHandler> basePackages(final List<String> basePackages) {
        return (input) -> {
            return (Boolean) declaringClass(input).transform(handlerPackage(basePackages)).or(true);
        };
    }

    private static Function<Class<?>, Boolean> handlerPackage(final List<String> basePackages) {
        return (input) -> {
            Iterator iterator = basePackages.iterator();
            boolean isMatch;
            do {
                if (!iterator.hasNext()) {
                    return false;
                }
                String strPackage = (String) iterator.next();
                isMatch = input.getPackage().getName().startsWith(strPackage);
            } while (!isMatch);
            return true;
        };
    }

    private static Optional<? extends Class<?>> declaringClass(RequestHandler input) {
        return Optional.fromNullable(input.declaringClass());
    }

    public static ApiKey clientInfo() {
        return new ApiKey("ClientInfo", "Authorization", "header");
    }

    public static ApiKey adminAuth() {
        return new ApiKey("AdminAuth", "Admin-Auth", "header");
    }

    public static ApiKey adminTenant() {
        return new ApiKey("TenantId", "Tenant-Id", "header");
    }
}

application.yml中新增swagger配置

yaml
#swagger公共信息
swagger:
  title: admin项目
  description: admin项目
  version: 1.0.0.RELEASE
  license: Powered By Admin
  license-url: https://www.mesmile.cn
  terms-of-service-url: https://www.mesmile.cn
  contact:
    name: admin
    email: admin@163.com
    url: https://gitee.com/springzb/admin-boot
    
    

spring:
  # Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException
  # 因为Springfox 使用的路径匹配是基于AntPathMatcher的,而Spring Boot 2.6.X使用的是PathPatternMatcher
  mvc:
    pathmatch:
      matching-strategy: ant_path_matcher

application-dev.yml中新增 knife4j配置

yaml
#knife4j配置
knife4j:
  #启用
  enable: true
  #基础认证
  basic:
    enable: false
    username: admin
    password: admin
  #增强配置
  setting:
    enableSwaggerModels: true
    enableDocumentManage: true
    enableHost: false
    enableHostText: http://localhost
    enableRequestCache: true
    enableFilterMultipartApis: false
    enableFilterMultipartApiMethodType: POST
    language: zh-CN
    enableFooter: false
    enableFooterCustom: true
    footerCustomContent: Copyright © 2022 Admin All Rights Reserved

二、测试

java
package cn.mesmile.admin.modules.system.controller;

import cn.mesmile.admin.common.result.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import sun.net.www.protocol.http.HttpURLConnection;

/**
 * @author zb
 * @Description
 */
@Api(tags = "用户登录测试接口")
@Slf4j
@RequestMapping("/api/v1/hello")
@RestController
public class HelloController {

    @ApiOperation(value = "用户登录测试接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name="word",value="关键字备注",required = true,type="Integer")
    })
    @GetMapping("/get")
    public R hello (@RequestParam("word") String word) {
        return R.data(word);
    }

}

输入 http://127.0.0.1:8080/doc 访问文档

此处得到接口文档

三、Swagger注解参数说明

作用范围API使用位置
对象属性@ApiModelProperty用在出入参数对象的字段上
协议集描述@Api用于controller类上
协议描述@ApiOperation用在contrller的方法上
Response集@ApiResponses用在controller的方法上
Response@ApiResponse用在@ApiResponses里边
非对象参数集@ApilmplicitParams用在controller的方法上
非对象参数描述@ApilmplicitParam用在@ApilmplicitParams的方法里边
描述返回对象的意义@ApiModel用在返回对象类上

@Api说明

@ApiOperation:controller方法上说明

@ApiOperation:"用在请求的方法上,说明方法的作用"

value="说明方法的作用"

notes="方法的备注说明"

@ApiImplicitParams、@ApiImplicitParam:controller方法参数的说明

@ApiImplicitParams:用在请求的方法上,包含一组参数说明

@ApiImplicitParam:对单个参数的说明

name:参数名

value:参数的说明、描述

required:参数是否必须必填

paramType:参数放在哪个地方

· query --> 请求参数的获取:@RequestParam

· header --> 请求参数的获取:@RequestHeader

· path(用于restful接口)--> 请求参数的获取:@PathVariable

· body(请求体)--> @RequestBody User user

· form(普通表单提交)

dataType:参数类型,默认String,其它值dataType="Integer"

defaultValue:参数的默认值

@ApiResponses、@ApiResponse:controller响应状态状态的说明

@ApiResponses:响应状态的说明。是个数组,可包含多个 @ApiResponse

@ApiResponse:每个参数的说明

code:数字,例如400

message:信息,例如"请求参数没填好"

response:抛出异常的类