前後端分離必備工具:SpringBoot整合Swagger超詳細教學

2020-10-27 12:00:51

1. 新建springboot專案

首先新建一個spirngboot專案,勾選元件時勾選Spring-Web



2. 匯入Swagger依賴

springfox-swagger2

<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>3.0.0</version>
</dependency>

springfox-swagger-ui

<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>3.0.0</version>
</dependency>


3. 編寫HelloController測試

我們編寫一個controller來測試一下專案是否搭建成功,在主程式同級目錄下新建controller包,其中新建HelloController

package com.zsr.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

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

然後啟動主程式,存取localhost:8080/hello,出現如下結果即成功
image-20201023183014921



4. 編寫Swagger設定類

在主程式同級目錄下新建config包,其中新建SwaggerConfig設定類

  • 記住用@Configuration註解註明這是設定類
  • 同時用@EnableSwagger2註解開啟Swagger2
package com.zsr.config;

import org.springframework.context.annotation.Configuration;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2//開啟Swagger2
public class SwaggerConfig {

}


5. 測試進入Sawgger頁面

重新啟動主程式,存取localhost:8080/swagger-ui.html

啟動報錯:@EnableSwagger2註解找不到,但是已經匯入了對應的jar包

image-20201023185624449
這時候降級為2.9.2即可使用

<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
</dependency>

<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.9.2</version>
</dependency>

再次啟動主程式即可成功,然後存取localhost:8080/swagger-ui.html,即可進入到以下介面
image-20201023205134046
這個介面是Swagger為我們提供的ui介面,我們可以在原始碼中找到它
image-20201023212945475



6. 設定Swagger API資訊

image-20201025220813224

在Swagger提供的ui介面,其中的Swagger資訊模組我們可以自定義資訊內容

我們只需要在Swagger設定類SwaggerConfig中範例化Docket類隊物件的bean範例,通過設定ApiInfo類的資訊然後傳入Docket的bean範例即可

image-20201023212301978

package com.zsr.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.service.VendorExtension;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.ArrayList;

@Configuration
@EnableSwagger2//開啟Swagger2
public class SwaggerConfig {
    //設定Swagger的Docket的bean範例
    @Bean
    public Docket docket() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo());//設定Swagger資訊
    }

    //設定Swagger資訊
    private ApiInfo apiInfo() {
        return new ApiInfo(
                "Baret-H",
                "我的Swagger API檔案",
                "1.0",
                "https://bareth.blog.csdn.net/",
                new Contact("Baret-H", "https://bareth.blog.csdn.net/", "1412578784@qq.com"),//作者資訊
                "Apache 2.0",
                "http://www.apache.org/licenses/LICENSE-2.0",
                new ArrayList<VendorExtension>());
    }
}

重新啟動主程式測試,可以看到Swagger資訊已經變更成我們定義的資訊
image-20201023212154292



7. 設定Swagger自定義掃描介面

我們在這個ui介面中,可以看到掃描了兩個controller介面

image-20201023213154765

  • 一個是預設的/error請求,也就是我們啟動springboot主程式未加設定預設存取8080埠的預設controller
    image-20201023213519690

  • 另一個是我們自己寫的/hello請求,對應著HelloController,由於我們用的@RequsetMapping註解,所以請求的方式有以上的六種

接下來我們自己設定以下要掃描的介面

@Bean
public Docket docket() {
    return new Docket(DocumentationType.SWAGGER_2)
            .apiInfo(apiInfo())//設定Swagger資訊
            .select()
            /**
             * apis():指定掃描的介面
             *  RequestHandlerSelectors:設定要掃描介面的方式
             *       basePackage:指定要掃描的包
             *       any:掃面全部
             *       none:不掃描
             *       withClassAnnotation:掃描類上的註解(引數是類上註解的class物件)
             *       withMethodAnnotation:掃描方法上的註解(引數是方法上的註解的class物件)
             */
            .apis(RequestHandlerSelectors.basePackage("com.zsr.controller"))
            /**
             * paths():過濾路徑
             *  PathSelectors:設定過濾的路徑
             *      any:過濾全部路徑
             *      none:不過濾路徑
             *      ant:過濾指定路徑:按照按照Spring的AntPathMatcher提供的match方法進行匹配
             *      regex:過濾指定路徑:按照String的matches方法進行匹配
             */
            .paths(PathSelectors.ant("/zsr/**"))
            .build();
}

其中.select().apis.paths.build是一套組合進行使用

然後我們啟動主程式存取localhost:8080/swagger-ui.html進行測試
image-20201025160758501
可以發現No opertations defined in spec,這是因為我們過濾了/zsr下的所有controller

我們將過濾條件更改為過濾全部路徑

.paths(PathSelectors.any)

再次啟動主程式存取localhost:8080/swagger-ui.html
image-20201025161212037
可以看到只顯示了我們上述自定義的com.zsr.controller下的介面HelloController

.apis(RequestHandlerSelectors.basePackage("com.zsr.controller"))


8. 設定是否啟動Swagger

我麼通過Docket物件的.enable方法來設定swagger是否啟動

@Bean
public Docket docket() {
    return new Docket(DocumentationType.SWAGGER_2)
            .apiInfo(apiInfo())//設定Swagger資訊
            .enable(false)//設定是否啟動swagger,預設為true
            .select()
            .apis(RequestHandlerSelectors.basePackage("com.zsr.controller"))
            .paths(PathSelectors.ant("/zsr/**"))
            .build();
}

更改為false後啟動測試一下,檢視控制檯,無法進入到swagger頁面
image-20201023220447602

如果我們有這樣一個需求:希望Swagger在開發環境中,在正式環境時不能使用

  • 首先要判斷是不是開發環境,可以設定一個flag表示用來表示:flag=1即表示生產環境
  • 然後將flag的值傳給enable(flag)

首先在resources目錄下新建兩種springboot組態檔:

  • 開發環境:application-dev.properties

    server.port=8081
    
  • 正式環境:application-pro.properties

    server.port=8082
    
    image-20201023233834369

然後在主組態檔application.properties中啟用開發環境

spring.profiles.active=dev

然後我們到SwaggerConfig中的docket()方法中新增程式碼:

  • 首先給該方法傳一個引數Environment的範例

    Environment environment
    
  • 首先設定藥設定的Swagger環境:這裡可以新增多個環境

    Profiles profiles = Profiles.of("dev", "test");
    
  • 然後通過environment.acceptsProfiles方法判斷是否處在上一步設定的dev/test環境中,返回一個boolean的值,我們用flag接收

    boolean flag = environment.acceptsProfiles(profiles);
    
  • 然後修改enable中的引數為flag,即通過flag來判斷是否開啟Swagger

    .enable(flag)//通過flag判斷是否開啟
    

完整程式碼

@Configuration
@EnableSwagger2//開啟Swagger2
public class SwaggerConfig {
    //設定Swagger的Docket的bean範例
    @Bean
    public Docket docket(Environment environment) {
        //設定要設定的Swagger環境
        Profiles profiles = Profiles.of("dev", "test");
        //通過environment.acceptsProfiles判斷是否處在自己設定的環境中
        boolean flag = environment.acceptsProfiles(profiles);

        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())//設定Swagger資訊
                .enable(flag)//通過flag判斷是否開啟
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.zsr.controller"))
                .paths(PathSelectors.ant("/zsr/**"))
                .build();
    }

    //設定Swagger資訊
    private ApiInfo apiInfo() {
        return new ApiInfo(
                "Baret-H",
                "我的Swagger API檔案",
                "1.0",
                "https://bareth.blog.csdn.net/",
                new Contact("Baret-H", "https://bareth.blog.csdn.net/", "1412578784@qq.com"),//作者資訊
                "Apache 2.0",
                "http://www.apache.org/licenses/LICENSE-2.0",
                new ArrayList<VendorExtension>());
    }
}

然後啟動主程式測試:由於啟用了dev開發環境,所以存取localhost:8081/swagger-ui.html
image-20201025155757821
成功開啟swagger,如果我們修改主組態檔,啟用pro正式釋出環境

spring.profiles.active=pro

再次重新啟動主程式測試,存取埠8082對應的地址localhost:8082/swagger-ui.html
image-20201025155948810
無法進入,因為pro環境不在我們設定的test/dev環境中,所以無法開啟



9. 設定API檔案分組

1. 設定預設組名

可以看到,我們預設只有一個組且組名為default
image-20201025163547341

我們可以在docket通過.groupName中設定組名

public Docket docket(Environment environment) {
    //設定要設定的Swagger環境
    Profiles profiles = Profiles.of("dev", "test");
    //通過environment.acceptsProfiles判斷是否處在自己設定的環境中
    boolean flag = environment.acceptsProfiles(profiles);

    return new Docket(DocumentationType.SWAGGER_2)
            .apiInfo(apiInfo())//設定Swagger資訊
            .groupName("zsr")
            .enable(true)//設定是否啟動swagger,預設為true
            .select()
            .apis(RequestHandlerSelectors.basePackage("com.zsr.controller"))
            .paths(PathSelectors.any())
            .build();
}

重新啟動測試,可以看到組名更改為zsr
image-20201025163953771


2. 設定多個組

上述我們成功修改了組名,但是隻有一個組,如果我們想要多個組呢?

觀察程式碼可以知道,一個Docket範例就對應著一個組,因此我們設定多個docket就對應著多個組

我們新增兩個Docket的bean範例

@Bean
public Docket docket1() {
    return new Docket(DocumentationType.SWAGGER_2).groupName("Baret-H");
}

@Bean
public Docket docket2() {
    return new Docket(DocumentationType.SWAGGER_2).groupName("鍾");
}

再次重新啟動測試,就可以看到多個組並選擇

image-20201025164947559



10. 設定Model實體類

1. 新建實體類

在主程式同級目錄下新建pojo包,其中新建User實體類

package com.zsr.pojo;

public class User {
    public String username;
    public String password;
}

2. 編寫對應請求介面

編寫完實體類,我們在model中還是看不到的,我們還需在HelloController中新增一個方法返回實體類的範例物件即可對映到實體項中

@GetMapping("/getUser")
public User getUser() {
    return new User();
}

3. 啟動測試

成功顯示實體類User

image-20201025172330524

4. 常用註解

我們可以在實體類上和其屬性上新增註解來新增對應的註釋

  • @ApiModel為類新增註釋

  • @ApiModelProperty為類屬性新增註釋

package com.zsr.pojo;

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

@ApiModel("使用者實體")
public class User {
    @ApiModelProperty("使用者名稱")
    public String username;
    @ApiModelProperty("密碼")
    public String password;
}

重新啟動測試,即可以看到註釋資訊
image-20201025173636862

我們同樣可以在Controller類和其中的方法上新增相應的註解

@Api(tags = "Hello控制類")
@RestController
public class HelloController {
    @RequestMapping("/hello")
    public String hello() {
        return "hello";
    }

    @ApiOperation("hello控制類")
    @GetMapping("/getUser")
    public User getUser() {
        return new User();
    }
}

重新啟動即可看到對應的註解
image-20201025175251278



11. 測試Swagger的使用

1. 測試傳參

我們在HelloController中新增一個方法,引數為username,可以用@ApiParam給該引數新增註解

@GetMapping("/username")
public String getUserName(@ApiParam("使用者名稱") String username) {
    return username;
}

重新啟動測試,可以看到我們新增的註釋
image-20201025180318626
我們可以簡單測試一下,點選Try it out;然後以json的格式輸入使用者名稱,然後點選Execute執行
image-20201025211728843
可以看到報錯了,這是因為我們是使用的是Get方式:是通過URL的方式傳遞的,而不是通過請求體單獨傳參
image-20201025211838700

我們將程式碼修改一下,將GetMapping改為PostMapping

@PostMapping("/username")
public String getUserName(@ApiParam("使用者名稱") String username) {
    return username;
}

image-20201025212320277
再次以json的格式輸入引數username,可以看到成功了
image-20201025212422153

2. 測試錯誤

我們在HelloController中新增一個方法,引數為User,可以用@ApiParam給該引數新增註解

然後執行測試
image-20201025214501614
找到對應的controller,點選Try it out測試,輸入使用者名稱和密碼然後點選Excute
image-20201025214626100
可以看到我們請求的URL完全正確,但是Response body相應體中使用者名稱和密碼都為空,這是因為我們的實體類沒有新增對應的GET和SET方法,我們新增上去

package com.zsr.pojo;

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

@ApiModel("使用者實體")
public class User {
    @ApiModelProperty("使用者名稱")
    public String username;
    @ApiModelProperty("密碼")
    public String password;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

再次啟動測試,成功!
image-20201025215501706
如果我們修改一下程式碼

@PostMapping("/post")
private User postUser(User user) {
    int i = 100 / 0;
    return user;
}

此時測試肯定會報錯,我們測試看看,可以看到500錯誤
image-20201025215801946
由此可見,swagger可以讓我們很容易的進行前後端的互動測試