1. 程式人生 > >SpringBoot 使用swagger2構建Restful APIs

SpringBoot 使用swagger2構建Restful APIs

一、Swagger簡介

  • 在日常的工作中,我們往往需要給前端(WEB端、IOS、Android)或者第三方提供介面,這個時候我們就需要給他們提供一份詳細的API說明文件。但維護一份詳細的文件可不是一件簡單的事情。

  • 首先,編寫一份詳細的文件本身就是一件很費時費力的事情,另一方面,由於程式碼和文件是分離的,所以很容易導致文件和程式碼的不一致。這篇文章我們就來分享一種API文件維護的方式,即通過Swagger來自動生成Restuful API文件。

  • 那什麼是Swagger?我們可以直接看下官方的描述:

THE WORLD'S MOST POPULAR API TOOLING Swagger is the world’s largest framework of API developer tools for the OpenAPI Specification(OAS), enabling development across the entire API lifecycle, from design and documentation, to test and deployment.

  • 這段話首先告訴大家Swagger是世界上最流行的API工具,並且Swagger的目的是支撐整個API生命週期的開發,包括設計、文件以及測試和部署。這篇文章中我們會用到Swagger的文件管理和測試功能。

  • 對Swagger的作用有了基本的認識後,我們現在來看看怎麼使用。

二、Swagger與Spring boot整合

  1. 第一步,引入對應jar包:
	<!-- 整合swagger-->
	<dependency>
		<groupId>io.springfox</groupId>
		<artifactId>springfox-swagger2</artifactId>
		<version>2.6.0</version>
	</dependency>
	<dependency>
		<groupId>io.springfox</groupId>
		<artifactId>springfox-swagger-ui</artifactId>
		<version>2.6.0</version>
	</dependency>
  1. 第二步,基本資訊配置:
@Configuration
@EnableSwagger2
public class Swagger2Config {
    /**
     * 在這個配置類裡面我麼例項化了一個Docket物件,這個物件主要包括三個方面的資訊:
     --整個API的描述資訊,即ApiInfo物件包括的資訊,這部分資訊會在頁面上展示。
     --指定生成API文件的包名。
     --指定生成API的路徑。按路徑生成API可支援四種模式,這個可以參考其原始碼:
     * */
    @Bean
    public Docket createRestApi(){
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.zzw.bootlaunch.rest"))
                .paths(PathSelectors.regex("/rest/.*"))
                .build();
    }

    private ApiInfo apiInfo(){
        return new ApiInfoBuilder()
                .title("XXX系統的API")
                .description("這是一個XXX系統的描述")
                .termsOfServiceUrl("http://127.0.0.1:8080")
                .contact("zhangsanfeng")
                .version("V1.0")
                .build();
    }
}

基礎的配置是對整個API文件的描述以及一些全域性性的配置,對所有介面起作用。這裡涉及到兩個註解:

  • @Configuration是表示這是一個配置類,是JDK自帶的註解,前面的文章中也已做過說明。
  • @EnableSwagger2的作用是啟用Swagger2相關功能。

在這個配置類裡面我麼例項化了一個Docket物件,這個物件主要包括三個方面的資訊:

  • 整個API的描述資訊,即ApiInfo物件包括的資訊,這部分資訊會在頁面上展示。
  • 指定生成API文件的包名。
  • 指定生成API的路徑。按路徑生成API可支援四種模式,這個可以參考其原始碼:
public class PathSelectors {
    private PathSelectors() {
        throw new UnsupportedOperationException();
    }

    public static Predicate<String> any() {
        return Predicates.alwaysTrue();
    }

    public static Predicate<String> none() {
        return Predicates.alwaysFalse();
    }

    public static Predicate<String> regex(final String pathRegex) {
        return new Predicate<String>() {
            public boolean apply(String input) {
                return input.matches(pathRegex);
            }
        };
    }

    public static Predicate<String> ant(final String antPattern) {
        return new Predicate<String>() {
            public boolean apply(String input) {
                AntPathMatcher matcher = new AntPathMatcher();
                return matcher.match(antPattern, input);
            }
        };
    }
}

從原始碼可以看出,Swagger總共支援任何路徑都生成、任何路徑都不生成以及正則匹配和ant 模式匹配四種方式。大家可能比較熟悉的是前三種,最後一種ant匹配,如果不熟悉ant的話就直接忽略吧,前三種應該足夠大家在日常工作中使用了。

按照rest風格編寫服務類

@Slf4j
@RestController
@RequestMapping("/rest")
public class ArticleRestController {

    @Resource
    ArticleRestService articleRestService;

    /**
     * 儲存
     * */
    @RequestMapping(value="/article", method = RequestMethod.POST, produces = "application/json")
    public AjaxResponse saveArticle(@RequestBody Article article){
        log.info("saveArticle:{}",article);
        //操作資料庫
        articleRestService.saveArticle(article);
        return AjaxResponse.sucess(article);
    }

    /**
     * 刪除
     * */
    @RequestMapping(value="/article/{id}", method = RequestMethod.DELETE, produces = "application/json")
    public AjaxResponse delArticle(@PathVariable Long id){
        log.info("delArticle:{}", id);
        //操作資料庫
        articleRestService.deleteArticle(id);
        return AjaxResponse.sucess(id);
    }

    /**
     * 更新
     * */
    @RequestMapping(value="/article/{id}", method = RequestMethod.PUT, produces = "application/json")
    public AjaxResponse updateArtice(@PathVariable Long id, @RequestBody Article article){
        log.info("updateArtice:{}",article);
        //操作資料庫
        article.setId(id);
        articleRestService.updateArticle(article);
        return AjaxResponse.sucess(article);
    }

    /**
     * 獲取單條記錄
     * */
    @RequestMapping(value = "/article/{id}", method = RequestMethod.GET, produces = "application/json")
    public AjaxResponse getArtice(@PathVariable Long id){
        /*Article article =  Article.builder().id(22L).author("張三").content("我是內容內容....")
                .title("我是標題標題...").createTime(new Date()).build();
        log.info("getArtice:{}", article);*/

        //操作資料庫
        Article article = articleRestService.getArticle(id);
        return AjaxResponse.sucess(article);
    }
  1. 第三步,啟動並訪問

啟動Spring boot,然後訪問:http://127.0.0.1:8080/swagger-ui.html 即可看到如下結果:

我們還可以點進去看一下每一個具體的介面,我們這裡以“POST /rest/article”這個介面為例:

可以看到,Swagger為每一個介面都生成了返回結果和請求引數的示例,並且能直接通過下面的"try it out"進行介面訪問,方面大家對介面進行測試。整體上感覺Swagger還是很強大的,配置也比較簡單。

三、Swagger API詳細配置

不過大家看到這裡肯定會有點疑問:

  • 第一個問題:這個返回結果和請求引數都沒有中文文字性的描述,這個可不可以配置?

  • 第二個問題:這個請求參應該是直接根據物件反射出來的結果,但是不是物件的每個屬性都是必傳的,另外引數的值也不一定滿足我們的需求,這個能否配置?

答案肯定是可以的,現在我們就來解決這兩個問題,直接看配置的程式碼:

列表頁:

可以看到,現在介面都位於Article這個tag下,並且介面後面也有了我們配置好的說明。我們再看下”POST /rest/article“這個介面的詳情頁:

如果我們的請求引數是一個物件,那如何配置呢?這就涉及到另外兩個註解:@ApiModel和@ApiModelProperty,我們還是先看程式碼,然後再解釋,這樣更容易理解:

@ApiModel(value="article物件",description="新增&更新文章物件說明")
public class Article {
 
    @Id
    @GeneratedValue
    @ApiModelProperty(name = "id",value = "文章ID",required = false,example = "1")
    private Long id;
 
    @ApiModelProperty(name = "title",value = "文章標題",required = true,example = "測試文章標題")
    private String title;
 
    @ApiModelProperty(name = "summary",value = "文章摘要",required = true,example = "測試文章摘要")
    private String summary;
 
    @ApiModelProperty(hidden = true)
    private Date createTime;
 
    @ApiModelProperty(hidden = true)
    private Date publicTime;
 
    @ApiModelProperty(hidden = true)
    private Date updateTime;
 
    @ApiModelProperty(hidden = true)
    private Long userId;
 
    @ApiModelProperty(name = "status",value = "文章釋出狀態",required = true,example = "1")
    private Integer status;
 
    @ApiModelProperty(name = "type",value = "文章分類",required = true,example = "1")
    private Integer type;
}

@ApiModel是對整個類的屬性的配置:

  • value:類的說明
  • description:詳細描述

@ApiModelProperty是對具體每個欄位的屬性配置:

  • name:欄位名稱
  • value:欄位的說明
  • required:是否必須
  • example:示例值
  • hidden:是否顯示

完成上面的配置後,我們再來看效果:

點選Try it out後,我們就可以看到返回的結果:

操作還是很方便的,相比Junit和postman,通過Swagger來測試會更加便捷,當然,Swagger的測試並不能代替單元測試,不過,在聯調的時候還是有非常大的作用的。

四、總結

總體上來說,Swagger的配置還是比較簡單的,並且Swagger能夠自動幫我們生成文件確實為我們節省了不少工作,對後續的維護也提供了很大的幫助。除此之外,Swagger還能根據配置自動為我們生成測試的資料,並且提供對應的HTTP方法,這對我們的自測和聯調工作也有不少的幫助,所以我還是推薦大家在日常的開發中去使用Swagger,應該可以幫助大家在一定程度上提高工作效率的。那我們怎麼才能在生產環節中關閉這個功