springboot集成knife4j配置问题

1、官方网站

knife4j 官网

https://doc.xiaominfo.com/

快速配置

https://doc.xiaominfo.com/docs/quick-start

旧版文档

https://doc.xiaominfo.com/v2/documentation/get_start.html

2、配置问题

公司遇到一个需要在生产环境关闭swagger文档的需求
相关版本

<spring.boot.version>2.1.14.RELEASE</spring.boot.version>
<knife4j.version>2.0.3</knife4j.version>

首先公司自己本身引入了公司自研的配置包,相关配置如下
也可以看到 需要添加 方法注解@ApiOperation 才会有swagger文档

import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import io.swagger.annotations.ApiOperation;
import java.util.Date;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Profile;
import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
@EnableKnife4j
@Import({BeanValidatorPluginsConfiguration.class, SwaggerApiInfoConfig.class})
@Profile({"dev", "test", "default"})
public class SwaggerConfig {
    @Value("${custom.swagger.title:系统xxx}")
    private String title;
    @Value("${custom.swagger.groupName:default}")
    private String groupName;

    public SwaggerConfig() {
    }

    @Bean
    public Docket productApi(ApiInfo apiInfo) {
        return (new Docket(DocumentationType.SWAGGER_2)).groupName(this.groupName).apiInfo(apiInfo).select().apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)).paths(PathSelectors.any()).build();
    }

    @Bean
    public ApiInfo apiInfo() {
        return (new ApiInfoBuilder()).title(this.title).termsOfServiceUrl("").version(DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss")).build();
    }
}

1)方案一
在nacos配置文件可以添加 配置来修改环境,上面的@Profile({“dev”, “test”, “default”})是可以支持的环境 修改为 integrate 之后还可以访问到界面,但是已经找不到具体接口。

spring:
  profiles:
    active: integrate

2)方案二
从权限上关闭,在nacos配置文件中添加,添加之后直接访问不到文档,显示无权限访问

knife4j:
  production: true 

3、源码分析

1)第一种方案的配置
查看@Profile 注解

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional({ProfileCondition.class})
public @interface Profile {
    String[] value();
}

结合我之前读的spring源码对于@Conditional注解会在类注册之前被解析到
它支持根据一定的条件来创建对应的Bean对象,并将Bean对象注册到IOC容器中。满足条件的Bean就会被注册到IOC容器中,不满足条件的Bean就不会被注册到IOC容器中。
spring源码 调试、分析和注释可以参考我的代码

https://gitee.com/fxysss/spring-framework-5.2.22.release

查看类ProfileCondition

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.springframework.context.annotation;

import java.util.Iterator;
import java.util.List;
import org.springframework.core.env.Profiles;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.util.MultiValueMap;

class ProfileCondition implements Condition {
    ProfileCondition() {
    }

    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
        if (attrs != null) {
            Iterator var4 = ((List)attrs.get("value")).iterator();

            Object value;
            do {
                if (!var4.hasNext()) {
                    return false;
                }

                value = var4.next();
            } while(!context.getEnvironment().acceptsProfiles(Profiles.of((String[])((String[])value))));

            return true;
        } else {
            return true;
        }
    }
}

可以定位到 acceptsProfiles 方法,该方法是在获取是否属于当前环境的配置
关键代码如下

    public boolean acceptsProfiles(Profiles profiles) {
        Assert.notNull(profiles, "Profiles must not be null");
        return profiles.matches(this::isProfileActive);
    }

    protected boolean isProfileActive(String profile) {
        this.validateProfile(profile);
        Set<String> currentActiveProfiles = this.doGetActiveProfiles();
        return currentActiveProfiles.contains(profile) || currentActiveProfiles.isEmpty() && this.doGetDefaultProfiles().contains(profile);
    }
    protected Set<String> doGetActiveProfiles() {
        synchronized(this.activeProfiles) {
            if (this.activeProfiles.isEmpty()) {
                String profiles = this.getProperty("spring.profiles.active");
                if (StringUtils.hasText(profiles)) {
                    this.setActiveProfiles(StringUtils.commaDelimitedListToStringArray(StringUtils.trimAllWhitespace(profiles)));
                }
            }

            return this.activeProfiles;
        }
    }

可以看出,我们需要配置 spring.profiles.active 为非对应环境的配置即可

2)第二种方案的配置
可以在knife4j自动配置类 Knife4jAutoConfiguration 中看到

@Bean
    @ConditionalOnMissingBean({ProductionSecurityFilter.class})
    @ConditionalOnProperty(
        name = {"knife4j.production"},
        havingValue = "true"
    )
    public ProductionSecurityFilter productionSecurityFilter(Knife4jProperties knife4jProperties) {
        boolean prod = false;
        ProductionSecurityFilter p = null;
        if (knife4jProperties == null) {
            if (this.environment != null) {
                String prodStr = this.environment.getProperty("knife4j.production");
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("swagger.production:{}", prodStr);
                }

                prod = Boolean.valueOf(prodStr);
            }

            p = new ProductionSecurityFilter(prod);
        } else {
            p = new ProductionSecurityFilter(knife4jProperties.isProduction());
        }

        return p;
    }

修改knife4j.production 即可

4、knife4j 常用配置

属性 默认值 说明值
knife4j.enable false 是否开启Knife4j增强模式
knife4j.cors false 是否开启一个默认的跨域配置,该功能配合自定义Host使用
knife4j.production false 是否开启生产环境保护策略,详情参考文档
knife4j.basic 对Knife4j提供的资源提供BasicHttp校验,保护文档
knife4j.basic.enable false 关闭BasicHttp功能
knife4j.basic.username basic用户名
knife4j.basic.password basic密码
knife4j.documents 自定义文档集合,该属性是数组
knife4j.documents.group 所属分组
knife4j.documents.name 类似于接口中的tag,对于自定义文档的分组
knife4j.documents.locations markdown文件路径,可以是一个文件夹(classpath:markdowns/*),也可以是单个文件(classpath:md/sign.md)
knife4j.setting 前端Ui的个性化配置属性
knife4j.setting.enableAfterScript true 调试Tab是否显示AfterScript功能,默认开启
knife4j.setting.language zh-CN Ui默认显示语言,目前主要有两种:中文(zh-CN)、英文(en-US)
knife4j.setting.enableSwaggerModels true 是否显示界面中SwaggerModel功能
knife4j.setting.swaggerModelName Swagger Models 重命名SwaggerModel名称,默认
knife4j.setting.enableDocumentManage true 是否显示界面中"文档管理"功能
knife4j.setting.enableReloadCacheParameter false 是否在每个Debug调试栏后显示刷新变量按钮,默认不显示
knife4j.setting.enableVersion false 是否开启界面中对某接口的版本控制,如果开启,后端变化后Ui界面会存在小蓝点
knife4j.setting.enableRequestCache true 是否开启请求参数缓存
knife4j.setting.enableFilterMultipartApis false 针对RequestMapping的接口请求类型,在不指定参数类型的情况下,如果不过滤,默认会显示7个类型的接口地址参数,如果开启此配置,默认展示一个Post类型的接口地址
knife4j.setting.enableFilterMultipartApiMethodType POST 具体接口的过滤类型
knife4j.setting.enableHost false 是否启用Host
knife4j.setting.enableHomeCustom false 是否开启自定义主页内容
knife4j.setting.homeCustomLocation 主页内容Markdown文件路径
knife4j.setting.enableSearch false 是否禁用Ui界面中的搜索框
knife4j.setting.enableFooter true 是否显示Footer
knife4j.setting.enableFooterCustom false 是否开启自定义Footer
knife4j.setting.footerCustomContent false 自定义Footer内容
knife4j.setting.enableDynamicParameter false 是否开启动态参数调试功能
knife4j.setting.enableDebug true 启用调试
knife4j.setting.enableOpenApi true 显示OpenAPI规范
knife4j.setting.enableGroup true 显示服务分组

  • 15
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值