SpringBoot3整合SpringDoc實現線上介面文件

xiezhr發表於2024-06-17

寫在前面

在現目前專案開發中,一般都是前後端分離專案。前端小姐姐負責開發前端,苦逼的我們負責後端開發

事實是一個人全乾,在這過程中編寫介面文件就顯得尤為重要了。然而作為一個程式設計師,最怕的莫過於自己寫文件和別人不寫文件

大家都不想寫文件,那這活就交給今天的主角Swagger來實現了

一、專業名詞介紹

OpenApi是什麼?

解答:OpenApi是一個用於描述、定義和共享 RESTful API 文件的規範。最新規範是 OpenAPI 3.0

Swagger是什麼?

解答: Swagger 是一個用於設計和測試 RESTful APIs 的工具。

它提供了API 描述、請求和響應示例、API 測試和文件生成等豐富的功能。最新版本是Swagger3,支援OpenAPI3.0規範

SpringFox 是什麼?

SpringFox 是 Spring 社群維護的一個專案(非官方),幫助使用者將 Swagger 2 整合到 Spring 中。

目前國內專案使用的都是它

github地址:https://github.com/springfox/springfox

springDoc是什麼?

解答: Spring-doc也是 Spring 社群維護的一個專案(非官方),幫助使用者將 Swagger 3 整合到 Spring 中

SpringDoc 支援 Swagger 頁面 Oauth2 登入,相較於 SpringFox 而言,它的支撐時間更長,無疑是更好的選擇

但是在國內發展較慢,網上一找資料,出來的基本上是 Swagger2的內容。

地址:https://springdoc.org/

OpenAPISpring-docSwagger 之間的關係

解答:OpenAPI 定義了一種標準的格式來表示 API 文件,而 Swagger 是一個實現 OpenAPI 規範的工具

二、Swagger詳細簡介

Swagger 江湖人稱“絲襪哥”,是一個幫助程式設計師生成介面文件的利器。

只需要簡單配置,就可以生成帶有漂亮UI介面的介面文件,而且編寫的介面程式碼變了

介面文件隨之也跟著變,做到了真正的解放雙手。

官網https://swagger.io/

Swagger 優點

  • 號稱世界上最流行的API框架
  • Restful Api 文件線上自動生成器
  • 直接執行,支援線上測試API
  • 不僅僅支援Java,還支援多種語言(如:PHPPythonNode.js等)

三、小試牛刀

說了這麼多Swagger 的優點,接下來就小試牛刀,看看怎麼將Swagger整合到SpringBoot中。

3.1、環境介紹

  • JDK:17
  • SpringBoot:3.3.0
  • Springdoc

注: 細心的小夥伴可能已經發現了,在springboot3.0之前我用的都是Springfox來整合Swagger管理我們的API介面文件,

但是Springfox已經停止更新了,我們使用的是SpringBoot3 +jdk17 的環境後,Spring官網推薦了Springdoc 來整合swagger

3.2 新建一個springboot-web專案

3.3 新增依賴

由於篇幅原因,其他web專案相關依賴這裡就不一一貼出來了。

第一個依賴是必須的,而且版本必須大於2.0.0

<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
    <version>2.2.0</version>
</dependency>
<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-starter-webmvc-api</artifactId>
    <version>2.2.0</version>
</dependency>

注:

我們這裡使用的是jdk17+springboot3.3.0 環境,原來swaggerV2V3都不能用了,小夥伴們一定更要注意這兒

不能引入的依賴

如果引入上面錯誤的依賴,專案啟動會報下面錯誤,這時候我們引入上面正確的依賴重新啟動專案即可

報錯資訊

3.4 編寫HelloController

新建一個controller包--->建立一個HelloController

新建Hellocontroller

@RestController
public class HelloController {

    @RequestMapping("/hello")
    public String hello(){
        return "hello";
    }
}

我們在瀏覽器中輸入“http://localhost:8080/hello” 後回車,出現如下介面,說明我們的hello開發成功了

hello介面正常訪問

3.5 訪問swagger介面頁面

:我們這裡採用的是openapi ,所以就不用像swaggerV2v3那樣新增配置類了

瀏覽器直接輸入:http://localhost:8080/swagger-ui/index.html 回車即可看到下面介面

介面資訊

整合swagger是不是很簡單呢

四、修改介面

多種請求方式

從上面截圖中我們看到,我們在HelloController 中只定義了一個介面,但是前端UI介面中出來個7種請求方式(GETPUTPOSTDELETEOPTIONSHEADPATCH)的介面,這是為什麼呢?

解答:@RequestMapping("/hello") 我們介面中只是指定了訪問地址,並沒有指定請求方式

我們將註解修改成@RequestMapping(path = "/hello",method = RequestMethod.GET)

或者@GetMapping("/hello") 然後重啟服務,我們看到介面上就只有一種請求方式的介面了

get請求方式

五、介面文件常用配置

5.1 配置訪問路徑

application.yml中可以自定義api-docsswagger-ui的訪問路徑。當然了,如果沒配置,預設就是下面路徑

springdoc:
  api-docs:
    path: /v3/api-docs
  swagger-ui:
    path: /swagger-ui.html

5.2 配置介面文件基本資訊

① 配置介面基本資訊

新建一個config包--->並在包下建立一個SpringDocConfig配置類

新建配置類

② 配置介面文件基礎資訊

我們在配置類中新增如下程式碼,

@Configuration
public class SpringDocConfig {

    @Bean
    public OpenAPI openAPI() {
        return new OpenAPI()
                // 配置介面文件基本資訊
                .info(this.getApiInfo())
                ;
    }

    private Info getApiInfo() {
        return new Info()
                 // 配置文件標題
                .title("SpringBoot3整合Swagger3")
                // 配置文件描述
                .description("SpringBoot3整合Swagger3示例文件")
                // 配置作者資訊
                .contact(new Contact().name("程式設計師小凡").url("https://www.xiezhrspace.cn").email("1666397814@163.com"))
                // 配置License許可證資訊
                .license(new License().name("Apache 2.0").url("https://www.xiezhrspace.cn"))
                // 概述資訊
                .summary("SpringBoot3整合Swagger3示例文件aaa")
                .termsOfService("https://www.xiezhrspace.cn")
                // 配置版本號
                .version("2.0");
    }

}

前端頁面訪問介面文件頁面後顯示如下

介面基本資訊

② 配置介面servers資訊

介面可能存在多環境,如開發環境、測試環境、生產環境等

我們可以透過@OpenAPIDefinition 配合servers 屬性來配置不同環境,具體配置示例如下

@OpenAPIDefinition(
        servers = {
                @Server(description = "開發環境伺服器", url = "http://localhost:8080"),
                @Server(description = "測試環境伺服器", url = "https://test.xiezhr.com")
        }
)
@Configuration
public class SpringDocConfig {
    //...
}

配置完成後,瀏覽器訪問顯示如下

配置servers資訊

③ 配置外部文件資訊

有時候我們需要在線上介面文件中可以顯示跳轉到API的一些外部文件(比如 專案部署文件等)

這個時候我們可以透過@OpenAPIDefinition 配合 externalDocs 屬性來配置外部文件

具體配置如下

@OpenAPIDefinition(

    externalDocs = @ExternalDocumentation(
        description = "專案編譯部署說明",
        url = "http://localhost:8080/deplay/readme.md"
    )
)
@Configuration
public class SpringDocConfig {
    //......
}

配置完後重啟服務,瀏覽器訪問介面文件,顯示如下

外部API文件

SpringDocConfig 類完整配置程式碼如下

@OpenAPIDefinition(

        servers = {
                @Server(description = "開發環境伺服器", url = "http://localhost:8080"),
                @Server(description = "測試環境伺服器", url = "https://test.xiezhr.com")
        },
        externalDocs = @ExternalDocumentation(
                description = "專案編譯部署說明",
                url = "http://localhost:8080/deplay/readme.md"
        )
)

@Configuration
public class SpringDocConfig {

    @Bean
    public OpenAPI openAPI() {
        return new OpenAPI()
                // 配置介面文件基本資訊
                .info(this.getApiInfo())
                ;
    }

    private Info getApiInfo() {
        return new Info()
                 // 配置文件標題
                .title("SpringBoot3整合Swagger3")
                // 配置文件描述
                .description("SpringBoot3整合Swagger3示例文件")
                // 配置作者資訊
                .contact(new Contact().name("程式設計師小凡").url("https://www.xiezhrspace.cn").email("1666397814@163.com"))
                // 配置License許可證資訊
                .license(new License().name("Apache 2.0").url("https://www.xiezhrspace.cn"))
                //
                .summary("SpringBoot3整合Swagger3示例文件aaa")
                .termsOfService("https://www.xiezhrspace.cn")

                // 配置版本號
                .version("2.0");
    }

  

}

配置完上面資訊後,重啟服務,瀏覽器訪問:http://localhost:8080/v3/swagger-ui/index.html

介面文件基本資訊

5.3 配置掃描介面

應用場景:

有時候我們為了業務需要,我們建立了多個包下的介面,如admin包下的,common包下的介面,

為了安全起見,我們只允許介面文件中訪問comm包下面的介面。

在不加任何配置的情況下,所以介面都會預設顯示,具體如下

顯示所有介面

配置掃描介面包:

application.yml中可以自定義要掃描的介面包

springdoc:
  packages-to-scan: com.xiezhr.swaggerdemo.common.controller

配置好之後重啟服務,我們發現前臺UI只顯示了common包下面的介面了

只顯示common包下面的介面

5.4 配置介面文件開關

使用場景:

為了介面安全,我們一般需要在測試(test)環境或者開發(dev)環境中開啟介面文件,而在生產(prod)環境中 關閉介面文件

這個應該怎麼做呢?

這裡涉及到SpringBoot多環境配置,忘記的小夥伴可以翻一翻之前的文章。傳送門:

我們建立三個配置檔案,分別為

  • application-dev.yml 開發環境

  • application-test.yml 測試環境

  • application-prod.yml 生產環境

只需在①和②配置檔案中新增如下配置

springdoc:
  api-docs:
    enabled: true

而③配置檔案中新增

springdoc:
  api-docs:
    enabled: false

透過上面配置後,我們在開發和測試環境下:就能正常訪問http://localhost:8080/v3/swagger-ui/index.html#/

而在生產環境下就無法訪問,報如下錯誤

生產環境

5.5 配置API分組

為了演示API分組,我們在controller包下面再建立admin包和common包,包下分別新增AdminControllerCommonController介面類,結構及程式碼如下

包結構

AdminController

// AdminController
@RestController
@RequestMapping("/admin")
public class AdminController {

    @GetMapping("/index")
    public String  admin(){
        return "admin";
    }
}

CommonController

@RestController
@RequestMapping("/common")
public class CommonController {

   @GetMapping("/hello")
    public String hello(){
        return "hello";
    }
}

在預設情況(沒有分組)的情況下,所有包下介面都顯示在一一個預設組下面,如/common/* 和/admin/* 訪問路徑下的介面都顯示在一起,如下圖所示

預設分組

這時,如果/common/* 下的介面比較多,/admin/* 下的介面也比較多,介面上顯示就很混亂

解決辦法就是新增分組資訊,我們在SpringDocConfig 配置類中新增如下程式碼,這樣就把介面分為了"common通用模組組" 和"admin模組組" 兩個組

@Bean("commonGroupApi")
public GroupedOpenApi webGroupApi() {
    return GroupedOpenApi.builder().group("common通用模組組")
        .pathsToMatch("/common/**")
        .build();
}

@Bean("adminGroupApi")
public GroupedOpenApi adminGroupApi() {
    return GroupedOpenApi.builder().group("admin模組組")
        .pathsToMatch("/admin/**")
        .build();
}

重啟服務,再訪問http://localhost:8080/v3/swagger-ui/index.html 如下

API分組

5.6 配置介面資訊

@Tag 註解使用

對一個 operation 進行說明或定義的標籤,用在類或方法上,也可以用在 @OpenAPIDefinition 中定義標籤。

常用引數:

  • name: 名稱
  • description: 介面描述資訊

示例:

用在類上

@RestController
@RequestMapping("/common")
@Tag(name = "公共介面", description = "公共介面")
public class CommonController {
    //......
}

@Operation 註解使用

用於說明方法用途,用在方法上。

引數:

  • summary:方法概要,方法的一個簡單介紹,建議 120 個字元內
  • description:方法描述,一般是很長的內容
  • hidden:是否隱藏

示例:

@GetMapping("/hello")
@Operation(summary = "hello介面", description = "hello介面描述" ,hidden = true)
public String hello(){
    return "hello";
}

@Parameter註解使用

用於說明方法引數,用在方法引數上。

引數:

  • name:指定的引數名
  • in:引數位置,可選 queryheaderpathcookie,預設為空,表示忽略
  • description:引數描述
  • required:是否必填,預設為 false

示例:

@GetMapping("/user/{id}")
public User getUser( @Parameter(name = "id",in = ParameterIn.PATH,description = "使用者ID",required = true) @PathVariable("id") Integer id){
    User user = userService.getUserById(id);
    return user;
}

前端頁面檢視

@Paramter註解配置資訊

@ApiResponse 註解使用

用於說明一個響應資訊,用在 @ApiResponses 中。

引數:

  • responseCode:HTTP 響應碼
  • description:描述

示例:

@GetMapping("/user/{id}")
@Operation(summary = "獲取使用者資訊", description = "根據使用者ID獲取使用者資訊")
@ApiResponses(value ={
    @ApiResponse(responseCode = "200", description = "請求成功"),
    @ApiResponse(responseCode = "404", description = "使用者不存在")            
})
public User getUser( @Parameter(name = "id",in = ParameterIn.PATH,description = "使用者ID",required = true) @PathVariable("id") Integer id){
    User user = userService.getUserById(id);
    return user;
}

@ApiResponse註解配置資訊

完整配置

@RestController
@RequestMapping("/common")
@Tag(name = "公共介面", description = "公共介面")
public class CommonController {

    @Autowired
    private IUserService userService;

   @GetMapping("/hello")
   @Operation(summary = "hello介面", description = "hello介面描述" ,hidden = true)
    public String hello(){
        return "hello";
    }

    @GetMapping("/hi")

    @Operation(summary = "hi介面", description = "hi介面描述")
    public String Hi(){
        return "Hi 程式設計師小凡";
    }

    @GetMapping("/user/{id}")
    @Operation(summary = "獲取使用者資訊", description = "根據使用者ID獲取使用者資訊")
    @ApiResponses(value ={
            @ApiResponse(responseCode = "200", description = "請求成功"),
            @ApiResponse(responseCode = "404", description = "使用者不存在")
    })
    public User getUser( @Parameter(name = "id",in = ParameterIn.PATH,description = "使用者ID",required = true) @PathVariable("id") Integer id){
        User user = userService.getUserById(id);
        return user;
    }
}

重啟後,瀏覽器訪問http://localhost:8080/v3/swagger-ui/index.html 如下

image-20240615213336423

5.7 配置實體資訊

① 新建一個User實體類

@Data
public class User {
    private String name;
    private Integer age;
    private String email;
    private String address;
}

@Schema標籤使用

用於描述資料物件資訊或資料物件屬性,比如各種POJO類及屬性,用在類或類屬性上。

引數:

  • name:屬性名稱
  • description:屬性描述
  • required:是否必須
  • minLength:字元最小長度
  • maxLength:字元最大長度

③使用示例:

@Data
@Schema(description = "使用者實體類",name = "User")
public class User {
    @Schema(description = "使用者名稱",name =  "name",minLength =  6,maxLength = 20,required = true)
    private String name;
    @Schema(description = "年齡",name =  "age",required = true,minimum = "1",maximum = "100")
    private Integer age;
    @Schema(description = "郵箱",name =  "email",required = true)
    private String email;
    @Schema(description = "地址",name =  "address")
    private String address;
}

④ 瀏覽器訪問:http://localhost:8080/v3/swagger-ui/index.html ,我們看到配置的實體資訊顯示出來了

實體資訊

六、介面除錯

透過上面各種配置之後,我們的線上介面文件基本上生成得差不多了。接下來我們就來說說怎麼使用線上介面文件進行介面測試

① 測試說明

在之前小節中我們開發了要給根據使用者ID 獲取使用者資訊的介面getUser。我們現在要做的就是在前端UI介面中找到這個介面,

在開發環境下輸入使用者ID值,然後獲取使用者資訊。

② 選擇組資訊

【獲取使用者資訊】這個介面在,common通用模組組下面,所以我們第一步就要前端UI介面右上角選擇這個組

選擇common通用模組組

② 選擇開發環境

Servers 下選擇配置好的開發環境

選擇開發環境

找到我們要測試的介面

找到目標介面

④ 測試介面,獲取響應資料

介面右邊下三角箭頭展開介面------>點選Try it out

點選Try it out

輸入引數:使用者ID------> 點選【Execute】----->在Response body 中檢視介面響應資訊

根據使用者id獲取到響應資訊

七、新增請求頭

很多時候我們介面都需要認證之後才能訪問,這時候我們就需要介面呼叫的時候攜帶著Token資訊

示例:

我們透過@RequestHeader 註解 獲取請求頭中token資訊

@GetMapping("/index")
public String  admin(@RequestHeader ("token") String token){
	System.out.println("token>>>>>>>>>>>>>>>>>>>>>>>>"+token);
    //token 驗證
    //.....各種業務邏輯
    return "admin";
}

新增請求頭資訊

到此,本期內容就結束了,★,°:.☆( ̄▽ ̄)/$:.°★ 。 希望對您有所幫助

我們下期再見 ヾ(•ω•`)o (●'◡'●)

相關文章