首頁 > 軟體

全網最全SpringBoot整合swagger的詳細教學

2022-08-02 14:02:37

一. 介面檔案概述

swagger是當下比較流行的實時介面文檔案生成工具。介面檔案是當前前後端分離專案中必不可少的工具,在前後端開發之前,後端要先出介面檔案,前端根據介面檔案來進行專案的開發,雙方開發結束後在進行聯調測試。

所以介面檔案其實就是開發之前雙方之間的一種約定。通常介面檔案分為離線的和實時的。離線的介面檔案工具有: word(相當於沒說), YAPI, 小么雞等,這種檔案需要程式設計師在上面編寫,也一般具備介面測試功能。通常是由開發人員先在離線介面檔案上編寫資訊,然後交給前端人員參照開發。最大的弊端是當我們的介面程式發生變動時,需要回過頭來維護上面的內容,很麻煩,是真的麻煩。

實時介面檔案就是可以根據我們的程式碼來自動生成相應的介面檔案,優點就是我們的程式碼發生變化時,生成的介面檔案也會自動更新,無需我們關注修改,主需要按時釋出即可。但是由於是根據程式碼自動生成的,所以最大的弊端就是程式碼侵入性強,需要我們在專案程式碼中整合生成介面檔案的相關程式碼。實時介面檔案現在的方案有很多,但是swagger還是其中比較有影響力的一個。

二. SpringBoot整合swagger2

官網地址: swagger.io 當然,官網都是英文的,看起來還是比較麻煩的。建議大家直接按照我的步驟來,還是很簡單的。

同時在說一點: swagger分為swagger2 和swagger3兩個常用版本。二者區別不是很大,主要對於依賴和註解進行了優化。swagger2需要引入2個jar包,swagger3只需要一個,用起來沒有什麼大的區別。下面以swagger2為例。

2.1 引入依賴

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.9.2</version>
</dependency>

2.2 引入設定

首先需要新增一個註解 : @EnableSwagger2。 這個註解我們可以新增到SpringBoot的啟動類上,也可以自定義一個設定類,放到上面。新增了這個註解以後,就代表我們已經在專案中開啟了Swagger的功能。

我們採用第二種方式,自己定義一個設定類,正好還可以新增一個Docket設定。 所謂Docket設定,就是一組(一個專案或一個版本)介面檔案的設定,比如設定名稱, 聯絡人等等。

我們在config資料夾下,新增一個SwaggerConfig類。

@Configuration
@EnableSwagger2
public class SwaggerConfig {
    /**
     * 設定多個:
     *
     * @Bean
     *     public Docket appApi() {
     *
     *         List<Parameter> pars = new ArrayList<>();
     *         ParameterBuilder token = new ParameterBuilder();
     *         token.name("token").description("使用者令牌").modelRef(new ModelRef("string")).parameterType("header").required(false)
     *                 .build();
     *         pars.add(token.build());
     *
     *         return new Docket(DocumentationType.SWAGGER_2).select().paths(regex("/app/.*")).build()
     *                 .globalOperationParameters(pars).apiInfo(pdaApiInfo()).useDefaultResponseMessages(false)
     *                 .enable(enableSwagger)
     *                 .groupName("appApi");
     *
     *     }
     *
     *     @Bean
     *     public Docket adminApi() {
     *
     *         List<Parameter> pars = new ArrayList<>();
     *         ParameterBuilder token = new ParameterBuilder();
     *         token.name("token").description("使用者令牌").modelRef(new ModelRef("string")).parameterType("header").required(false)
     *                 .build();
     *         pars.add(token.build());
     *         return new Docket(DocumentationType.SWAGGER_2).select().paths(regex("/admin/.*")).build()
     *                 .globalOperationParameters(pars).apiInfo(pdaApiInfo()).useDefaultResponseMessages(false)
     *                 .enable(enableSwagger)
     *                 .groupName("adminApi");
     *
     *     }
     *
     *
     * @return
     */

    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select()
                .apis(RequestHandlerSelectors.basePackage("com.lsqingfeng.action.swagger.controller")).paths(PathSelectors.any())
                .build().globalOperationParameters(setHeaderToken());

    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder().title("action-swagger").description("swagger實戰").termsOfServiceUrl("")
                .version("1.0").build();
    }

    /**
     * @Description: 設定swagger檔案中全域性引數
     * @param
     * @Date: 2020/9/11 10:15
     * @return: java.util.List<springfox.documentation.service.Parameter>
     */

    private List<Parameter> setHeaderToken() {
        List<Parameter> pars = new ArrayList<>();
        ParameterBuilder userId = new ParameterBuilder();
        userId.name("token").description("使用者TOKEN").modelRef(new ModelRef("string")).parameterType("header")
                .required(true).build();
        pars.add(userId.build());
        return pars;
    }
}

上面就是一個設定案例, 還設定了一個setToken方法,代表生成檔案的所有介面中,都要包含一個header型別的token引數。

2.3 給Controller 新增註解

我們介面檔案的直接描述主要就是在Controller這一層,比如這個介面的功能,引數的名稱,返回值的名稱等。這些值我們都需要在Controller上通過給方法上,請求引數和返回引數上新增對應的註解,swagger才能幫我們生成相應的介面檔案。這也就是我前面提到的對現有程式碼的侵入性。

我們來寫一個案例。

首先先建立一個vo的包,裡邊寫我們的請求和相應引數,使用JavaBean定義出請求和響應的資料結構。注意這裡要新增相應的註解:

請求類:

package com.lsqingfeng.springboot.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
 * @className: SwaggerReqVO
 * @description:
 * @author: sh.Liu
 * @date: 2022-03-22 19:19
 */
@Data
@ApiModel("建立Swagger請求引數")
public class SwaggerReqVO {

    @ApiModelProperty("id")
    private Integer id;

    @ApiModelProperty("姓名")
    private String name;

    @ApiModelProperty("性別")
    private Integer gender;
}

響應類:

package com.lsqingfeng.springboot.vo;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

/**
 * @className: SwaggerResVO
 * @description:
 * @author: sh.Liu
 * @date: 2022-03-22 19:20
 */
@Data
@ApiModel("建立Swagger響應結果")
public class SwaggerResVO {

    @ApiModelProperty("id")
    private Integer id;

    @ApiModelProperty("姓名")
    private String name;

    @ApiModelProperty("性別")
    private Integer gender;

    @ApiModelProperty("啥啥")
    private String what;
}

這裡分別使用了 @ApiModel註解和 @@ApiModelProperty 註解定義了實體的名稱和欄位的名稱,方便生成介面檔案時展示。

再來看Controller:

package com.lsqingfeng.springboot.controller;

import com.lsqingfeng.springboot.vo.SwaggerReqVO;
import com.lsqingfeng.springboot.vo.SwaggerResVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;

/**
 * @className: SwaggerController
 * @description: swagger 介面測試
 * @author: sh.Liu
 * @date: 2022-03-22 19:18
 */
@RestController
@RequestMapping("/swagger")
@Api(value = "使用者介面", tags = {"使用者介面"})
public class SwaggerController {

    @ApiOperation("新增使用者")
    @PostMapping("save")
    public String save(@RequestBody SwaggerReqVO req) {
        return "success";
    }

    @GetMapping("getById")
    @ApiOperation("根據條件查詢使用者")
    public SwaggerResVO getById(@RequestBody SwaggerResVO req) {
        return new SwaggerResVO();
    }
}

這裡使用了@Api註解和 @ApiOperation註解分別標註了介面組名和介面的名稱。現在我們啟動專案。

發現報了這個錯誤。

上網查詢原因說是SpringBoot2.6版本和Swagger2.9.2不相容導致的。 也有人說是由於guava這個包的版本過低導致的。

我都分別試了一下,替換了guava的高版本依賴問題還是存在。

這個問題的主要原因確實是SpringBoot版本過高導致。如果你用的是SpringBoot2.5.x及之前版本是沒有問題的。

Spring Boot 2.6.X使用PathPatternMatcher匹配路徑,Swagger參照的Springfox使用的路徑匹配是基於AntPathMatcher的。

所以要想解決,新增設定,將springBoot MVC的路勁匹配模式修改一下即可。

在springBoot組態檔中新增設定:

spring.mvc.pathmatch.matching-strategy=ANT_PATH_MATCHER

如果是yml格式的組態檔:

再次啟動問題解決。

存取地址: ip:埠號/swagger-ui.html

正常情況就可以看到我們的介面了。一會再說非正常情況。由於我們只給使用者介面新增了註解,所有使用者介面是可以直接觀察中文檔案的。而剩下的兩個介面,由於沒新增註解,所以都是以預設的形式展示的。

點開介面,我們可以看到介面中的想詳細資訊

點選model,可以看到欄位的中文描述。點選 Try it out,就可以直接偵錯介面。同時注意介面中都讓填一個token,這就是我們之前的設定成效了。

截止到目前其實swagger的整合就已經完畢了,主要就是根據我們的註解生成檔案,並且可以線上呼叫偵錯。開發的時候,我們只需要把Controller這一層的請求和響應,以及方法描述等內容先開發完畢,就可以提供給前端讓他們參照開發了。

2.4 [404]問題解決

正常情況我們按照上面的步驟就可以出現頁面,但是有些時候可能是由於springBoot的版本過高導致的,我們輸入之前的地址,出現404的情況,這個主要是由於專案中無法讀取到swagger依賴包下的頁面導致的。如果出現了這個問題,我們可以新增一個設定類,讓他實現WebMvcConfigurer 介面,在新增一個方法:

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
    registry.addResourceHandler("swagger-ui.html")
            .addResourceLocations("classpath:/META-INF/resources/");
    registry.addResourceHandler("/webjars/**")
            .addResourceLocations("classpath:/META-INF/resources/webjars/");
}

完整程式碼如下:

package com.lsqingfeng.springboot.config;

import com.lsqingfeng.springboot.interceptor.TokenInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @className: WebMvcConfig
 * @description:webMvc設定
 * @author: sh.Liu
 * @date: 2022-01-13 09:51
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {


    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
        registry.addResourceHandler("swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
    }
}

這個時候在啟動就可以了!

2.5 替換UI

上面的整個過程已經完成了,但是生成的介面檔案的頁面,其實很多人不太喜歡,覺得不太符合國人的使用習慣,所有又有一些大神,提供了其他的UI測試頁面。這個頁面的使用還是比較廣泛的。

修改方式:只需引入一個依賴包:

<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>swagger-bootstrap-ui</artifactId>
    <version>1.9.6</version>
</dependency>

然後把剛才實現的那個的那個方法再新增一條:

registry.addResourceHandler("doc.html")
                .addResourceLocations("classpath:/META-INF/resources/");

完成程式碼:

package com.lsqingfeng.springboot.config;

import com.lsqingfeng.springboot.interceptor.TokenInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @className: WebMvcConfig
 * @description:webMvc設定
 * @author: sh.Liu
 * @date: 2022-01-13 09:51
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

//    @Override
//    public void addInterceptors(InterceptorRegistry registry) {
//        //攔截
//        registry.addInterceptor(new TokenInterceptor())
//                .addPathPatterns("/**")
//                .excludePathPatterns("/login");
//    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
        registry.addResourceHandler("swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
        registry.addResourceHandler("doc.html")
                .addResourceLocations("classpath:/META-INF/resources/");
    }
}

重新啟動專案: 存取路徑發生了變化:** ip:埠號/doc.html**

頁面出現了。我們在看看我們的使用者介面:

這個風格確實更加的直觀,同時也是可以直接進行偵錯的。大部分的swagger都用的這個風格的檔案。

三. SpringBoot整合swagger3

上面已經很詳細的講解了swagger2的整合方式,而swagger3的整合方式更加的簡潔一些。

首先引入依賴:

<dependency>
  <groupId>io.springfox</groupId>
  <artifactId>springfox-boot-starter</artifactId>
  <version>3.0.0</version>
</dependency>

然後是替換註解: swagger2使用的開啟註解是: @EnableSwagger2

而在swagger3中,這個註解要換成: @EnableOpenApi

設定類:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;

@Configuration
public class SwaggerConfig {
    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.OAS_30) // v2 不同
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.example.swaggerv3.controller")) // 設定掃描路徑
                .build();
    }
}

要注意,裡邊的版本型別換成了 OAS_30, 就是swagger3的意思。

OAS 是 OpenAPI Specification 的簡稱,翻譯成中文就是 OpenAPI 說明書。

同時存取地址:原始地址,也就是沒換UI的地址: localhost:8080/swagger-ui/index.html這個要和swagger2區分開。

swagger3的原始UI風格也發生了一些變化:

同時swagger3也是可以更換UI的。方法和swagger2一樣。

四. swaggerUI 攔截器和跨域衝突處理

如果我們的專案中有關於跨域的處理,同時還有攔截器,然後還要使用swagger,這種情況大家要注意了,有可能我們的攔截器會將swagger中的頁面路徑攔截掉導致swagger頁面出不來,當我們在攔截器中把swagger的頁面排除掉的時候,也有可能會導致跨域設定的失效。

詳細的解決方案可以看我之前寫過的一篇部落格: lsqingfeng.blog.csdn.net/article/det…

具體解決方案簡單提一下:

攔截器:

/**
 * 攔截器設定
 *
 * @author liuShuai
 */
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
 
    @Bean
    public TokenInterceptor tokenInterceptor() {
        return new TokenInterceptor();
    }
 
 
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry
                .addInterceptor(tokenInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns("/user/login")
                .excludePathPatterns("/user/downloadExcel")
                .excludePathPatterns("/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**");
    }
 
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
    }
}

跨域設定:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
 
/**
 * @className: CorsConfig
 * @description:
 * @author: sh.Liu
 * @date: 2020-12-02 10:16
 */
@Configuration
public class CorsConfig {
 
    @Bean
    public CorsFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedOrigin("*");
        config.setAllowCredentials(true);
        config.addAllowedMethod("*");
        config.addAllowedHeader("*");
        UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
        configSource.registerCorsConfiguration("/**", config);
        return new CorsFilter(configSource);
    }
}

用這兩種方式去設定,就可以讓他們和平共處了。

另: 配套專案程式碼已託管中gitCode: gitcode.net/lsqingfeng/…

分支: feautre/MybatisPlus

所有文章也會在微信公眾號首發更新,歡迎關注:

五. 寫在最後

截止到本篇文章,關於SpringBoot的系列學習筆記已經更新了十六篇,也基本上要和大家說再見了。感謝大家的一路支援。這十六篇文章主要面向SpringBoot的實戰性學習上,基本很少會介紹一些原理性的概念。也已經整合目前大部分主流的框架和中介軟體。如果大家對於Spring中一些生命週期,初始化過程,類載入原理和常用註解不太瞭解(因為這一個部分很少介紹),建議大家結合我之前寫的Spring5系列教學一起學習,裡邊介紹了Spring IOC和AOP的核心概念。

這個系列的教學就更新到這裡了,後面可能就不會在繼續更新這個系列了。下個目標,我可能準備寫一個SpringCloud的系列教學,主要針對alibaba版本中的一些元件用法。但是由於最近公司比較忙,可能更新的會比較慢。希望大家多多支援。

到此這篇關於全網最全SpringBoot整合swagger的詳細教學的文章就介紹到這了,更多相關SpringBoot整合swagger內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com