一、簡介
spring-boot作為目前最為流行的Java web開發腳手架,越來越多的開發者選擇用其來建構企業級的RESTFul API接口。這些接口不但會服務于傳統的web端(b/s),也會服務于移動端。在實際開發過程中,這些接口還要提供給開發測試進行相關的白盒測試,那麼勢必存在如何在多人協作中共享和及時更新API開發接口文檔的問題。
假如你已經對傳統的wiki文檔共享方式所帶來的弊端深惡痛絕,那麼嘗試一下Swagger2 方式,一定會讓你有不一樣的開發體驗。
使用 Swagger 內建文檔具有以下幾個優勢:
- 功能豐富 :支援多種注解,自動生成接口文檔界面,支援在界面測試API接口功能;
- 及時更新 :開發過程中花一點寫注釋的時間,就可以及時的更新API文檔,省心省力;
- 整合簡單 :通過添加pom依賴和簡單配置,内嵌于應用中就可同時釋出API接口文檔界面,不需要部署獨立服務。
二、案例
1、pom引包
<!--添加Swagger依賴 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.7.0</version>
</dependency>
<!--添加Swagger-UI依賴 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.7.0</version>
</dependency>
<!-- 引入swagger-bootstrap-ui依賴包-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
<version>1.8.7</version>
</dependency>
2、添加配置類
package com.zhouzy.ssm.config;
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;
import com.github.xiaoymin.swaggerbootstrapui.annotations.EnableSwaggerBootstrapUI;
@Configuration
@EnableSwagger2
@EnableSwaggerBootstrapUI // 開啟SwaggerBootstrapUI
public class SwaggerConfig {
@Bean
public Docket createRestApi(){
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any()).build();
}
private ApiInfo apiInfo(){
return new ApiInfoBuilder()
.title("Kitty API Doc")
.description("This is a restful api document of Kitty.")
.version("1.0")
.build();
}
}
3、接口
1)接口組
接口有時候應該是分組的,而且大部分都是在一個controller中的,比如使用者管理相關的接口應該都在UserController中,那麼不同的業務的時候,應該定義/劃分不同的接口組。接口組可以使用
@Api
來劃分。
比如:
/* 類注解 */
@Api(tags = "首頁管理")
@Controller
public class IndexController {
}
2)接口
我們可以使用
@ApiOperation
來描述接口,比如:
/**
* 首頁
* @author zhouzhiyao
* @date 2021/08/03
**/
@ApiOperation(value = "首頁", notes = "跳轉到使用者清單頁面")
@RequestMapping("/")
public String index() {
return "user/userList";
}
常用配置項:
- value:可以當作是接口的簡稱
- notes:接口的描述
- tags:可以額外定義接口組,比如這個接口外層已經有
,将接口劃分到了“使用者管理”中,但你可以額外的使用tags,例如@Api(tags = "使用者管理")
讓角色管理中也有這個接口文檔。tags = "角色管理"
3)參數
此時我們需要使用
@ApiModel
來标注實體類,然後在接口中定義入參為實體類即可:
- @ApiModel:用來标類
- 常用配置項:
- value:實體類簡稱
- description:實體類說明
- 常用配置項:
- @ApiModelProperty:用來描述類的字段的意義。
- 常用配置項:
- value:字段說明
- example:設定請求示例(Example Value)的預設值,如果不配置,當字段為string的時候,此時請求示例中預設值為"".
- name:用新的字段名來替代舊的字段名。
- allowableValues:限制值得範圍,例如
代表隻能取這三個值;{1,2,3}
代表取1到5的值;[1,5]
代表1到5的值,不包括1和5;還可以使用infinity或-infinity來無限值,比如(1,5)
代表最小值為1,最大值無窮大。[1, infinity]
- required:标記字段是否必填,預設是false,
- hidden:用來隐藏字段,預設是false,如果要隐藏需要使用true,因為字段預設都會顯示,就算沒有
。@ApiModelProperty
- 常用配置項:
比如:
package com.zhouzy.ssm.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
import java.util.Date;
/**
* @description 使用者資訊表
* @author zhouzhiyao
* @date 2021-08-03
*/
@ApiModel(value="使用者資訊",description="使用者資訊")
public class UserInfo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* id
*/
@ApiModelProperty(value = "使用者ID",required = false,example = "1",hidden=true)
private Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
/**
* 姓名
*/
@ApiModelProperty(value = "姓名",required = true,example = "張三")
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/**
* 年齡
*/
@ApiModelProperty(value = "年齡",required = true,example = "23")
private Integer age;
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
/**
* 性别:0:男 1:女
*/
@ApiModelProperty(value = "性别",required = true,example = "0")
private Integer sex;
public Integer getSex() {
return sex;
}
public void setSex(Integer sex) {
this.sex = sex;
}
/**
* 位址
*/
@ApiModelProperty(value = "位址",required = true,example = "上海浦東")
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
/**
* 手機号
*/
@ApiModelProperty(value = "手機号",required = true,example = "13349668342")
private String mobile;
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
/**
* 建立時間
*/
private Date createTime;
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
/**
* 更新時間
*/
private Date updateTime;
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
public UserInfo() {}
}
4) 新增一個控制層接口類
package com.zhouzy.ssm.controller;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.alibaba.fastjson.JSONObject;
import com.zhouzy.ssm.model.DataGrid;
import com.zhouzy.ssm.model.PageInfo;
import com.zhouzy.ssm.model.UserInfo;
import com.zhouzy.ssm.service.UserInfoService;
/* 類注解 */
@Api(tags = "使用者管理")
@Controller
@RequestMapping("/user")
public class UserInfoController {
@Resource
private UserInfoService userInfoService;
/**
* 新增
* @author zhouzhiyao
* @date 2021/08/03
**/
@ApiOperation(value = "新增使用者", notes = "新增使用者")
@PostMapping("/insert")
@ResponseBody
public void insert(@RequestBody UserInfo userInfo){
userInfoService.innerTest(userInfo);
}
/**
* 刪除
* @author zhouzhiyao
* @date 2021/08/03
**/
@ApiOperation(value = "删除使用者", notes = "删除使用者")
@PostMapping("/delete")
public void delete(int id){
userInfoService.delete(id);
}
/**
* 更新
* @author zhouzhiyao
* @date 2021/08/03
**/
@ApiOperation(value = "更新使用者", notes = "更新使用者")
@PostMapping("/update")
public void update(UserInfo userInfo){
userInfoService.update(userInfo);
}
/**
* 查詢 根據主鍵 id 查詢
* @author zhouzhiyao
* @date 2021/08/03
**/
@ApiOperation(value = "根據ID檢視使用者", notes = "使用者詳情")
@GetMapping("/load")
public Object load(int id){
return userInfoService.load(id);
}
/**
* 查詢 分頁查詢
* @author zhouzhiyao
* @date 2021/08/03
**/
@ApiOperation(value = "跳轉使用者清單", notes = "跳轉使用者清單")
@GetMapping("/list")
public String pageList() {
return "user/userList";
}
/**
* 查詢 分頁查詢
* @author zhouzhiyao
* @date 2021/08/03
**/
@ApiOperation(value = "分頁查詢", notes = "分頁查詢使用者清單")
@SuppressWarnings("unchecked")
@GetMapping("/listData")
@ResponseBody
public String listData(PageInfo page) {
int pageNum = page.getPage();
int size = page.getLimit();
Map<String,Object> map = userInfoService.pageList((pageNum-1)*size, size);
List<UserInfo> data = (List<UserInfo>)map.get("data");
int count = (Integer)map.get("count");
DataGrid<UserInfo> grid = new DataGrid<UserInfo>(data,count,0,null);
return JSONObject.toJSONString(grid);
}
/**
* 新增
* @author zhouzhiyao
* @date 2021/08/03
**/
@ApiOperation(value = "批量插入", notes = "批量插入")
@PostMapping("/insertBatch")
@ResponseBody
public void insertBatch(){
List<UserInfo> users = new ArrayList<UserInfo>();
UserInfo u1 = new UserInfo();
UserInfo u2 = new UserInfo();
u1.setName("張三");
u1.setAddress("上海");
u1.setAge(24);
u1.setMobile("13347882343");
u1.setSex(0);
u2.setName("李四");
u2.setAddress("北京");
u2.setAge(34);
u2.setMobile("13347882345");
u2.setSex(1);
users.add(u1);
users.add(u2);
userInfoService.insertBatch(users);
}
}
4、加載資源檔案
//通過重寫配置方法覆寫
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/mapper/**").addResourceLocations("classpath:/mapper/");//mapper.xml
registry.addResourceHandler("/**")
.addResourceLocations("classpath:/static/")
.addResourceLocations("classpath:/templates/")
.addResourceLocations("classpath:/META-INF/resources/"); //swagger2頁面;
super.addResourceHandlers(registry);
}
.addResourceLocations("classpath:/META-INF/resources/"); //swagger2頁面;
這個要加上否則頁面出不來,報404錯誤!
5、啟動
package com.zhouzy.ssm;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@MapperScan("com.zhouzy.ssm.mapper") //掃描的mapper
@SpringBootApplication
@EnableWebMvc
@EnableAspectJAutoProxy(exposeProxy=true)
public class Webapplication {
public static void main(String[] args) {
SpringApplication.run(Webapplication.class, args);
}
}