爲什麼要用Swagger?
首先說一下需求:最近公司要開發一個小程序,我負責後臺的接口開發。公司爲了規範接口文檔要統一使用YAPI 進行管理。YAPI支持Swagger 格式json文件導入,所以準備將公司的一個老項目接入Swagger2。在集成的過程中遇到一些問題,特意寫這篇文章與大家分享。希望有同樣需求的你少走些彎路。
項目環境版本
項目Spring版本: 3.2.2.RELEASE ,並且該項目不是mavne項目。
maven項目搭建步驟
Spring4 並且是maven項目的話集成相對簡單一些。集成的步驟如下:
引入Swagger2的2個核心依賴即可,
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.7.0</version>
</dependency>
然後就是配置Swagger 的配置類,配置類具體內容如下:
package com.bfsuol.swagger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
@EnableWebMvc
public class SwaggerConfig {
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
// .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
.apis(RequestHandlerSelectors.basePackage("com.bfsuol.app.interfaces.controller"))
.build().apiInfo(apiInfo());
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("開放接口API")
.description("HTTP對外開放接口")
.version("1.0.0")
.termsOfServiceUrl("http://xxx.xxx.com")
.license("LICENSE")
.licenseUrl("http://xxx.xxx.com")
.build();
}
}
maven項目使用步驟參考 和光同塵ss 博主的文章 你也可以點擊查看原文的具體操作步驟 Maven+SpringMVC+SwaggerUI
Spring3 項目集成Swagger中遇到的問題
整理jar包的方法
但是我們的項目是非mavne項目。
我的做法是創建mavne項目,然後引入上面2個核心依賴然後去本地倉庫中複製jar包,jar包的具體路徑如下圖紅色框所示。
缺少jar包的問題
整理完jar包複製到我們的jar 項目中。第一次嘗試報如下圖錯誤:
Caused by: java.io.FileNotFoundException: class path resource [org/mapstruct/Mapper.class] cannot be opened because it does not exist
at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:157)
at org.springframework.core.type.classreading.SimpleMetadataReader.<init>(SimpleMetadataReader.java:50)
at org.springframework.core.type.classreading.SimpleMetadataReaderFactory.getMetadataReader(SimpleMetadataReaderFactory.java:80)
at org.springframework.core.type.classreading.CachingMetadataReaderFactory.getMetadataReader(CachingMetadataReaderFactory.java:102)
at org.springframework.core.type.classreading.SimpleMetadataReaderFactory.getMetadataReader(SimpleMetadataReaderFactory.java:76)
at org.springframework.context.annotation.ConfigurationClassParser.getImports(ConfigurationClassParser.java:298)
at org.springframework.context.annotation.ConfigurationClassParser.getImports(ConfigurationClassParser.java:300)
at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:231)
at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:154)
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:131)
at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:225)
at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:154)
at org.springframework.context.annotation.ConfigurationClassParser.processImport(ConfigurationClassParser.java:349)
at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:233)
at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:154)
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:131)
at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.ja
在mavne項目中搜索該類 發現該類在mapstruct-1.1.0.Final.jar包中 我們將該jar包複製到我們的項目中。
聲明@EnableWebMvc報錯問題
第二次嘗試 沒有報上面的錯誤但是報如在錯誤:
Caused by: java.lang.ClassCastException: org.springframework.web.accept.ContentNegotiationManagerFactoryBean$$EnhancerByCGLIB$$dbb6606b cannot be cast to org.springframework.web.accept.ContentNegotiationManager
at org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration$$EnhancerByCGLIB$$269d1c34.mvcContentNegotiationManager(<generated>)
at org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport.requestMappingHandlerMapping(WebMvcConfigurationSupport.java:196)
at org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration$$EnhancerByCGLIB$$269d1c34.CGLIB$requestMappingHandlerMapping$19(<generated>)
at org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration$$EnhancerByCGLIB$$269d1c34$$FastClassByCGLIB$$ad3fcfb7.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:286)
at org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration$$EnhancerByCGLIB$$269d1c34.requestMappingHandlerMapping(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43
去掉 @EnableWebMvc 因爲配置文件中已經配置了mvc:annotation-driven
在次啓動沒有報錯。
Spring版本不兼容的問題
滿心歡喜的去訪問swagger-ui.html頁面取查看我們定義的接口,結果報如下錯誤。此時我的內心是崩潰的。
java.lang.NoSuchMethodError: org.springframework.web.util.UriComponentsBuilder.fromHttpRequest(Lorg/springframework/http/HttpRequest;)Lorg/springframework/web/util/UriComponentsBuilder;
at springfox.documentation.swagger2.web.HostNameProvider.componentsFrom(HostNameProvider.java:44)
at springfox.documentation.swagger2.web.Swagger2Controller.getDocumentation(Swagger2Controller.java:93)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
從錯誤中我們發先該類未定義但是spring的jar包確實存在。 明顯是Spring版本太低的問題。現在解決方式只有2種。
1 升級Spring版本
2 降低 Swagger 的版本
我這裏選擇了 降低 Swagger 的版本,百度搜索swagger的pom依賴
這裏選擇最低版本再次進行嘗試。如下圖所示 我們集成成功!
需要集成的jar包的 請點擊鏈接去下載(僅僅是swagger 先關jar沒有spring的jar吧哈):https://download.csdn.net/download/ljk126wy/11099420