SpringBoot2.3.0集成Swagger2
背景:最近在工作中發現,已經多次發現後臺開發人員提供的接口協議和實際的業務代碼不統一。這些現象往往都是因爲開發人員在對接口協議調整後沒有及時進行協議文檔的更新造成的。
引入Swagger2相應的依賴
在SprintBoot中引入Swagger2依賴包很簡單,在pom.xml文件中引入相應的依賴即可。
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.8.0</version>
</dependency>
入門示例
我們創建一個入門的Springboot項目。項目整體目錄結構如下:
然後編寫一個DemoController類,在類中添加幾個方法,具體如下:
package com.majing.learning.springboot.swagger2.controller;
import com.majing.learning.springboot.swagger2.entity.User;
import io.swagger.annotations.*;
import org.springframework.web.bind.annotation.*;
import java.util.*;
@RestController
@Api(tags = "用戶管理相關接口")
@RequestMapping(value="/users")
public class DemoController {
static Map<Long, User> users = Collections.synchronizedMap(new HashMap<>());
static{
users.put(1L, new User(1L,"majing1", "31"));
users.put(2L, new User(2L,"majing2", "32"));
users.put(3L, new User(3L,"majing3", "33"));
users.put(4L, new User(4L,"majing4", "34"));
}
@ApiOperation(value="獲取用戶列表", notes="")
@RequestMapping(value={""}, method= RequestMethod.GET)
@ApiResponses(value={@ApiResponse(code=9001, message="OK"),@ApiResponse(code=9002, message="ERROR")})
public List<User> getUserList() {
List<User> r = new ArrayList<User>(users.values());
return r;
}
@ApiOperation(value="創建用戶", notes="根據User對象創建用戶")
@ApiImplicitParam(name = "user", value = "用戶詳細實體user", required = true, dataType = "User")
@RequestMapping(value="/", method=RequestMethod.POST)
public String postUser(@RequestBody User user) {
users.put(user.getId(), user);
return "success";
}
@ApiOperation(value="獲取用戶詳細信息", notes="根據url的id來獲取用戶詳細信息")
@ApiImplicitParam(name = "id", value = "用戶ID", required = true, dataType = "Long")
@RequestMapping(value="/{id}", method=RequestMethod.GET)
public User getUser(@PathVariable Long id) {
return users.get(id);
}
@ApiOperation(value="更新用戶詳細信息", notes="根據url的id來指定更新對象,並根據傳過來的user信息來更新用戶詳細信息")
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "用戶ID", required = true, dataType = "Long"),
@ApiImplicitParam(name = "user", value = "用戶詳細實體user", required = true, dataType = "User")
})
@RequestMapping(value="/{id}", method=RequestMethod.PUT)
public String putUser(@PathVariable Long id, @RequestBody User user) {
User u = users.get(id);
u.setName(user.getName());
u.setAge(user.getAge());
users.put(id, u);
return "success";
}
@ApiOperation(value="刪除用戶", notes="根據url的id來指定刪除對象")
@ApiImplicitParam(name = "id", value = "用戶ID", required = true, dataType = "Long")
@RequestMapping(value="/{id}", method=RequestMethod.DELETE)
public String deleteUser(@PathVariable Long id) {
users.remove(id);
return "success";
}
}
對於上面的實體類User定義如下:
package com.majing.learning.springboot.swagger2.entity;
import io.swagger.annotations.ApiModel;
@ApiModel
public class User {
private Long id;
private String name;
private String age;
public User(long id, String name, String age){
this.id = id;
this.name = name;
this.age = age;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
}
爲了使用Swagger2,需要在應用啓動類同級目錄加上Swagger2的配置及註解,具體如下:
package com.majing.learning.springboot.swagger2;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
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
public class Swagger2Config {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.majing.learning.springboot.swagger2.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Spring Boot中使用Swagger2構建RESTful APIs")
.description("測試使用Swagger2生成API文檔")
.termsOfServiceUrl("https://***.com/")
.contact("馬靖")
.version("1.0")
.build();
}
}
接下來我們啓動應用程序,然後訪問http://localhost:5002/swagger-ui.html,即可看到自動生成的API文檔。這裏的端口根據需要在application.properties文件自行調整。
至此,在SpringBoot2中集成Swagger2便完成了,看了下生成的API文檔,感覺還是不錯的。
SpringBoot2集成Swagger2後啓動報錯
上面的示例是沒問題的,但是最開始嘗試集成Swagger2時遇到個啓動報錯,其中有一段錯誤信息如下:
AnnotationConfigServletWebServerApplicationContext: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'linkDiscoverers' defined in class path resource [org/springframework/hateoas/config/HateoasConfiguration.class]: Unsatisfied dependency expressed through method 'linkDiscoverers' parameter 0; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.springframework.plugin.core.PluginRegistry<org.springframework.hateoas.client.LinkDiscoverer, org.springframework.http.MediaType>' available: expected single matching bean but found 15: modelBuilderPluginRegistry,modelPropertyBuilderPluginRegistry,typeNameProviderPluginRegistry,documentationPluginRegistry,apiListingBuilderPluginRegistry,operationBuilderPluginRegistry,parameterBuilderPluginRegistry,expandedParameterBuilderPluginRegistry,resourceGroupingStrategyRegistry,operationModelsProviderPluginRegistry,defaultsProviderPluginRegistry,pathDecoratorRegistry,relProviderPluginRegistry,linkDiscovererRegistry,entityLinksPluginRegistry
剛開始看到這個錯誤有點懵逼,後來百度了下,說是Swagger2版本和Springboot版本不兼容導致,所以就修改了下Swagger2的版本,用了2.8.0,我自己的SpringBoot版本是2.3.0,重新啓動了下,發現問題真的沒有了。這裏做個記錄。
結語
上面我們通過Swagger2實現了後臺代碼動態生成和更新API文檔,非常方便。但是有個缺點是沒有訪問權限的控制,數據Mock等功能。而且存在一定的代碼侵入。後來針對國內外的API接口管理平臺給調研了下,主要看了下ShowDoc、阿里雲的RAP和CRAP-API,覺得都還挺好用的,有需要的可以自己研究下,這三個都是可以支持私有化部署的。