SpringBoot 項目集成增強版 Swagger-Knife4j - 附常見問題及解決方案

1 - 引入 Maven 依賴

👇點這裏展開代碼👇
    <properties>
        <spring-boot.version>2.4.3</spring-boot.version>
        <spring.version>5.3.4</spring.version>
        <mybatis.starter.version>2.0.1</mybatis.starter.version>
        
        <swagger.version>3.0.0</swagger.version>
        <knife4j.version>3.0.3</knife4j.version>
        <slf4j.version>1.7.25</slf4j.version>
        <log4j.version>1.2.17</log4j.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>${swagger.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>${swagger.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-boot-starter</artifactId>
            <version>${swagger.version}</version>
            <exclusions>
                <exclusion>
                    <artifactId>guava</artifactId>
                    <groupId>com.google.guava</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <version>${knife4j.version}</version>
        </dependency>
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-annotations</artifactId>
            <version>${knife4j.version}</version>
        </dependency>

        <!-- 日誌框架 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4j.version}</version>
        </dependency>
    </dependencies>

2 - 編寫 SwaggerConfig 配置類

注意:要把此配置類放置在最外側,與 SpringBoot 的啓動類在同一個包下,不能是子包,否則可能會有一些奇怪的問題。

另外,Swagger 3.x 版本中,使用 EnableOpenApi 註解,而不是 EnableSwagger2 註解。

👇點這裏展開代碼👇
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.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;

/**
 * Swagger API 文檔的配置
 * 集成到 SpringBoot 中時,要放在 SpringBoot 啓動類 同級的目錄下
 */
@Configuration
@EnableOpenApi
public class Swagger2Config {

    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .enable(true) // 默認開啓
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.healchow.swagger.controller"))
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("HealChow Swagger Doc")
                .description("更多請關注:《https://healchow.com》")
                .version("1.0")
                .build();
    }

}

3 - Swagger 常用註解

待補充。。。

4 - 啓動項目後,訪問 Swagger 首頁出現 Whitelabel Error Page

👇點這裏展開代碼👇
@Configuration
@ComponentScan
public class ApplicationConfig extends WebMvcConfigurationSupport implements ServletContextInitializer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // 下面定義了攔截器,會導致 spring.resources.static-locations 配置失效
        registry.addResourceHandler("/**").addResourceLocations("classpath:/webapp/public/");

        // 配置 knife4j 文檔資源的訪問路徑
        registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        try {
            // 設置ThreadLocal攔截器
            registry.addInterceptor(threadLocalInterceptor()).addPathPatterns("/**")
                    .excludePathPatterns("/login/**").excludePathPatterns("/");

            super.addInterceptors(registry);
        } catch (Exception e) {
            LOGGER.error("Add ThreadLocal Interceptor error", e);
        }
    }

}

4 - 踩坑指南

4.1 Controller 中的接口都沒有顯示

在 Controller 類上用註解 @Api(tags = "公共接口(上傳/下載)") 標識當前 Controller 的功能, tags 的值包含反斜線,導致接口詳情無法顯示:

改成 @Api(tags = "公共接口(上傳、下載)") 後,顯示正常:

4.2 部分 Controller 中的接口顯示不全

如果請求參數是 Java 基本類型之外的其他複雜類型,比如 HttpServletRequest,那麼就不能用 @ApiImplicitParam 描述參數信息,比如下面這種就不行:

    @ApiOperation(value = "查詢數據條數")
    @ApiImplicitParam(name = "request", value = "請求體,參數有:startTime、endTime,格式:yyyyMMddHHmm", required = true)
    public Response<Integer> getDataCount(HttpServletRequest request) { }

可以在日誌中看到,出現了空指針異常,可能是沒有指定 dataTypeClass 導致的,有知道原因的同學,感謝留言告訴我呀🤝

最後刪掉 @ApiImplicitParam ,改成下面這種就可以全部顯示了:

    @ApiOperation(value = "查詢數據條數,請求參數有:startTime、endTime,格式:yyyyMMddHHmm")
    public Response<Integer> getDataCount(HttpServletRequest request) { }

4.3 頁面調試時,提示“xx參數不能爲空”

對於路徑中的變量(以 @PathVariable 註解標識),即使指定可以不填 required = false,在 Swagger 頁面也會顯示 id不能爲空

    @GetMapping("/getDetail/{id}")
    @ApiOperation(value = "查詢詳情")
    @ApiImplicitParam(name = "id", value = "數據ID", dataTypeClass = String.class, required = false)
    public Response<Object> getDetail(@PathVariable(required = false) String id) { }

爲了避免這種情況,可以把這個參數改成 @RequestParam,修改如下:

    @GetMapping("/getDetail")
    @ApiOperation(value = "查詢詳情")
    @ApiImplicitParam(name = "id", value = "數據ID", dataTypeClass = String.class, required = false)
    public Response<Object> getDetail(@RequestParam(required = false) String id) { }

參考資料

https://blog.csdn.net/sanyaoxu_2/article/details/80555328
https://zhuanlan.zhihu.com/p/21353795
https://juejin.cn/post/6844903607414816775
https://www.cnblogs.com/paddix/p/8204916.html
https://juejin.cn/post/6844903993890586632


版權聲明

作者:瘦風(https://healchow.com)

出處:博客園-瘦風的南牆(https://www.cnblogs.com/shoufeng)

感謝閱讀,公衆號 「瘦風的南牆」 ,手機端閱讀更佳,還有其他福利和心得輸出,歡迎掃碼關注🤝

本文版權歸博主所有,歡迎轉載,但 [必須在頁面明顯位置標明原文鏈接],否則博主保留追究相關人士法律責任的權利。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章