Spring Boot如何讓Web API自動生成文件,並解決swagger-annotations的API註解description屬性廢棄的問題
前後端分離的系統架構中,前端開發人員需要檢視後端WEB API的文件來進行開發。採用後端API文件自動生成的方式,可以大幅提高開發效率。swagger是一個被廣泛使用的文件自動生成工具,可以與多種程式語言結合使用。我們可以利用合適的jar包,讓swqgger來協助java開發。本文講述瞭如何把 swagger 與 Spring Boot 框架結合起來使用。
我用一個專案來解釋如何完成上述的目標。開啟 eclipse。 File → New → Maven Project → 選中Create a simple project(skip archetype selection)和Use default Workspace location → Next → Group Id 填成 zhangchao,Artifact Id 填成 blog4 → Finish。這時我們可以在eclipse中看到一個blog4專案。
當我們完成blog4專案的時候,blog4的目錄結構應該如下:
blog4
│
├─ pom.xml
│
└─ src
│
└─ main
│
├─ java
│ └─ zhangchao
│ │
│ └─ blog4
│ │
│ ├─ Blog4Application.java
│ ├─ Blog4MvcConfig.java
│ ├─ User.java
│ ├─ UserAddressController.java
│ └─ UserController.java
│
└─ resources
├─ application.properties
└─ public
├─ css
└─ images
我使用 Maven 來管理專案。 Maven 專案的配置檔案 pom.xml 內容如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>zhangchao</groupId>
<artifactId>blog4</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.2.RELEASE</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.6.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
pom.xml 檔案中 groupId 是 io.springfox 的兩個依賴是自動生成文件所需的依賴元件。
java/main/resources下的application.properties 檔案內容:
spring.jackson.serialization.indent_output=true
server.tomcat.uri-encoding=UTF-8
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
spring.http.encoding.force=true
Blog4Application.java 啟動專案,程式碼如下:
package zhangchao.blog4;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Blog4Application {
public static void main(String[] args){
SpringApplication.run(Blog4Application.class, args);
}
}
Blog4MvcConfig.java 是配置類,程式碼如下:
package zhangchao.blog4;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.service.Tag;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class Blog4MvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*")
.allowedMethods("GET", "HEAD", "POST","PUT", "DELETE", "OPTIONS")
.allowCredentials(false).maxAge(3600);
}
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
/* .tags 第一個引數必須是Tag,後面的是 Tag 型別的可選引數
new Tag(String,String) 第一個引數是key,第二個引數是Value。註解@Api#tags傳入的是tag的key */
.tags(new Tag("user", "使用者相關"),getTags())
.select()
.apis(RequestHandlerSelectors.basePackage("zhangchao.blog4"))
.paths(PathSelectors.any())
.build();
}
private Tag[] getTags() {
Tag[] tags = {
new Tag("book", "書相關的API"),
new Tag("dog", "狗相關")
};
return tags;
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Spring Boot中使用Swagger2構建RESTful APIs")
.description("api根地址:http://api.xiaomo.info:8080/")
.termsOfServiceUrl("https://xiaomo.info/")
.contact(new Contact("張超","",""))
.version("1.0")
.build();
}
}
Blog4MvcConfig 類中,為了生成文件,必須在類名上方加註解@EnableSwagger2。createRestApi()、getTags() 和 apiInfo() 三個成員方法都是用來配置文件自動生成的。createRestApi 中的 tags 方法引數需要注意,第一個引數必須是 Tag。後面的是可選引數,型別可以是Tag陣列,也可以是多個Tag。
傳值類 User 的內容:
package zhangchao.blog4;
import java.math.BigDecimal;
import java.sql.Timestamp;
import io.swagger.annotations.ApiModelProperty;
public class User {
public String id;
public String name;
public BigDecimal balance;
@ApiModelProperty(example="1481770165015")
public Timestamp birthday;
}
在這裡 @ApiModelProperty(example="1481770165015")
用來更改 swagger 的使用者介面。使用者介面上關於 user 的例子中,birthday 的取值是1481770165015。如果你用傳統java bean的形式,在成員變數上直接加這個註解就行,get方法和set方法不做改變。
UserController.java 的內容:
package zhangchao.blog4;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.UUID;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
/*
* 在swagger-annotations jar包中 1.5.X版本以上, 註解 io.swagger.annotations.API
* 中的description被廢棄了。新的swagger元件中使用了新的方法來對Web api 進行分組。原來使用 description ,
* 預設一個Controller類中包含的方法構成一 個api分組。現在使用tag,可以更加方便的分組。
* 比如把兩個Controller類裡的方法劃分成同一個分組。tag的key用來區分不同的分組。tag的value用做分組的描述。
* @ApiOperation 中value是api的簡要說明,在介面api 連結的右側,少於120個字元。
* @ApiOperation 中notes是api的詳細說明,需要點開api 連結才能看到。
* @ApiOperation 中 produces 用來標記api返回值的具體型別。這裡是json格式,utf8編碼。
*/
@RestController
@RequestMapping("/user")
@Api(tags={"user"})
public class UserController {
@ApiOperation(value = "新增使用者", notes = "新增使用者注意事項", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@RequestMapping(value="",method=RequestMethod.POST)
public User save(@RequestBody User user){
user.id = UUID.randomUUID().toString();
return user;
}
@ApiOperation(value = "使用者詳情", notes = "使用者詳情注意事項", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@RequestMapping(value="/{id}",method=RequestMethod.GET)
public User get(@PathVariable String id){
User user = new User();
user.balance = new BigDecimal("3.2");
user.id = id;
user.name = "小明";
user.birthday = new Timestamp(System.currentTimeMillis());
return user;
}
@ApiOperation(value = "更新使用者", notes = "更新使用者注意事項", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@RequestMapping(value="",method=RequestMethod.PUT)
public User update(@RequestBody User user){
return user;
}
@ApiOperation(value = "刪除使用者", notes = "刪除使用者注意事項", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@RequestMapping(value="/{id}",method=RequestMethod.DELETE)
public String delete(@PathVariable String id){
return "success";
}
}
UserAddressController.java 內容:
package zhangchao.blog4;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
/*
UserAddressController 和 UserController 的 Api 註解的 tags 引數都使用
了key=user 的tag。在文件中,可以看到 這兩個Controller的web api 被放在同一個
分組中。
*/
@RestController
@RequestMapping("/user")
@Api(tags={"user"})
public class UserAddressController {
@ApiOperation(value = "使用者地址詳情", notes = "使用者地址詳情注意事項", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@RequestMapping(value="/address/{id}",method=RequestMethod.GET)
public String get(@PathVariable String id){
return "萊陽路8號";
}
@ApiOperation(value = "刪除使用者地址", notes = "刪除使用者地址注意事項", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@RequestMapping(value="/address/{id}",method=RequestMethod.DELETE)
public String delete(@PathVariable String id){
return "success";
}
}
這裡下載壓縮檔案,解壓後是一個public 資料夾,這個public資料夾包含css 資料夾和images資料夾。請把這個 public 資料夾放到 src/main/resources 下面。