java集成開發(fā)SpringBoot生成接口文檔示例實現(xiàn)
大家好,我是飄渺。
SpringBoot老鳥系列的文章已經(jīng)寫了兩篇,每篇的閱讀反響都還不錯,果然大家還是對SpringBoot比較感興趣。那今天我們就帶來老鳥系列的第三篇:集成Swagger接口文檔以及Swagger的高級功能。 文章涉及到的代碼已經(jīng)上傳到了github,希望最終能應(yīng)用在你們實際項目上,當(dāng)然如果有其他需要我添加到內(nèi)容也可以直接留言告訴我,我會視情況給你們加上去的。
SpringBoot 如何統(tǒng)一后端返回格式?老鳥們都是這樣玩的!
SpringBoot 如何進行參數(shù)校驗? 老鳥們都是這樣玩的!
好了,閑話少敘,讓我們先來看看為什么要用Swagger?
為什么要用Swagger ?
作為一名程序員,我們最討厭兩件事:1. 別人不寫注釋。2. 自己寫注釋。
而作為一名接口開發(fā)者,我們同樣討厭兩件事:
1. 別人不寫接口文檔,文檔不及時更新。
2. 需要自己寫接口文檔,還需要及時更新。
相信無論是前端還是后端開發(fā),都或多或少地被接口文檔折磨過。前端經(jīng)常抱怨后端給的接口文檔與實際情況不一致。后端又覺得編寫及維護接口文檔會耗費不少精力,經(jīng)常來不及更新。
而隨著Springboot、Springcloud等微服務(wù)的流行,每個項目都有成百上千個接口調(diào)用,這時候再要求人工編寫接口文檔并且保證文檔的實時更新幾乎是一件不可能完成的事,所以這時候我們迫切需要一個工具,一個能幫我們自動化生成接口文檔以及自動更新文檔的工具。它就是Swagger。
Swagger 提供了一個全新的維護 API 文檔的方式,有4大優(yōu)點:
自動生成文檔:只需要少量的注解,Swagger 就可以根據(jù)代碼自動生成 API 文檔,很好的保證了文檔的時效性。
跨語言性,支持 40 多種語言。
Swagger UI 呈現(xiàn)出來的是一份可交互式的 API 文檔,我們可以直接在文檔頁面嘗試 API 的調(diào)用,省去了準(zhǔn)備復(fù)雜的調(diào)用參數(shù)的過程。
還可以將文檔規(guī)范導(dǎo)入相關(guān)的工具(例如 SoapUI), 這些工具將會為我們自動地創(chuàng)建自動化測試。
現(xiàn)在我們知道了Swagger的作用,接下來將其集成到我們項目中。
Swagger集成
集成Swagger很簡單,只需要簡單三步。
第一步: 引入依賴包
<!--swagger--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <!--swagger-ui--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency>
第二步:修改配置文件
application.properties 加入配置
# 用于控制是否開啟Swagger,生產(chǎn)環(huán)境記得關(guān)閉Swagger,將值設(shè)置為 false springfox.swagger2.enabled = true
增加一個swagger配置類
@Configuration @EnableSwagger2 @ConditionalOnClass(Docket.class) public class SwaggerConfig { private static final String VERSION = "1.0"; @Value("${springfox.swagger2.enabled}") private Boolean swaggerEnabled; @Bean public Docket createRestApi(){ return new Docket(DocumentationType.SWAGGER_2) .enable(swaggerEnabled) .groupName("SwaggerDemo") .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.withClassAnnotation(Api.class)) .paths(PathSelectors.any()) .build(); } /** * 添加摘要信息 */ private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("接口文檔") .contact(new Contact("JAVA日知錄","http://javadaily.cn","jianzh5@163.com")) .description("Swagger接口文檔") .version(VERSION) .build(); } }
這里通過 .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
表面給加上 @Api注解的類自動生成接口文檔。
第三步,配置API接口
@RestController @Api(tags = "參數(shù)校驗") @Slf4j @Validated public class ValidController { @PostMapping("/valid/test1") @ApiOperation("RequestBody校驗") public String test1(@Validated @RequestBody ValidVO validVO){ log.info("validEntity is {}", validVO); return "test1 valid success"; } @ApiOperation("Form校驗") @PostMapping(value = "/valid/test2") public String test2(@Validated ValidVO validVO){ log.info("validEntity is {}", validVO); return "test2 valid success"; } @ApiOperation("單參數(shù)校驗") @PostMapping(value = "/valid/test3") public String test3(@Email String email){ log.info("email is {}", email); return "email valid success"; } }
通過 @Api
注解標(biāo)注需要生成接口文檔,通過 @ApiOperation
注解標(biāo)注接口名。
同時我們給 ValidVO
也加上對應(yīng)的注解
@Data @ApiModel(value = "參數(shù)校驗類") public class ValidVO { @ApiModelProperty("ID") private String id; @ApiModelProperty(value = "應(yīng)用ID",example = "cloud") private String appId; @NotEmpty(message = "級別不能為空") @ApiModelProperty(value = "級別") private String level; @ApiModelProperty(value = "年齡") private int age; ... }
通過 @ApiModel
標(biāo)注這是一個參數(shù)實體,通過 @ApiModelProperty
標(biāo)注字段說明。
Unable to infer base url
簡單三步,我們項目就集成了Swagger接口文檔,趕緊啟動服務(wù),訪問 http://localhost:8080/swagger-ui.html 體驗一下。
好吧,出了點小問題,不過不用慌。
出現(xiàn)這個問題的原因是因為我們加上了 ResponseBodyAdvice
統(tǒng)一處理返回值/響應(yīng)體,導(dǎo)致給Swagger的返回值也包裝了一層,UI頁面無法解析??梢酝ㄟ^ http://localhost:8080/v2/api-docs?group=SwaggerDemo觀察Swagger返回的json數(shù)據(jù)。
既然知道了問題原因那就很好解決了,我們只需要在ResponseBodyAdvice處理類中只轉(zhuǎn)換我們自己項目的接口即可。
@RestControllerAdvice(basePackages = "com.jianzh5.blog") @Slf4j public class ResponseAdvice implements ResponseBodyAdvice<Object> { ... }
通過添加basePackage屬性限定統(tǒng)一返回值的范圍,這樣就不影響Swagger了。
重啟服務(wù)器再次訪問swagger接口地址,就可以看到接口文檔頁面了。
For input string: “”
Swagger2.9.2有個bug,就是當(dāng)我們參數(shù)實體有int類型的參數(shù)時,打開Swagger接口頁面時后端會一直提示異常:
java.lang.NumberFormatException: For input string: "" at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) at java.base/java.lang.Long.parseLong(Long.java:702) at java.base/java.lang.Long.valueOf(Long.java:1144)
有兩種解決方案:
給int類型的字段使用@ApiModelPorperty
注解時添加example屬性
@ApiModelProperty(value = "年齡",example = "10") private int age;
去除原swagger中的swagger-models
和swagger-annotations
,自行引入高版本的annotations和models
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> <exclusions> <exclusion> <groupId>io.swagger</groupId> <artifactId>swagger-annotations</artifactId> </exclusion> <exclusion> <groupId>io.swagger</groupId> <artifactId>swagger-models</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>io.swagger</groupId> <artifactId>swagger-annotations</artifactId> <version>1.5.22</version> </dependency> <dependency> <groupId>io.swagger</groupId> <artifactId>swagger-models</artifactId> <version>1.5.22</version> </dependency>
集成Swagger過程中雖然會出現(xiàn)兩個小問題,解決后我們就可以愉快享受Swagger給我們帶來的便利了。
Swagger美化
Swagger原生UI有點丑,我們可以借助Swagger的增強工具 knife4j
優(yōu)化一下。
第一步: 引入依賴包
<!--整合Knife4j--> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-spring-boot-starter</artifactId> <version>2.0.4</version> </dependency>
由于knife4j中已經(jīng)帶了 swagger-annotations和 swagger-models的依賴,所以我們可以把上文中手動添加的兩個依賴刪除。
第二步:啟用knife4j增強
@Configuration @EnableSwagger2 @ConditionalOnClass(Docket.class) @EnableKnife4j public class SwaggerConfig { ... }
通過上面兩步我們就完成了Swagger的美化,通過瀏覽器訪問 http://localhost:8080/doc.html 即可看到效果。
Swagger參數(shù)分組
看到這里的同學(xué)心理肯定會想,就這?這就是老鳥的做法?跟我們新手也沒啥區(qū)別呀
別急,我們先來看一個效果。
首先我們定義了兩個接口,一個新增,一個編輯
@ApiOperation("新增") @PostMapping(value = "/valid/add") public String add(@Validated(value = {ValidGroup.Crud.Create.class}) ValidVO validVO){ log.info("validEntity is {}", validVO); return "test3 valid success"; } @ApiOperation("更新") @PostMapping(value = "/valid/update") public String update(@Validated(value = ValidGroup.Crud.Update.class) ValidVO validVO){ log.info("validEntity is {}", validVO); return "test4 valid success"; }
注意看,這里用的是同一個實體 ValidVO
來接收前端參數(shù),只不過使用了參數(shù)校驗中的分組,然后我們打開kife4j頁面觀察兩者的接口文檔有何不同。
新增:
編輯:
通過上面可以看到,雖然用于接受參數(shù)的實體一樣,但是當(dāng)分組不一樣時展示給前端的參數(shù)也不一樣,這就是Swagger的分組功能。
當(dāng)然原生的Swagger是不支持分組功能的,我們需要對Swagger進行擴展。我已經(jīng)將代碼上傳到了github上,由于代碼量比較多這里就不展示了,大家可以自行查閱。
引入擴展類后還需要在Swagger配置類 SwaggerConfig
中注入對應(yīng)的Bean。
@Configuration @EnableSwagger2 @ConditionalOnClass(Docket.class) @EnableKnife4j public class SwaggerConfig { ... @Bean @Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1000) public GroupOperationModelsProviderPlugin groupOperationModelsProviderPlugin() { return new GroupOperationModelsProviderPlugin(); } @Bean @Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1000) public GroupModelBuilderPlugin groupModelBuilderPlugin() { return new GroupModelBuilderPlugin(); } @Bean @Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1000) public GroupModelPropertyBuilderPlugin groupModelPropertyBuilderPlugin() { return new GroupModelPropertyBuilderPlugin(); } @Bean @Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1000) public GroupExpandedParameterBuilderPlugin groupExpandedParameterBuilderPlugin() { return new GroupExpandedParameterBuilderPlugin(); } @Bean @Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1000) public GroupOperationBuilderPlugin groupOperationBuilderPlugin() { return new GroupOperationBuilderPlugin(); } @Bean @Primary @Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1000) public GroupModelAttributeParameterExpander groupModelAttributeParameterExpander(FieldProvider fields, AccessorsProvider accessors, EnumTypeDeterminer enumTypeDeterminer) { return new GroupModelAttributeParameterExpander(fields, accessors, enumTypeDeterminer); } }
分組使用說明
1.在bean對象的屬性里配置如下注釋
@Null(groups = ValidGroup.Crud.Create.class) @NotNull(groups = ValidGroup.Crud.Update.class,message = "應(yīng)用ID不能為空") @ApiModelProperty(value = "應(yīng)用ID",example = "cloud") private String appId;
當(dāng)新增場景的時候,appId為空,不需要傳值; 當(dāng)修改場景的時候,appId不能為空,需要傳值 ;其他沒有配置組的皆為默認組(Default)
2.在接口參數(shù)的時候加入組規(guī)則校驗
@ApiOperation("新增") @PostMapping(value = "/valid/add") public String add(@Validated(value = {ValidGroup.Crud.Create.class}) ValidVO validVO){ log.info("validEntity is {}", validVO); return "test3 valid success"; }
當(dāng)前接口會針對默認組的bean屬性進行校驗,同時針對保存常見的屬性進行校驗。
小結(jié)
Swagger集成相對來說還是很簡單的,雖然在集成過程中也出現(xiàn)了幾個小問題,不過也很容易就解決了。今天文章的重點內(nèi)容是Swagger分組功能,跟之前的參數(shù)校驗文章一樣,很多同學(xué)遇到這種分組場景時往往會選擇創(chuàng)建多個實體類,雖然也能解決問題,只不過總是有點別扭。
不過遺憾的是,本文中Swagger的分組擴展只支持Swagger2,至于新版本Swagger3就不怎么支持了。如果有同學(xué)已經(jīng)擴展好了,歡迎給我提pr呀。
以上就是java集成開發(fā)SpringBoot生成接口文檔示例實現(xiàn)的詳細內(nèi)容,更多關(guān)于SpringBoot生成接口文檔的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
java根據(jù)模板導(dǎo)出PDF的詳細實現(xiàn)過程
前段時間因為相關(guān)業(yè)務(wù)需求需要后臺生成pdf文件,所以下面這篇文章主要給大家介紹了關(guān)于java根據(jù)模板導(dǎo)出PDF的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2022-02-02springsecurity記住我登錄時訪問無權(quán)限接口跳轉(zhuǎn)登錄界面的處理方案
這篇文章主要介紹了springsecurity記住我登錄時訪問無權(quán)限接口跳轉(zhuǎn)登錄界面的處理方案,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧2024-02-02Windows下將JAVA?jar注冊成windows服務(wù)的方法
這篇文章主要介紹了Windows下將JAVA?jar注冊成windows服務(wù)的方法,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-07-07SpringMVC的注解@RequestMapping屬性及使用
這篇文章主要為大家介紹了SpringMVC注解@RequestMapping屬性及使用,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-05-05IntelliJ IDEA中Project與Module的概念以及區(qū)別
這篇文章主要給大家介紹了關(guān)于IntelliJ IDEA中Project與Module的概念以及區(qū)別的相關(guān)資料,文中通過實例介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01IDEA快速搭建Java開發(fā)環(huán)境的教程圖解
這篇文章主要介紹了IDEA如何快速搭建Java開發(fā)環(huán)境,本文通過圖文并茂的形式給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-11-11