【開源項(xiàng)目】springfox-bridge:隨心所欲地為非restful接口生成API文檔

項(xiàng)目github地址: https://github.com/double-bin/springfox-bridge

一、引言

????目前,利用swagger框架為restful接口編寫API文檔非常流行,在spring web項(xiàng)目中,利用springfox+swagger更是可以通過注解的方式直接進(jìn)行API文檔的生成,這樣開發(fā)者在項(xiàng)目開發(fā)的同時(shí)就直接把文檔準(zhǔn)備好了,利用springfox的配置,可以在項(xiàng)目啟動(dòng)后直接瀏覽器訪問查看API文檔,同時(shí)還能在界面直接進(jìn)行API的測(cè)試。springfox的使用本文不在此贅述了,現(xiàn)在引出一個(gè)問題: 非restful接口能否采用swagger生成接口文檔

????在項(xiàng)目中集成springfox-bridge可以快速的為非restful接口生成API文檔,編寫文檔的方式跟springfox一樣簡(jiǎn)單,在相關(guān)類或者接口上采用注解的方式定義文檔信息即可。

????springfox-bridge相當(dāng)于架設(shè)了一座與springfox之間的橋梁,通過動(dòng)態(tài)生成配置了springfox注解的mvc接口并進(jìn)行注冊(cè),形成對(duì)非restful接口生成swagger文檔的能力。

二、springfox-bridge特性說明

  1. 啟動(dòng)簡(jiǎn)單
  • 在springboot項(xiàng)目中,集成springfox-bridge-spring-boot-starter即可自動(dòng)啟動(dòng);
  • 在非springboot項(xiàng)目中,通過實(shí)現(xiàn)ApplicationContextAware接口,通過SpringfoxBridge.start(ApplicationContext context)方法,并配置@EnableSwagger2注解即可快速啟動(dòng)。
  1. 兼容性強(qiáng)
  • 與協(xié)議無關(guān),不挑協(xié)議,無論你是使用dubbo、ServiceComb還是其它種種,只要項(xiàng)目本身啟用了springmvc, 相應(yīng)的接口注冊(cè)了spring bean, 就能像使用springfox那樣使用springfox-brige,用注解的方式為接口生成文檔。
  • 更進(jìn)一步的講,只要滿足上述條件的spring bean, 即使不是controller層的接口,也能使用springfox-bridge進(jìn)行文檔生成。
  1. 簡(jiǎn)單的注解
  • springfox-bridge提供了幾個(gè)簡(jiǎn)單的注解供開發(fā)使用,注解的使用方式與springfox的類似,主要在類/接口、方法上進(jìn)行文檔的定義。
  1. 方便的分組
  • 采用@BridgeGroup注解可以方便的為項(xiàng)目的接口文檔進(jìn)行分組,而無需手動(dòng)的配置Docket,springfox-bridge自動(dòng)按照@BridgeGroup的注解值將文檔進(jìn)行分組歸類。
  1. 不影響原有文檔
  • springfox-bridge通過分組隔離,項(xiàng)目中原先使用springfox為restful接口生成的文檔,不會(huì)受到springfox-bridge的影響
  1. 方法入?yún)⒉幌薅ㄕ?qǐng)求體的數(shù)量
  • 原生springfox對(duì)restful請(qǐng)求生成文檔,而restful只支持一個(gè)請(qǐng)求體入?yún)ⅲㄓ聾RequestBody注解標(biāo)識(shí))。springfox-bridge沒有這個(gè)限制。
  1. 支持界面測(cè)試
  • 跟springfox生成文檔可以通過界面直接調(diào)用一樣,springfox-bridge同樣支持

三、使用說明

使用springfox-bridge需要項(xiàng)目本身啟用了springmvc框架, spring相關(guān)依賴版本在spring3.1以上

3.1 配置maven依賴

1)使用了springboot的項(xiàng)目:

        <dependency>
            <groupId>com.github.double-bin</groupId>
            <artifactId>springfox-bridge-spring-boot-starter</artifactId>
            <version>1.0.8</version>
        </dependency>
  1. 非springboot項(xiàng)目:
        <dependency>
            <groupId>com.github.double-bin</groupId>
            <artifactId>springfox-bridge-core</artifactId>
            <version>1.0.8</version>
        </dependency>

3.2 啟動(dòng)配置

1)使用了springboot的項(xiàng)目

  • 配置了springfox-bridge-spring-boot-starter后,默認(rèn)開啟springfox-bridge。
  • 如果需要關(guān)閉,可以在application.properties文件(或yml文件)中配置springfox.bridge.enabled的值為false即可
  1. 非springboot項(xiàng)目:
    可通過配置類實(shí)現(xiàn)ApplicationContextAware接口的setApplicationContext方法,方法實(shí)現(xiàn)中通過SpringfoxBridge.start()方法啟動(dòng)springfox-bridge, 配置類上通過@EnableSwagger2啟動(dòng)springfox基本功能, 可參考:
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;
import com.github.doublebin.springfox.bridge.core.SpringfoxBridge;
import springfox.documentation.swagger2.annotations.EnableSwagger2;


@EnableSwagger2
@Configuration
public class MyXXXConfiguration implements ApplicationContextAware {
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringfoxBridge.start(applicationContext);

    }
}

3.3 使用示例

下面示例代碼演示如何使用springfox-bridge的注解,如何定義的文檔,如果設(shè)置分組等,展示結(jié)果請(qǐng)看3.4

1, 定義兩個(gè)請(qǐng)求的model類:TestRquest1和TestRequest2

model類中可以使用springfox的原生注解:io.swagger.annotations.ApiModel和io.swagger.annotations.ApiModelProperty

package com.github.doublebin.springfox.bridge.demo.model;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@ApiModel(value="TestRequest1", description = "測(cè)試請(qǐng)求體1")
public class TestRequest1 {

    @ApiModelProperty(value = "唯一id", required = true)
    private long uuid;

    @ApiModelProperty(value = "名字", required = true)
    private String name;
}

package com.github.doublebin.springfox.bridge.demo.model;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@ApiModel(value="TestRequest2", description = "測(cè)試請(qǐng)求體2")
public class TestRequest2 {

    @ApiModelProperty(value = "名字", required = true)
    private String name;

    @ApiModelProperty(value = "描述", required = true)
    private String desc;
}

2, 定義三個(gè)service類,并標(biāo)注@Service供spring掃描并注冊(cè)bean。
package com.github.doublebin.springfox.bridge.demo.service;

import com.github.doublebin.springfox.bridge.demo.model.TestRequest1;
import com.github.doublebin.springfox.bridge.demo.model.TestRequest2;
import org.springframework.stereotype.Service;
import com.github.doublebin.springfox.bridge.core.builder.annotations.BridgeApi;
import com.github.doublebin.springfox.bridge.core.builder.annotations.BridgeGroup;
import com.github.doublebin.springfox.bridge.core.builder.annotations.BridgeModelProperty;
import com.github.doublebin.springfox.bridge.core.builder.annotations.BridgeOperation;

@Service
@BridgeApi(value = "TestService1 Apis", description = "測(cè)試服務(wù)1")
@BridgeGroup("test-group1")
public class TestService1 {

    @BridgeOperation(value = "測(cè)試查詢1", notes = "測(cè)試查詢方法1說明")
    public String testQuery(@BridgeModelProperty(value = "用戶id", required = true) long id, @BridgeModelProperty(value = "請(qǐng)求2", required = false) TestRequest1 request){
        return "Test query success, id is " + id;
    }

    @BridgeOperation(value = "測(cè)試查詢2", notes = "測(cè)試查詢方法2說明")
    public String testQuery(@BridgeModelProperty(value = "用戶id", required = true) long id){
        return "Test query success, id is " + id;
    }

    @BridgeOperation(value = "測(cè)試查詢3", notes = "測(cè)試查詢方法3說明")
    public String testQuery(){
        return "Test query success.";
    }

    @BridgeOperation(value = "測(cè)試查詢4", notes = "測(cè)試查詢方法4說明")
    public String testQuery(@BridgeModelProperty(value = "用戶id", required = true) long id, @BridgeModelProperty(value = "請(qǐng)求2", required = false) TestRequest2 request){
        return "Test query success, id is " + id;
    }

}
package com.github.doublebin.springfox.bridge.demo.service;

import com.github.doublebin.springfox.bridge.core.builder.annotations.BridgeApi;
import com.github.doublebin.springfox.bridge.core.builder.annotations.BridgeGroup;
import com.github.doublebin.springfox.bridge.core.builder.annotations.BridgeModelProperty;
import com.github.doublebin.springfox.bridge.core.builder.annotations.BridgeOperation;
import com.github.doublebin.springfox.bridge.demo.model.TestRequest1;
import org.springframework.stereotype.Service;

@Service
@BridgeApi(value = "TestService2 Apis", description = "測(cè)試服務(wù)2")
@BridgeGroup("test-group2")
public class TestService2 {
    @BridgeOperation(value = "測(cè)試查詢", notes = "測(cè)試查詢方法說明")
    public String testQuery(@BridgeModelProperty(value = "用戶id", required = true) long id, @BridgeModelProperty(value = "請(qǐng)求2", required = false) TestRequest1 request){
        return "Test query success, id is " + id;
    }
}

package com.github.doublebin.springfox.bridge.demo.service;

import com.github.doublebin.springfox.bridge.core.builder.annotations.BridgeApi;
import com.github.doublebin.springfox.bridge.core.builder.annotations.BridgeGroup;
import com.github.doublebin.springfox.bridge.core.builder.annotations.BridgeModelProperty;
import com.github.doublebin.springfox.bridge.core.builder.annotations.BridgeOperation;
import com.github.doublebin.springfox.bridge.demo.model.TestRequest1;
import org.springframework.stereotype.Service;

@Service
@BridgeApi(value = "TestService3 Apis", description = "測(cè)試服務(wù)3")
@BridgeGroup("test-group1")
public class TestService3 {
    @BridgeOperation(value = "測(cè)試查詢", notes = "測(cè)試查詢方法說明")
    public String testQuery(@BridgeModelProperty(value = "用戶id", required = true) long id, @BridgeModelProperty(value = "請(qǐng)求2", required = false) TestRequest1 request){
        return "Test query success, id is " + id;
    }
}

?

????示例中定義了2個(gè)分組:test-group1 和 test-group2, 其中TestService1和TestService3歸屬于test-group1分組,TestService2歸屬于test-group2分組,其中TestService1中定義了多個(gè)不同的方法,在3.4節(jié)中會(huì)展示這些情況下的多個(gè)效果

3.4 示例效果展示

瀏覽器訪問地址:http:${host}:${port}/${server.context-path}/swagger-ui.html

  1. 首先看下面兩個(gè)分組的截圖,其中test-group1:
test-group1.png

test-group2:

test-group2.png

說明:

  • 用spring-fox對(duì)某個(gè)類生成API文檔,必須用在類上使用@BridgeApi注解,并在需要生成文檔的方法上使用@BridgeOperation注解。

  • 如果要對(duì)某個(gè)類分組,可以在類上標(biāo)識(shí)@BridgeGroup注解。前面示例中,通過@BridgeGroup注解定義了2個(gè)分組,將3個(gè)Service類進(jìn)行了歸類,在上面兩圖可以看到,通過下拉框切換分組后,將分別展示@BridgeGroup注解定義的不同分組的頁(yè)面。當(dāng)然@BridgeGroup如果不定義,springfox-bridge會(huì)生成一個(gè)名為defafult的分組,將沒有顯式定義@BridgeGroup注解的文檔歸類到default分組下。

  • swagger頁(yè)面上類的tag采用類全名的方式展示,@BridgeApi注解的description值也會(huì)展示在界面上描述類的作用。

  • @BridgeOperation注解定義方法,springfox-bridge會(huì)在對(duì)應(yīng)的類tag下生成對(duì)應(yīng)的方法tag,由圖可以看出,path路徑的組成格式為:“/類全名/方法名/入?yún)⒌念惷鬃帜附M合”。

  • 如果@BridgeOperation定義的方法沒有入?yún)?,那么path路徑中則沒有“入?yún)⒌念愂鬃帜附M合”;如果兩個(gè)同名方法入?yún)⒌念惷鬃帜附M合相同,那么第二個(gè)及之后的同名方法的path路徑會(huì)追加“/index數(shù)字”以區(qū)分不同的方法,index的排序以springfox-bridge內(nèi)部對(duì)方法加載的順序進(jìn)行排序。

  • @BridgeOperation注解的value值標(biāo)識(shí)該方法的簡(jiǎn)要說明,跟path在同一行展示。

  • @BridgeModelProperty注解可以對(duì)方法入?yún)⑦M(jìn)行標(biāo)識(shí),用以對(duì)入?yún)⒓右哉f明

  • 方法入?yún)㈩愋腿绻且粋€(gè)model類,該model類可以用io.swagger包的原生注解@ApiModel(標(biāo)識(shí)類)和@ApiModelProperty(標(biāo)識(shí)字段)對(duì)model類進(jìn)行說明,之所以用原生注解,是為了兼容原生springfox,不必重復(fù)定義注解。

  • 在swagger界面上可以看到,springfox-bridge對(duì)每個(gè)標(biāo)識(shí)了@BridgeOperation的方法都動(dòng)態(tài)生成一個(gè)post請(qǐng)求,并動(dòng)態(tài)生成一個(gè)body請(qǐng)求體,方法的所有入?yún)⒍甲鳛樾抡?qǐng)求體的字段。

四、springfox-bridge注解說明

4.1 springfox-bridge自定義注解
注解 位置 主要字段 說明 對(duì)標(biāo)原生注解
BridgeApi description 對(duì)類進(jìn)行說明 io.swagger.annotations.Api
BridgeGroup value 標(biāo)識(shí)分組
BridgeOperation 方法 value、notes value、notes分別標(biāo)識(shí)方法概要和詳細(xì)說明 io.swagger.annotations.ApiOperation
BridgeModelProperty 入?yún)?/td> value 標(biāo)識(shí)入?yún)⒄f明 io.swagger.annotations.ApiModelProperty
4.2 兼容的springfox swagger原生注解

目前兼容入?yún)⒌恼?qǐng)求體的model用io.swagger包的原生注解@ApiModel@ApiModelProperty ,后續(xù)會(huì)提供其它支持

五、展望

目前springfox-bridge的1.0.8版本已經(jīng)發(fā)布到maven中央倉(cāng)庫(kù),后續(xù)會(huì)持續(xù)更新,支持更多的特性, 比如: 兼容更多的springfox swagger的原生注解、支持返回體說明、支持author自定義、支持入?yún)㈩愋腿故镜?。?xiàng)目源碼見github: https://github.com/double-bin/springfox-bridge

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容