最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot3整合knife4j(swagger3)的詳細(xì)過程

 更新時(shí)間:2026年06月08日 10:32:51   作者:多則惑少則明  
本文給大家介紹SpringBoot3整合knife4j(Swgger3)的關(guān)鍵步驟與常見問題解決方案,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧

一、引言

        使用jdk21版本創(chuàng)建的spring boot項(xiàng)目, 在SpringBoot3整合swagger3過程中遇到一些問題,網(wǎng)上很多寫的SpringBoot3 整合knife4j(swagger3)的步驟,完全照著做很多都是有問題的。 現(xiàn)在將遇到的問題做記錄。

二、SpringBoot3整合knife4j(swagger3)關(guān)鍵點(diǎn)梳理

1、 添加/修改依賴

  • Spring Boot 3.x必須使用knife4j-openapi3-jakarta(Jakarta命名空間)
<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
    <version>4.5.0</version>
</dependency>

網(wǎng)上很多文章說使用下面的maven是有問題的。 本人調(diào)試實(shí)際上遇到很多問題,一個(gè)問題解決又出了另一個(gè)問題。

<dependency>
        <groupId>com.github.xiaoymin</groupId>
         <artifactId>knife4j-spring-boot-starter</artifactId>
                <version>3.0.3</version>
 </dependency>
  • 我用的SpringBoot版本是3.4.5。SpringBoot3.x相比SpringBoot2.x特性上有很大改變。必須選擇SpringBoot3.x版本兼容的knife4j(swagger3)版本。 

看看knife4j官網(wǎng)怎么說: https://doc.xiaominfo.com/docs/quick-start

2、添加配置文件

package com.Knife4j;
//
import cn.hutool.core.util.RandomUtil;
import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.PathItem;
import io.swagger.v3.oas.models.Paths;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.media.Content;
import io.swagger.v3.oas.models.media.MediaType;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.responses.ApiResponse;
import io.swagger.v3.oas.models.responses.ApiResponses;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springdoc.core.customizers.GlobalOpenApiCustomizer;
import org.springdoc.core.models.GroupedOpenApi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Map;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class Knife4jConfig {
    private final static Logger logger = LoggerFactory.getLogger(Knife4jConfig.class);
    private static final String SERVICE_URL = "http://127.0.0.1:8886/tj4/doc.html";
    private static final String API_INFO_TITLE = "軟件接口文檔";
    private static final String API_INFO_VERSION = "V1.0";
    private static final String API_INFO_DESCRIPTION = "Api接口列表";
    private static final String API_INFO_LICENSE = "2025年度內(nèi)部文檔,違拷必究.";
    private static final String API_INFO_EMAIL = "zpphnkjxy@126.com";
    private static final String API_INFO_NAME = "zpp";
    // xxx1模塊
    @Bean
    public GroupedOpenApi api4() {
        return GroupedOpenApi.builder()
                .group("regularGrade-module-api")
                .displayName("平時(shí)成績模塊接口")
                .packagesToScan("com.call.controller.regularGrade")//xxx1模塊接口所在包
                // 自定義全局響應(yīng)碼
                .addOpenApiCustomizer((this::setCustomStatusCode))
                .build();
    }
    // 智能評分模塊
    @Bean
    public GroupedOpenApi api3() {
        return GroupedOpenApi.builder()
                .group("IntelligentScoring-module-api")
                .displayName("智能評分模塊接口")
                .packagesToScan("com.call.controller.intelligentScoring")
                // 自定義全局響應(yīng)碼
                .addOpenApiCustomizer((this::setCustomStatusCode))
                .build();
    }
    // AI大模型Agent接口
    @Bean
    public GroupedOpenApi api2() {
        return GroupedOpenApi.builder()
                .group("aiagent-module-api")
                .displayName("AI大模型Agent接口")
                .packagesToScan("com.ai.LangChain4j.agent2.DeclarativeAPI")
                // .pathsToMatch("/v1/**")
                .addOpenApiMethodFilter(method -> method.isAnnotationPresent(io.swagger.v3.oas.annotations.Operation.class))
                // 自定義全局響應(yīng)碼
                .addOpenApiCustomizer((this::setCustomStatusCode))
                .build();
    }
    @Bean
    public OpenAPI openAPI() {
        return new OpenAPI()
                .info(new Info()
                        .title(API_INFO_TITLE)
                        .description(API_INFO_DESCRIPTION)
                        .version(API_INFO_VERSION)
                        .contact(new Contact().name(API_INFO_NAME).email(API_INFO_EMAIL))
                        .license(new License().name(API_INFO_LICENSE).url(SERVICE_URL))
                );
    }
    /**
     * 設(shè)置自定義錯(cuò)誤碼
     *
     * @param openApi openApi對象
     */
    private void setCustomStatusCode(OpenAPI openApi) {
        if (openApi.getPaths() != null) {
            Paths paths = openApi.getPaths();
            for (Map.Entry<String, PathItem> entry : paths.entrySet()) {
                String key = entry.getKey();
                PathItem value = entry.getValue();
                // put方式自定義全局響應(yīng)碼
                Operation put = value.getPut();
                // get方式自定義全局響應(yīng)碼
                Operation get = value.getGet();
                // delete方式自定義全局響應(yīng)碼
                Operation delete = value.getDelete();
                // post方式自定義全局響應(yīng)碼
                Operation post = value.getPost();
                if (put != null) {
                    put.setResponses(handleResponses(put.getResponses()));
                }
                if (get != null) {
                    get.setResponses(handleResponses(get.getResponses()));
                }
                if (delete != null) {
                    delete.setResponses(handleResponses(delete.getResponses()));
                }
                if (post != null) {
                    post.setResponses(handleResponses(post.getResponses()));
                }
            }
        }
    }
    /**
     * 處理不同請求方式中的自定義響應(yīng)碼
     * - 響應(yīng)碼中使用原有的響應(yīng)體Content(否則會造成BaseRes中通用的data無法解析各自的對象)
     * - 使用原生的ApiResponses作為返回體(否則會造成前端響應(yīng)示例和響應(yīng)內(nèi)容中丟失注釋)
     *
     * @param responses 響應(yīng)體集合
     * @return 返回處理后的響應(yīng)體集合
     */
    private ApiResponses handleResponses(ApiResponses responses) {
        // 設(shè)置默認(rèn)Content
        Content content = new Content();
        // 以下代碼注釋,因?yàn)闊o論如何都會從原生responses中獲取到一個(gè)Content
        // MediaType mediaType = new MediaType();
        // Schema schema = new Schema();
        // schema.set$ref("#/components/schemas/BaseRes");
        // mediaType.setSchema(schema);
        // content.addMediaType("*/*", mediaType);
        // 從原來的responses中獲取原生Content
        for (Map.Entry<String, ApiResponse> entry : responses.entrySet()) {
            String key = entry.getKey();
            ApiResponse apiResponse = entry.getValue();
            if (apiResponse != null) {
                content = apiResponse.getContent();
                break;
            }
        }
        // 獲取全部全局響應(yīng)自定義列表
        Map<Integer, String> map = StatusCode.toMap();
        // 設(shè)置全局響應(yīng)碼
        for (Map.Entry<Integer, String> entry : map.entrySet()) {
            ApiResponse api = new ApiResponse();
            api.setContent(content);
            api.description(entry.getValue());
            responses.addApiResponse(entry.getKey() + "", api);
        }
        return responses;
    }
    /**
     * 根據(jù)@Tag 上的排序,寫入x-order
     *
     * @return the global open api customizer
     */
    @Bean
    public GlobalOpenApiCustomizer orderGlobalOpenApiCustomizer() {
        return openApi -> {
            if (openApi.getTags()!=null){
                openApi.getTags().forEach(tag -> {
                    Map<String,Object> map=new HashMap<>();
                    map.put("x-order", RandomUtil.randomInt(0,100));
                    tag.setExtensions(map);
                });
            }
            if(openApi.getPaths()!=null){
                openApi.addExtension("x-test123","333");
                openApi.getPaths().addExtension("x-abb",RandomUtil.randomInt(1,100));
            }
        };
    }
    @Bean
    public OpenAPI customOpenAPI() {
        return new OpenAPI()
                .info(new Info()
                        .title("AI大模型API")
                        .version("1.0")
                        .description( "Knife4j集成springdoc-openapi")
                        .termsOfService("http://doc.xiaominfo.com")
                        .license(new License().name("Apache 2.0")
                                .url("http://doc.xiaominfo.com")));
    }
}

3、啟動(dòng)springboot

啟動(dòng)成功,訪問:http://127.0.0.1:8886/doc.html

出現(xiàn)類似下面的頁面:

4、配置項(xiàng)

springdoc:
  # 防止全局異常處理器的響應(yīng)定義覆蓋所有接口[citation:2]
  override-with-generic-response: false
  # 禁用損壞引用清理(如遇到Schema解析問題可嘗試)[citation:4]
  remove-broken-reference-definitions: false
  swagger-ui:
    path: /doc.html
    tags-sorter: alpha
    operations-sorter: alpha
    api-docs:
      path: /v3/api-docs
    group-configs:
      - group: 'default'
        paths-to-match: '/**'
        packages-to-scan: com
  # knife4j的增強(qiáng)配置,不需要增強(qiáng)可以不配
  knife4j:
    enable: true
    setting:
      language: zh_cn

運(yùn)行結(jié)果(目前訪問doc.html,會自動(dòng)跳轉(zhuǎn)到swagger-ui/index.html):

5、配置項(xiàng)中添加更多控制細(xì)節(jié)

配置項(xiàng)如下:

# 配置Knife4j,以啟用Swagger文檔的增強(qiáng)功能和定制化展示
knife4j:
  # 啟用Knife4j擴(kuò)展
  enable: true
  # 配置展示的文檔分組
  documents:
    -
      # 文檔分組標(biāo)題
      group: 2.X版本
      # 文檔分組描述
      name: 接口簽名
      # 指定接口文檔的位置
      locations: classpath:sign/*
  # 配置Knife4j的展示細(xì)節(jié)和功能開關(guān)
  setting:
    # 設(shè)置界面語言
    language: zh-CN
    # 啟用Swagger模型展示
    enable-swagger-models: true
    # 啟用文檔管理功能
    enable-document-manage: true
    # 設(shè)置Swagger模型的顯示名稱
    swagger-model-name: 實(shí)體類列表
    # 是否顯示版本信息
    enable-version: false
    # 是否啟用參數(shù)緩存刷新
    enable-reload-cache-parameter: false
    # 啟用后端腳本支持
    enable-after-script: true
    # 過濾特定方法類型的multipart/form-data接口
    enable-filter-multipart-api-method-type: POST
    # 是否過濾所有multipart/form-data類型的接口
    enable-filter-multipart-apis: false
    # 啟用請求緩存
    enable-request-cache: true
#    # 是否顯示自定義主機(jī)名
#    enable-host: false
#    # 設(shè)置自定義的主機(jī)名
#    enable-host-text: 192.168.0.193:8000
#    # 啟用自定義首頁
#    enable-home-custom: true
#    # 設(shè)置自定義首頁的路徑
#    home-custom-path: classpath:markdown/home.md
    # 是否啟用搜索功能
    enable-search: false
    # 是否顯示頁腳
    enable-footer: false
    # 啟用自定義頁腳內(nèi)容
    enable-footer-custom: true
    # 設(shè)置自定義頁腳的內(nèi)容
    footer-custom-content: Apache License 2.0
    # 是否啟用動(dòng)態(tài)參數(shù)
    enable-dynamic-parameter: false
    # 啟用調(diào)試模式
    enable-debug: true
    # 啟用OpenAPI 3.0的支持
    enable-open-api: false
    # 啟用接口分組功能
    enable-group: true
  # 是否啟用CORS跨域支持
  cors: false
  # 是否啟用生產(chǎn)模式
  production: false
  # 配置基本的認(rèn)證信息
  basic:
    # 啟用基本認(rèn)證
    enable: false
    # 設(shè)置用戶名
    username: admin
    # 設(shè)置密碼
    password: 123
springdoc:
  # 防止全局異常處理器的響應(yīng)定義覆蓋所有接口[citation:2]
  override-with-generic-response: false
  # 禁用損壞引用清理(如遇到Schema解析問題可嘗試)[citation:4]
  remove-broken-reference-definitions: false
  swagger-ui:
    path: /doc.html
    tags-sorter: alpha
    operations-sorter: alpha
    api-docs:
      path: /v3/api-docs
    group-configs:
      - group: 'default'
        paths-to-match: '/**'
        packages-to-scan: com

目前啟動(dòng)時(shí)會報(bào)如下錯(cuò)誤(暫時(shí)未解決):

2025-12-24T23:04:56.337+08:00 WARN 35067 --- [langchain4jAI] [  restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'knife4jAutoConfiguration' defined in URL [jar:file:/Users/apple/.m2/repository/com/github/xiaoymin/knife4j-openapi3-jakarta-spring-boot-starter/4.5.0/knife4j-openapi3-jakarta-spring-boot-starter-4.5.0.jar!/com/github/xiaoymin/knife4j/spring/configuration/Knife4jAutoConfiguration.class]: Unsatisfied dependency expressed through constructor parameter 0: No qualifying bean of type 'com.github.xiaoymin.knife4j.spring.configuration.Knife4jProperties' available: expected single matching bean but found 2: knife4jProperties,knife4j-com.github.xiaoymin.knife4j.spring.configuration.Knife4jProperties
2025-12-24T23:04:56.444+08:00 INFO 35067 --- [langchain4jAI] [  restartedMain] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
2025-12-24T23:04:56.478+08:00 INFO 35067 --- [langchain4jAI] [  restartedMain] .s.b.a.l.ConditionEvaluationReportLogger :
Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2025-12-24T23:04:56.762+08:00 ERROR 35067 --- [langchain4jAI] [  restartedMain] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in com.github.xiaoymin.knife4j.spring.configuration.Knife4jAutoConfiguration required a single bean, but 2 were found:
- knife4jProperties: defined in URL [jar:file:/Users/apple/.m2/repository/com/github/xiaoymin/knife4j-openapi3-jakarta-spring-boot-starter/4.5.0/knife4j-openapi3-jakarta-spring-boot-starter-4.5.0.jar!/com/github/xiaoymin/knife4j/spring/configuration/Knife4jProperties.class]
- knife4j-com.github.xiaoymin.knife4j.spring.configuration.Knife4jProperties: defined in unknown location
This may be due to missing parameter name information
Action:
Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed
Ensure that your compiler is configured to use the '-parameters' flag.
You may need to update both your build tool settings as well as your IDE.
(See https://github.com/spring-projects/spring-framework/wiki/Upgrading-to-Spring-Framework-6.x#parameter-name-ret

等等

三、問題梳理

問題1: 啟動(dòng)springboot后訪問doc.html頁面報(bào)錯(cuò)

java.lang.NoSuchMethodError: 'void org.springframework.web.method.ControllerAdviceBean.<init>(java.lang.Object)'] with root cause
java.lang.NoSuchMethodError: 'void org.springframework.web.method.ControllerAdviceBean.<init>(java.lang.Object)'
	at org.springdoc.core.service.GenericResponseService.lambda$getGenericMapResponse$8(GenericResponseService.java:702) ~[springdoc-openapi-starter-common-2.3.0.jar:2.3.0]
	at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:178) ~[na:na]
	at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:1024) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:575) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260) ~[na:na]
	at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:616) ~[na:na]
	at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:622) ~[na:na]
	at java.base/java.util.stream.ReferencePipeline.toList(ReferencePipeline.java:627) ~[na:na]
	at org.springdoc.core.service.GenericResponseService.getGenericMapResponse(GenericResponseService.java:704) ~[springdoc-openapi-starter-common-2.3.0.jar:2.3.0]
	at org.springdoc.core.service.GenericResponseService.build(GenericResponseService.java:246) ~[springdoc-openapi-starter-common-2.3.0.jar:2.3.0]
	at org.springdoc.api.AbstractOpenApiResource.calculatePath(AbstractOpenApiResource.java:499) ~[springdoc-openapi-starter-common-2.3.0.jar:2.3.0]

網(wǎng)上查了很多資料,最終看到下面的兩個(gè)內(nèi)容解決了問題:

http://www.fzitv.net/article/223113.htm

http://www.fzitv.net/program/353796sg3.htm

由于我不想降低springboot的版本, 故而選擇修改配置文件。 最終解決辦法: 確定該問題是增加異常處理器類后,對全局的異常起作用了,如對swagger也起作用了。所以可以在application配置里增加springdoc的配置,防止全局異常處理器的響應(yīng)定義覆蓋所有接口。

application.yml添加的內(nèi)容如下所示:

springdoc:
  # 防止全局異常處理器的響應(yīng)定義覆蓋所有接口[citation:2]
  override-with-generic-response: false
  # 禁用損壞引用清理(如遇到Schema解析問題可嘗試)[citation:4]
  remove-broken-reference-definitions: false

到此這篇關(guān)于SpringBoot3整合knife4j(swagger3)的詳細(xì)過程的文章就介紹到這了,更多相關(guān)SpringBoot3整合knife4j內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

温州市| 夏津县| 普宁市| 虹口区| 蒙山县| 唐山市| 同仁县| 隆安县| 蒙山县| 蒲江县| 工布江达县| 呼图壁县| 芦山县| 鲜城| 威海市| 北川| 台东县| 敦化市| 琼结县| 辛集市| 信丰县| 黄山市| 通山县| 景宁| 二手房| 承德市| 礼泉县| 祁阳县| 遵义县| 普定县| 兴和县| 宝鸡市| 青冈县| 阿拉善盟| 南宫市| 赤水市| 洮南市| 天祝| 大悟县| 阿城市| 舞阳县|