Swagger 教程

   轉自   Vojtech Ruzicka的編程博客html

 

(一)Swagger和SpringFox前端

   記錄REST API很是重要。它是一個公共接口,其餘模塊,應用程序或開發人員可使用它。即便你沒有公開曝光它,它仍然很重要。後端和前端代碼一般由不一樣的開發人員處理。建立API的人一般不是消費它的人。所以,擁有適當記錄的界面以免混淆並使其始終保持最新是相當重要的。git

最受歡迎的API文檔規範之一是OpenApi,之前稱爲Swagger。它容許您使用JSON或YAML元數據描述API的屬性。它還提供了一個Web UI,它能夠將元數據轉換爲一個很好的HTML文檔。此外,經過該UI,您不只能夠瀏覽有關API端點的信息,還能夠將UI用做REST客戶端 - 您能夠調用任何端點,指定要發送的數據並檢查響應。它很是方便。github

然而,手動編寫此類文檔並在代碼更改時保持更新是不現實的。這就是SpringFox發揮做用的地方。它是Spring Framework的Swagger集成。它能夠自動檢查您的類,檢測控制器,它們的方法,它們使用的模型類以及它們映射到的URL。沒有任何手寫文檔,只需檢查應用程序中的類,它就能夠生成大量有關API的信息。多麼酷啊?最重要的是,每當您進行更改時,它們都會反映在文檔中。正則表達式

 

(二)開始項目spring

首先,你須要一個帶有一些Rest Controller的Spring Boot應用程序,我在這裏準備了一個簡單的。apache

在本文中,我使用了SpringFox 2.9.2和Spring Boot 1.5.10.RELEASE。它使用Swagger規範的第2版。版本3已經發布,但還沒有(截至2014年2月)SpringFox支持。支持應在下一版本中提供編程

使用本博文中描述的全部功能構建的最終項目的源代碼可在GitHub上得到json

 

(三)添加依賴項後端

      要在項目中使用SpringFox,您須要先將其添加爲依賴項。若是您使用的是Maven,則可使用如下內容(您能夠檢查是否有更新的版本)。

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

或者若是您使用的是Gradle:

compile "io.springfox:springfox-swagger2:2.9.2"

 

(四)基本配置

添加依賴項後,您須要提供一些基本的Spring配置。雖然您能夠在技術上使用現有配置文件之一,但最好爲其配置單獨的文件。您須要提供的第一件事是@ EnableSwagger2註釋。而後你須要提供一個Docket bean,它是用於配置SpringFox的主bean。

@Configuration
@EnableSwagger2
public class SpringFoxConfig {
    @Bean
    public Docket apiDocket() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.any())
                .paths(PathSelectors.any())
                .build();
    }
}

固然,您能夠提供更多配置設置,咱們稍後會看到,但這是一個簡約配置,它執行如下操做:

  • @ EnableSwagger2支持Swagger 2的SpringFox支持。
  • DocumentationType.SWAGGER_2告訴Docket bean咱們正在使用Swagger規範的版本2。
  • select()建立一個構建器,用於定義哪些控制器及其生成的文檔中應包含哪些方法。
  • apis()定義要包含的類(控制器和模型類)。這裏咱們包括全部這些,但您能夠經過基礎包,類註釋等來限制它們。
  • paths()容許您根據路徑映射定義應包含哪一個控制器的方法。咱們如今包括全部這些,但您可使用正則表達式等限制它。

 

(五)添加UI

若是您如今部署應用程序,則已經生成了描述API的swagger元數據!你能夠看看:

http://localhost:8080/v2/api-docs

招摇,JSON

事實證實它只是一個很大的JSON,而不是人類可讀的。但你已經能夠驗證它是否有效。只需轉到Swagger在線編輯器並將JSON粘貼到那裏。將生成的JSON粘貼到左側面板,瞧!您如今能夠將生成的文檔視爲HTML頁面。不錯,不是嗎?將這些文檔做爲應用程序的一部分直接使用會更好。幸運的是,實現這一點很是容易。顯示基於JSON輸入的HTML文檔的GUI稱爲swagger-ui。要啓用它是一個Spring Boot應用程序,您只須要添加此依賴項:

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

//GRADLE 
compile "io.springfox:springfox-swagger-ui:2.9.2"

該文檔將在此處自動提供:

http://localhost:8080/swagger-ui.html

 

招摇的UI

 

(六)添加ApiInfo

默認狀況下,咱們文檔的標題部分看起來很是通用:

招摇头

如今是時候作點什麼了。咱們能夠經過簡單的配置更改來更改那裏的全部信息。在SpringFoxConfiguration文件中,咱們須要添加ApiInfo對象,該對象提供有關API的通常信息,例如標題,版本,聯繫人或許可信息。

@Bean
public Docket apiDocket() {
    return new Docket(DocumentationType.SWAGGER_2)
            .select()
            .apis(RequestHandlerSelectors.any())
            .paths(PathSelectors.any())
            .build()
            .apiInfo(getApiInfo());
}

private ApiInfo getApiInfo() {
    return new ApiInfo(
            "TITLE",
            "DESCIPRION",
            "VERSION",
            "TERMS OF SERVICE URL",
            new Contact("NAME","URL","EMAIL"),
            "LICENSE",
            "LICENSE URL",
            Collections.emptyList()
    );
}

如今咱們的文檔標題應該看起來更好:

招摇头更新的

(七)縮小已處理的API

到如今爲止還挺好。可是當你仔細看看生成的文檔時,你會發現除了咱們使用的模型和控制器類以外,還有一些特定於Spring的類,如Controllers部分中的BasicErrorController以及ViewModelAndView下的型號部分。

有時,縮小類,SpringFox會將其檢測爲文檔生成源。Controller和Model類。您能夠在Docket配置中輕鬆配置它。還記得像咱們使用.apis(RequestHandlerSelectors.any()來包含全部類嗎?讓咱們將它縮小到咱們的基礎包:

 

@Bean
public Docket apiDocket() {
    return new Docket(DocumentationType.SWAGGER_2)
            .select()
            .apis(RequestHandlerSelectors.basePackage("com.vojtechruzicka"))
            .paths(PathSelectors.any())
            .build()
            .apiInfo(getApiInfo());
}

當您想要指定應包含哪些類時,這很是有用。有時您還須要只包含特定的URL路徑。您可能正在使用API​​的多個版本以實現向後兼容,但不但願包含歷史版本。也許API的某些部分是內部的,不該該是公共文檔的一部分。不管哪一種方式,也能夠在Docket中配置基於URL匹配的這種包含。記住.paths(PathSelectors.any())?您能夠將其限制爲某些正則表達式或Ant樣式的路徑模式,而不是匹配全部路徑的任何路徑

@Bean
public Docket apiDocket() {
    return new Docket(DocumentationType.SWAGGER_2)
            .select()
            .apis(RequestHandlerSelectors.basePackage("com.vojtechruzicka"))
            .paths(PathSelectors.ant("/v2/**"))
            .build()
            .apiInfo(getApiInfo());
}

 

若是內置選項對您來講還不夠,您能夠隨時爲apis()paths()提供本身的謂詞。忽略某些類或方法的另外一種方法是使用@ApiIgnore註釋它們。

(八)使用JSR-303註解

JSR 303:Bean Validation  容許您註釋Java類的字段以聲明約束和驗證規則。您可使用如下規則註釋單個字段: - 不能爲空,最小值,最大值,正則表達式匹配等。

public class Person {
    @NotNull
    private int id;

    @NotBlank
    @Size(min = 1, max = 20)
    private String firstName;

    @NotBlank
    @Pattern(regexp ="[SOME REGULAR EXPRESSION]")
    private String lastName;

    @Min(0)
    @Max(100)
    private int age;

    //... Constructor, getters, setters, ...
}

這是一種已經普遍使用的常見作法。好消息是,SpringFox能夠根據這些註釋生成Swagger文檔,所以您能夠利用項目中已有的內容而無需手動編寫全部約束!它很是有用,由於您的API的消費者知道他們應該爲您的API提供的值的限制以及指望的值。若是沒有包含這樣的註釋,咱們的人員模型的生成文檔看起來很簡單,除了字段名稱及其數據類型以外什麼也沒有。

 

招摇的UI模型平原

使用來自JSR-303註釋的數據,它看起來會更好:

JSR-303-招摇

 

不幸的是,基於JSR-303的文檔沒法開箱即用,您須要一個額外的依賴:

//MAVEN
<dependency>
   <groupId>io.springfox</groupId>
   <artifactId>springfox-bean-validators</artifactId>
   <version>2.9.2</version>
</dependency>

//GRADLE
compile "io.springfox:springfox-bean-validators:2.9.2"

而且您須要在swagger配置類之上導入BeanValidatorPluginsConfiguration配置文件:

@Configuration
@EnableSwagger2
@Import(BeanValidatorPluginsConfiguration.class)
public class SpringFoxConfig {
  ...
}

(九)將Swagger Core註釋添加到模型類中

 

使用JSR-303的優勢是,若是您已經使用它們,您能夠絕不費力地得到額外的文檔信息,而無需更改任何代碼。問題是目前,SpringFox不顯示註釋中指定的驗證消息。此外,您可能須要記錄一些更復雜的約束。在這種狀況下,您可使用Swagger Core註釋,它容許您指定其餘信息,例如描述。用這些註釋註釋的Person類能夠看起來像這樣。

 

@ApiModel(description = "Class representing a person tracked by the application.")
public class Person {
    @ApiModelProperty(notes = "Unique identifier of the person. No two persons can have the same id.", example = "1", required = true, position = 0)
    private int id;
    @ApiModelProperty(notes = "First name of the person.", example = "John", required = true, position = 1)
    private String firstName;
    @ApiModelProperty(notes = "Last name of the person.", example = "Doe", required = true, position = 2)
    private String lastName;
    @ApiModelProperty(notes = "Age of the person. Non-negative integer", example = "42", position = 3)
    private int age;

    // … Constructor, getters, setters, ...
}

在類級別,您使用@ApiModel註釋並在字段級別@ApiModelProperty。固然,您能夠與JSR-303註釋混合搭配。 @ApiModelProperty的示例對於提供示例值很是有用,這不只適用於用戶的指導,並且還能夠在使用Swagger UI做爲REST客戶端來測試服務時預填充請求有效負載。Position屬性很方便指定屬性在文檔中顯示的順序。首先提供重要或必需的屬性或屬於一塊兒的組屬性是有用的。不然,屬性將按字母順序列出。

 

(十)將Swagger Core註釋添加到控制器類

與使用Swagger核心註釋註釋模型類以提供其餘元數據相同,您能夠註釋控制器及其方法和方法參數。

  • @Api描述了整個控制器
  • @ApiOperation用於方法級別的描述
  • @ApiParam用於方法參數

 

@RestController
@RequestMapping("/v2/persons/")
@Api(description = "Set of endpoints for Creating, Retrieving, Updating and Deleting of Persons.")
public class PersonController {

    private PersonService personService;

    @RequestMapping(method = RequestMethod.GET, produces = "application/json")
    @ApiOperation("Returns list of all Persons in the system.")
    public List getAllPersons() {
        return personService.getAllPersons();
    }

    @RequestMapping(method = RequestMethod.GET, path = "/{id}", produces = "application/json")
    @ApiOperation("Returns a specific person by their identifier. 404 if does not exist.")
    public Person getPersonById(@ApiParam("Id of the person to be obtained. Cannot be empty.")
                                    @PathVariable int id) {
        return personService.getPersonById(id);
    }

    @RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
    @ApiOperation("Deletes a person from the system. 404 if the person's identifier is not found.")
    public void deletePerson(@ApiParam("Id of the person to be deleted. Cannot be empty.")
                                 @PathVariable int id) {
        personService.deletePerson(id);
    }

    @RequestMapping(method = RequestMethod.POST, produces = "application/json")
    @ApiOperation("Creates a new person.")
    public Person createPerson(@ApiParam("Person information for a new person to be created.")
                                   @RequestBody Person person) {
        return personService.createPerson(person);
    }

    @Autowired
    public void setPersonService(PersonService personService) {
        this.personService = personService;
    }
}

如今您的文檔還應包含所提供的描述:

 

招摇控制器-doc的

 

請注意,咱們的控制器和域類如今受到Swagger特定註釋的困擾。可讀性受到很大影響,由於重要的信息在大量的漏洞中丟失了。更糟糕的是 - 當您更改代碼時,以這種方式編寫的文檔不會更新,您須要記住手動更改消息。這會增長您的文檔不一樣步的風險,所以不值得信任。最好包括一些不明顯的基本信息,而這些信息還沒有被自動生成的信息很好地涵蓋。具備參數的描述性名稱以及JSR-303註釋一般能夠記錄大部分所需信息。

 

 

(十一)從屬性文件加載描述

直接在註釋中提供描述並非很優雅。它可能佔用大量空間,污染您的代碼。你不能真正支持多種語言。若是要修復拼寫錯誤或對文檔進行一些更改,則須要從新構建並從新部署整個應用程序。根據環境,您不能擁有不一樣的值。不是很靈活。幸運的是,Spring提供了Property佔位符的概念。簡而言之,它容許您提供佔位符$ {placeholder}而不是硬編碼值。而後在.properties文件中定義佔位符的值。Spring從屬性加載數據並注入它而不是佔位符。很酷的是,您能夠爲每種語言提供多個屬性文件。您能夠在不一樣的環境中提供不一樣的屬性文件。

SpringFox在一些註釋中支持這種機制。這是一種很好的方法,能夠將文檔與代碼分離,並具備更大的靈活性。不幸的是,目前只支持一些註釋。所以,例如在模型中,它們在方法級別(@ApiModelProperty)上支持它,但在類級別(@ApiModel)上不支持它。

要完成這項工做,您須要:

  1. 建立屬性文件,例如swagger.properties
  2. 輸入您想要的消息做爲鍵值對,其中鍵將用做佔位符 - 例如person.id =此人的惟一標識符
  3. 而不是註釋文本插入佔位符 - 例如$ {person.id}
  4. 在類級別註冊配置中的屬性文件 - 例如。 @PropertySource( 「類路徑:swagger.properties」)

 

 

結論

SpringFox是一個有用的工具,它能夠根據您的Spring控制器和模型類自動生成Swagger文檔。它還能夠識別JSR-303註釋,所以您還要記錄模型類的全部約束。它還可使用核心的swagger類,例如@ApiModelProperty。但要當心,由於這會使你的代碼充滿了大量特定的註釋。只有在SpringFox沒法推斷信息自己時才使用它們老是更好。僅在須要添加某些描述時才使用它們,其中類,屬性和方法名稱不能自我解釋。再說一遍,你的API多是一個紅色標誌,說明你的API是神祕的仍是太複雜了。若是您保留由SpringFox自動生成的大部分文檔,您能夠確保它始終是最新的。除此之外,在代碼中進行更改時,您須要很是當心地更新Core Swagger註釋。若是您的文檔和代碼不匹配,用戶將失去對您的API文檔的信任,而且此類文檔幾乎無用。

 

 

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

聲明: 本文轉自      Vojtech Ruzicka的編程博客

相關文章
相關標籤/搜索