全網最全SpringBoot集成swagger的詳細教程
一. 接口文檔概述
swagger是當下比較流行的實時接口文文檔生成工具。接口文檔是當前前後端分離項目中必不可少的工具,在前後端開發之前,後端要先出接口文檔,前端根據接口文檔來進行項目的開發,雙方開發結束後在進行聯調測試。
所以接口文檔其實就是開發之前雙方之間的一種約定。通常接口文檔分為離線的和實時的。離線的接口文檔工具有: word(相當於沒說), YAPI, 小幺雞等,這種文檔需要程序員在上面編寫,也一般具備接口測試功能。通常是由開發人員先在離線接口文檔上編寫信息,然後交給前端人員參照開發。最大的弊端是當我們的接口程序發生變動時,需要回過頭來維護上面的內容,很麻煩,是真的麻煩。
實時接口文檔就是可以根據我們的代碼來自動生成相應的接口文檔,優點就是我們的代碼發生變化時,生成的接口文檔也會自動更新,無需我們關註修改,主需要按時發佈即可。但是由於是根據代碼自動生成的,所以最大的弊端就是代碼侵入性強,需要我們在項目代碼中集成生成接口文檔的相關代碼。實時接口文檔現在的方案有很多,但是swagger還是其中比較有影響力的一個。
二. SpringBoot集成swagger2
官網地址: swagger.io 當然,官網都是英文的,看起來還是比較麻煩的。建議大傢直接按照我的步驟來,還是很簡單的。
同時在說一點: swagger分為swagger2 和swagger3兩個常用版本。二者區別不是很大,主要對於依賴和註解進行瞭優化。swagger2需要引入2個jar包,swagger3隻需要一個,用起來沒有什麼大的區別。下面以swagger2為例。
2.1 引入依賴
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency>
2.2 引入配置
首先需要添加一個註解 : @EnableSwagger2。 這個註解我們可以添加到SpringBoot的啟動類上,也可以自定義一個配置類,放到上面。添加瞭這個註解以後,就代表我們已經在項目中開啟瞭Swagger的功能。
我們采用第二種方式,自己定義一個配置類,正好還可以添加一個Docket配置。 所謂Docket配置,就是一組(一個項目或一個版本)接口文檔的配置,比如設置名稱, 聯系人等等。
我們在config文件夾下,添加一個SwaggerConfig類。
@Configuration @EnableSwagger2 public class SwaggerConfig { /** * 設置多個: * * @Bean * public Docket appApi() { * * List<Parameter> pars = new ArrayList<>(); * ParameterBuilder token = new ParameterBuilder(); * token.name("token").description("用戶令牌").modelRef(new ModelRef("string")).parameterType("header").required(false) * .build(); * pars.add(token.build()); * * return new Docket(DocumentationType.SWAGGER_2).select().paths(regex("/app/.*")).build() * .globalOperationParameters(pars).apiInfo(pdaApiInfo()).useDefaultResponseMessages(false) * .enable(enableSwagger) * .groupName("appApi"); * * } * * @Bean * public Docket adminApi() { * * List<Parameter> pars = new ArrayList<>(); * ParameterBuilder token = new ParameterBuilder(); * token.name("token").description("用戶令牌").modelRef(new ModelRef("string")).parameterType("header").required(false) * .build(); * pars.add(token.build()); * return new Docket(DocumentationType.SWAGGER_2).select().paths(regex("/admin/.*")).build() * .globalOperationParameters(pars).apiInfo(pdaApiInfo()).useDefaultResponseMessages(false) * .enable(enableSwagger) * .groupName("adminApi"); * * } * * * @return */ @Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select() .apis(RequestHandlerSelectors.basePackage("com.lsqingfeng.action.swagger.controller")).paths(PathSelectors.any()) .build().globalOperationParameters(setHeaderToken()); } private ApiInfo apiInfo() { return new ApiInfoBuilder().title("action-swagger").description("swagger實戰").termsOfServiceUrl("") .version("1.0").build(); } /** * @Description: 設置swagger文檔中全局參數 * @param * @Date: 2020/9/11 10:15 * @return: java.util.List<springfox.documentation.service.Parameter> */ private List<Parameter> setHeaderToken() { List<Parameter> pars = new ArrayList<>(); ParameterBuilder userId = new ParameterBuilder(); userId.name("token").description("用戶TOKEN").modelRef(new ModelRef("string")).parameterType("header") .required(true).build(); pars.add(userId.build()); return pars; } }
上面就是一個配置案例, 還設置瞭一個setToken方法,代表生成文檔的所有接口中,都要包含一個header類型的token參數。
2.3 給Controller 添加註解
我們接口文檔的直接描述主要就是在Controller這一層,比如這個接口的功能,參數的名稱,返回值的名稱等。這些值我們都需要在Controller上通過給方法上,請求參數和返回參數上添加對應的註解,swagger才能幫我們生成相應的接口文檔。這也就是我前面提到的對現有代碼的侵入性。
我們來寫一個案例。
首先先創建一個vo的包,裡邊寫我們的請求和相應參數,使用JavaBean定義出請求和響應的數據結構。註意這裡要添加相應的註解:
請求類:
package com.lsqingfeng.springboot.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** * @className: SwaggerReqVO * @description: * @author: sh.Liu * @date: 2022-03-22 19:19 */ @Data @ApiModel("創建Swagger請求參數") public class SwaggerReqVO { @ApiModelProperty("id") private Integer id; @ApiModelProperty("姓名") private String name; @ApiModelProperty("性別") private Integer gender; }
響應類:
package com.lsqingfeng.springboot.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** * @className: SwaggerResVO * @description: * @author: sh.Liu * @date: 2022-03-22 19:20 */ @Data @ApiModel("創建Swagger響應結果") public class SwaggerResVO { @ApiModelProperty("id") private Integer id; @ApiModelProperty("姓名") private String name; @ApiModelProperty("性別") private Integer gender; @ApiModelProperty("啥啥") private String what; }
這裡分別使用瞭 @ApiModel註解和 @@ApiModelProperty 註解定義瞭實體的名稱和字段的名稱,方便生成接口文檔時展示。
再來看Controller:
package com.lsqingfeng.springboot.controller; import com.lsqingfeng.springboot.vo.SwaggerReqVO; import com.lsqingfeng.springboot.vo.SwaggerResVO; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.*; /** * @className: SwaggerController * @description: swagger 接口測試 * @author: sh.Liu * @date: 2022-03-22 19:18 */ @RestController @RequestMapping("/swagger") @Api(value = "用戶接口", tags = {"用戶接口"}) public class SwaggerController { @ApiOperation("新增用戶") @PostMapping("save") public String save(@RequestBody SwaggerReqVO req) { return "success"; } @GetMapping("getById") @ApiOperation("根據條件查詢用戶") public SwaggerResVO getById(@RequestBody SwaggerResVO req) { return new SwaggerResVO(); } }
這裡使用瞭@Api註解和 @ApiOperation註解分別標註瞭接口組名和接口的名稱。現在我們啟動項目。
發現報瞭這個錯誤。
上網查詢原因說是SpringBoot2.6版本和Swagger2.9.2不兼容導致的。 也有人說是由於guava這個包的版本過低導致的。
我都分別試瞭一下,替換瞭guava的高版本依賴問題還是存在。
這個問題的主要原因確實是SpringBoot版本過高導致。如果你用的是SpringBoot2.5.x及之前版本是沒有問題的。
Spring Boot 2.6.X使用PathPatternMatcher匹配路徑,Swagger引用的Springfox使用的路徑匹配是基於AntPathMatcher的。
所以要想解決,添加配置,將springBoot MVC的路勁匹配模式修改一下即可。
在springBoot配置文件中添加配置:
spring.mvc.pathmatch.matching-strategy=ANT_PATH_MATCHER
如果是yml格式的配置文件:
再次啟動問題解決。
訪問地址: ip:端口號/swagger-ui.html
正常情況就可以看到我們的界面瞭。一會再說非正常情況。由於我們隻給用戶接口添加瞭註解,所有用戶接口是可以直接觀察中文文檔的。而剩下的兩個接口,由於沒添加註解,所以都是以默認的形式展示的。
點開接口,我們可以看到接口中的想詳細信息
點擊model,可以看到字段的中文描述。點擊 Try it out,就可以直接調試接口。同時註意接口中都讓填一個token,這就是我們之前的設置成效瞭。
截止到目前其實swagger的集成就已經完畢瞭,主要就是根據我們的註解生成文檔,並且可以在線調用調試。開發的時候,我們隻需要把Controller這一層的請求和響應,以及方法描述等內容先開發完畢,就可以提供給前端讓他們參照開發瞭。
2.4 [404]問題解決
正常情況我們按照上面的步驟就可以出現頁面,但是有些時候可能是由於springBoot的版本過高導致的,我們輸入之前的地址,出現404的情況,這個主要是由於項目中無法讀取到swagger依賴包下的頁面導致的。如果出現瞭這個問題,我們可以添加一個配置類,讓他實現WebMvcConfigurer 接口,在添加一個方法:
@Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/**").addResourceLocations("classpath:/static/"); registry.addResourceHandler("swagger-ui.html") .addResourceLocations("classpath:/META-INF/resources/"); registry.addResourceHandler("/webjars/**") .addResourceLocations("classpath:/META-INF/resources/webjars/"); }
完整代碼如下:
package com.lsqingfeng.springboot.config; import com.lsqingfeng.springboot.interceptor.TokenInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** * @className: WebMvcConfig * @description:webMvc配置 * @author: sh.Liu * @date: 2022-01-13 09:51 */ @Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/**").addResourceLocations("classpath:/static/"); registry.addResourceHandler("swagger-ui.html") .addResourceLocations("classpath:/META-INF/resources/"); registry.addResourceHandler("/webjars/**") .addResourceLocations("classpath:/META-INF/resources/webjars/"); } }
這個時候在啟動就可以瞭!
2.5 替換UI
上面的整個過程已經完成瞭,但是生成的接口文檔的頁面,其實很多人不太喜歡,覺得不太符合國人的使用習慣,所有又有一些大神,提供瞭其他的UI測試頁面。這個頁面的使用還是比較廣泛的。
修改方式:隻需引入一個依賴包:
<dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>swagger-bootstrap-ui</artifactId> <version>1.9.6</version> </dependency>
然後把剛才實現的那個的那個方法再添加一條:
registry.addResourceHandler("doc.html") .addResourceLocations("classpath:/META-INF/resources/");
完成代碼:
package com.lsqingfeng.springboot.config; import com.lsqingfeng.springboot.interceptor.TokenInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** * @className: WebMvcConfig * @description:webMvc配置 * @author: sh.Liu * @date: 2022-01-13 09:51 */ @Configuration public class WebMvcConfig implements WebMvcConfigurer { // @Override // public void addInterceptors(InterceptorRegistry registry) { // //攔截 // registry.addInterceptor(new TokenInterceptor()) // .addPathPatterns("/**") // .excludePathPatterns("/login"); // } @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/**").addResourceLocations("classpath:/static/"); registry.addResourceHandler("swagger-ui.html") .addResourceLocations("classpath:/META-INF/resources/"); registry.addResourceHandler("/webjars/**") .addResourceLocations("classpath:/META-INF/resources/webjars/"); registry.addResourceHandler("doc.html") .addResourceLocations("classpath:/META-INF/resources/"); } }
重新啟動項目: 訪問路徑發生瞭變化:** ip:端口號/doc.html**
頁面出現瞭。我們在看看我們的用戶接口:
這個風格確實更加的直觀,同時也是可以直接進行調試的。大部分的swagger都用的這個風格的文檔。
三. SpringBoot集成swagger3
上面已經很詳細的講解瞭swagger2的集成方式,而swagger3的集成方式更加的簡潔一些。
首先引入依賴:
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-boot-starter</artifactId> <version>3.0.0</version> </dependency>
然後是替換註解: swagger2使用的開啟註解是: @EnableSwagger2
而在swagger3中,這個註解要換成: @EnableOpenApi
配置類:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.oas.annotations.EnableOpenApi; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; @Configuration public class SwaggerConfig { @Bean public Docket createRestApi() { return new Docket(DocumentationType.OAS_30) // v2 不同 .select() .apis(RequestHandlerSelectors.basePackage("com.example.swaggerv3.controller")) // 設置掃描路徑 .build(); } }
要註意,裡邊的版本類型換成瞭 OAS_30, 就是swagger3的意思。
OAS 是 OpenAPI Specification 的簡稱,翻譯成中文就是 OpenAPI 說明書。
同時訪問地址:原始地址,也就是沒換UI的地址: localhost:8080/swagger-ui/index.html這個要和swagger2區分開。
swagger3的原始UI風格也發生瞭一些變化:
同時swagger3也是可以更換UI的。方法和swagger2一樣。
四. swaggerUI 攔截器和跨域沖突處理
如果我們的項目中有關於跨域的處理,同時還有攔截器,然後還要使用swagger,這種情況大傢要註意瞭,有可能我們的攔截器會將swagger中的頁面路徑攔截掉導致swagger頁面出不來,當我們在攔截器中把swagger的頁面排除掉的時候,也有可能會導致跨域配置的失效。
詳細的解決方案可以看我之前寫過的一篇博客: lsqingfeng.blog.csdn.net/article/det…
具體解決方案簡單提一下:
攔截器:
/** * 攔截器配置 * * @author liuShuai */ @Configuration public class InterceptorConfig implements WebMvcConfigurer { @Bean public TokenInterceptor tokenInterceptor() { return new TokenInterceptor(); } @Override public void addInterceptors(InterceptorRegistry registry) { registry .addInterceptor(tokenInterceptor()) .addPathPatterns("/**") .excludePathPatterns("/user/login") .excludePathPatterns("/user/downloadExcel") .excludePathPatterns("/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**"); } @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("swagger-ui.html") .addResourceLocations("classpath:/META-INF/resources/"); registry.addResourceHandler("/webjars/**") .addResourceLocations("classpath:/META-INF/resources/webjars/"); } }
跨域配置:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; /** * @className: CorsConfig * @description: * @author: sh.Liu * @date: 2020-12-02 10:16 */ @Configuration public class CorsConfig { @Bean public CorsFilter corsFilter() { CorsConfiguration config = new CorsConfiguration(); config.addAllowedOrigin("*"); config.setAllowCredentials(true); config.addAllowedMethod("*"); config.addAllowedHeader("*"); UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource(); configSource.registerCorsConfiguration("/**", config); return new CorsFilter(configSource); } }
用這兩種方式去配置,就可以讓他們和平共處瞭。
另: 配套項目代碼已托管中gitCode: gitcode.net/lsqingfeng/…
分支: feautre/MybatisPlus
所有文章也會在微信公眾號首發更新,歡迎關註:
五. 寫在最後
截止到本篇文章,關於SpringBoot的系列學習筆記已經更新瞭十六篇,也基本上要和大傢說再見瞭。感謝大傢的一路支持。這十六篇文章主要面向SpringBoot的實戰性學習上,基本很少會介紹一些原理性的概念。也已經集成目前大部分主流的框架和中間件。如果大傢對於Spring中一些生命周期,初始化過程,類加載原理和常用註解不太瞭解(因為這一個部分很少介紹),建議大傢結合我之前寫的Spring5系列教程一起學習,裡邊介紹瞭Spring IOC和AOP的核心概念。
這個系列的教程就更新到這裡瞭,後面可能就不會在繼續更新這個系列瞭。下個目標,我可能準備寫一個SpringCloud的系列教程,主要針對alibaba版本中的一些組件用法。但是由於最近公司比較忙,可能更新的會比較慢。希望大傢多多支持。
到此這篇關於全網最全SpringBoot集成swagger的詳細教程的文章就介紹到這瞭,更多相關SpringBoot集成swagger內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- springboot更新配置Swagger3的一些小技巧
- 詳解SpringBoot禁用Swagger的三種方式
- Spring security 如何開放 Swagger 訪問權限
- springboot詳解整合swagger方案
- Swagger2配置方式(解決404報錯)