項(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特性說明
- 啟動(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)循衰。
- 兼容性強(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)行文檔生成奸鬓。
- 簡(jiǎn)單的注解
- springfox-bridge提供了幾個(gè)簡(jiǎn)單的注解供開發(fā)使用型型,注解的使用方式與springfox的類似,主要在類/接口全蝶、方法上進(jìn)行文檔的定義。
- 方便的分組
- 采用@BridgeGroup注解可以方便的為項(xiàng)目的接口文檔進(jìn)行分組寺枉,而無需手動(dòng)的配置Docket抑淫,springfox-bridge自動(dòng)按照@BridgeGroup的注解值將文檔進(jìn)行分組歸類。
- 不影響原有文檔
- springfox-bridge通過分組隔離姥闪,項(xiàng)目中原先使用springfox為restful接口生成的文檔始苇,不會(huì)受到springfox-bridge的影響
- 方法入?yún)⒉幌薅ㄕ?qǐng)求體的數(shù)量
- 原生springfox對(duì)restful請(qǐng)求生成文檔,而restful只支持一個(gè)請(qǐng)求體入?yún)ⅲㄓ聾RequestBody注解標(biāo)識(shí))筐喳。springfox-bridge沒有這個(gè)限制催式。
- 支持界面測(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>
- 非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即可
- 非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
- 首先看下面兩個(gè)分組的截圖授段,其中test-group1:
test-group2:
說明:
用spring-fox對(duì)某個(gè)類生成API文檔蹲蒲,必須用在類上使用@BridgeApi注解,并在需要生成文檔的方法上使用@BridgeOperation注解侵贵。
如果要對(duì)某個(gè)類分組届搁,可以在類上標(biāo)識(shí)@BridgeGroup注解。前面示例中窍育,通過@BridgeGroup注解定義了2個(gè)分組卡睦,將3個(gè)Service類進(jìn)行了歸類,在上面兩圖可以看到漱抓,通過下拉框切換分組后表锻,將分別展示@BridgeGroup注解定義的不同分組的頁面。當(dāng)然@BridgeGroup如果不定義乞娄,springfox-bridge會(huì)生成一個(gè)名為defafult的分組瞬逊,將沒有顯式定義@BridgeGroup注解的文檔歸類到default分組下。
swagger頁面上類的tag采用類全名的方式展示仪或,@BridgeApi注解的description值也會(huì)展示在界面上描述類的作用确镊。
@BridgeOperation注解定義方法,springfox-bridge會(huì)在對(duì)應(yīng)的類tag下生成對(duì)應(yīng)的方法tag范删,由圖可以看出蕾域,path路徑的組成格式為:“/類全名/方法名/入?yún)⒌念惷鬃帜附M合”。
如果@BridgeOperation定義的方法沒有入?yún)ⅲ敲磒ath路徑中則沒有“入?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)㈩愋腿故镜取m?xiàng)目源碼見github: https://github.com/double-bin/springfox-bridge