swagger是當下比較流行的即時介面文件產生工具。介面文件是目前前後端分離專案中必不可少的工具,在前後端開發之前,後端要先出介面文檔,前端根據介面文件來進行專案的開發,雙方開發結束後在進行聯調測試。
所以介面文件其實就是開發之前雙方之間的一種約定。通常介面文件分為離線的和即時的。離線的介面文件工具有: word(相當於沒說), YAPI, 小么雞等,這種文件需要程式設計師在上面寫,也一般具備介面測試功能。通常是由開發人員先在離線介面文件上撰寫訊息,然後交給前端人員參考開發。最大的弊端是當我們的介面程式發生變動時,需要回過頭來維護上面的內容,很麻煩,是真的很麻煩。
即時介面文檔就是可以根據我們的程式碼自動產生對應的介面文檔,優點就是我們的程式碼變更時,產生的介面文件也會自動更新,無需我們關注修改,主需要準時發布即可。但是由於是根據程式碼自動產生的,所以最大的弊端就是程式碼侵入性強,需要我們在專案程式碼中整合生成介面文檔的相關程式碼。即時介面文件現在的方案很多,但是swagger還是其中比較有影響力的一個。
官網位址:swagger.io 當然,官網都是英文的,看起來還是比較麻煩的。建議大家直接照我的步驟來,還是很簡單的。
同時在說一點: swagger分為swagger2 和swagger3兩個常用版本。二者差異不是很大,主要對於依賴和註解進行了最佳化。 swagger2需要引入2個jar包,swagger3只需要一個,用起來沒有什麼大的差別。下面以swagger2為例。
<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>
#首先需要新增一個註解 : @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參數。
我們介面文件的直接描述主要就是在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这一层的请求和响应,以及方法描述等内容先开发完毕,就可以提供给前端让他们参照开发了。
正常情况我们按照上面的步骤就可以出现页面,但是有些时候可能是由于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/"); } }
这个时候在启动就可以了!
上面的整个过程已经完成了,但是生成的接口文档的页面,其实很多人不太喜欢,觉得不太符合国人的使用习惯,所有又有一些大神,提供了其他的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都用的这个风格的文档。
上面已经很详细的讲解了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一样。
如果我们的项目中有关于跨域的处理,同时还有拦截器,然后还要使用swagger,这种情况大家要注意了,有可能我们的拦截器会将swagger中的页面路径拦截掉导致swagger页面出不来,当我们在拦截器中把swagger的页面排除掉的时候,也有可能会导致跨域配置的失效。
具体解决方案简单提一下:
拦截器:
/** * 拦截器配置 * * @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整合swagger實例分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!