SpringBoot開發詳解(八) -- 使用Swagger2構建API文檔

原文鏈接:http://blog.csdn.net/qq_31001665

如有侵權,請聯繫博主刪除博客,謝謝

API文檔

文檔在開發中的價值與作用:

作爲一個開發人員,平時看得最多的恐怕就是各式各樣的文檔了。並且在開發中我們也避免不了的需要自己去書寫文檔,比如作爲後臺開發人員,我們書寫最多的應該就是接口文檔了。前端人員會按照我們給出的文檔來進行前端開發,並且按照文檔細節來構建不同的傳輸協議,對象定義,字段解析等等。

我曾長時間的使用EXCEl來書寫接口文檔,可是逐漸的也暴露出一些問題:

  • 接口過多,每一個接口需要一個入參定義以及出參定義,不同的請求類型。書寫過多,浪費時間。
  • 輸出參數類型定義與文檔不符,前端外無法解析,耗費時間。
  • 接口修改需要同步修改文檔,重複工作。
  • 多人開發文檔常常造成衝突。

爲了解決以上所描述的問題,我們引入了Swagger2,它可以減少我們書寫文檔的工作量,並且可以保持代碼與文檔的一致性。同時,可以通過頁面測試來直接挑事接口。說了這麼多的好處,我們來看看我們我們應該如何在SpringBoot中如何使用Swagger2吧。

這裏寫圖片描述

這樣的文檔是不是看起來很簡單明瞭呢。

引入Swagger2依賴:

<!--swagger2依賴,構建API文檔-->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.2.2</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.2.2</version>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

在引入Swagger2的依賴後,我們需要創建一個配置類。這個配置類應該是和你的啓動類是同級的,這裏,我直接在啓動類中進行代碼書寫了(就是這麼懶……)

/**
 * 啓動類
 */
@RequestMapping(value = "/")
@RestController
@SpringBootApplication
@MapperScan(basePackages = "com.zzp.dao")
@Configuration
@EnableSwagger2
public class Round1Application {

    @RequestMapping(value = "/",method = RequestMethod.GET)
    public String helloWorld(){
        return "Hello World";
    }
    public static void main(String[] args) {
        SpringApplication.run(Round1Application.class, args);
    }


    @Bean
    public Docket createApi(){
        return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select()
                .apis(RequestHandlerSelectors.basePackage("com.zzp.controller"))
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo apiInfo(){
        return new ApiInfoBuilder()
                .title("API文檔")
                .description("API使用即參數定義")
                .termsOfServiceUrl("http://blog.csdn.net/qq_31001665")
                .contact("ZZP")
                .version("0.1")
                .build();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

我們通過@Configuration註解,讓Spring啓動時加載配置,通過@EnableSwagger2開啓Swagger。話說一般開慶某個功能都是@EnableXXX的。

apiInfo中的內容是文檔的一些基本配置信息,而createApi中則是確定掃面哪些包下的接口形成文檔,以及文檔展示哪些信息。注意這裏是一個Docket的bean。

完成配置類的書寫後我們已經可以直接訪問我們的文檔了,啓動項目,訪問

http://localhost:9090/swagger-ui.html

是不是看見如下內容了呢:

這裏寫圖片描述

沒錯這就是我們的四個controller,每個點擊開來就可以看到我們的每一個接口了。不過沒有中文註釋的接口始終對於用戶不太友好,我們接下來的工作就是給每一個接口添加註釋。這裏我們使用@ApiOperation註解來註釋我們接口的一些基本信息,使用@ApiImplicitParams,@ApiImplicitParam註解來註釋我們的入參信息。

@RequestMapping("/user")
@RestController
public class UserController {

    @Autowired
    private UserService userService;

    /**
     * 添加用戶
     * @param tel 註冊手機號
     * @param pwd 設置密碼
     */
    @ApiOperation(value = "創建用戶",notes = "使用手機以及密碼初始化用戶信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "tel",value = "用戶手機號",required = true,dataType = "String"),
            @ApiImplicitParam(name = "pwd",value = "用戶初始密碼",required = true,dataType = "String")
    })
    @PostMapping("/createUser")
    public void createUser(@RequestParam("tel") String tel, @RequestParam("pwd") String pwd){
        userService.createUser(tel,pwd);
    }

    /**
     * 添加用戶2
     * @param userInfo
     * @Valid添加表單驗證,BindingResult獲取驗證結果
     */
    @ApiOperation(value = "創建用戶V2版本",notes = "使用UserInfo對象初始化用戶信息")
    @ApiImplicitParam(name = "userInfo",value = "用戶對象",required = true,dataType = "UserInfo")
    @PostMapping("/createUser2")
    public String createUser2(@Valid UserInfo userInfo, BindingResult bindingResult){
        if (bindingResult.hasErrors()){
            return bindingResult.getFieldError().getDefaultMessage();
        }
        userService.createUser(userInfo.getTel(),userInfo.getPassWord());
        return "OK";
    }

    /**
     * 更新用戶信息
     * @param user_id 用戶ID
     * @param nickName 暱稱
     */
    @PutMapping("/updateUser/{id}")
    public void updateUser(@PathVariable("id") String user_id, @RequestParam("nickName") String nickName){
        userService.updateUser(user_id,nickName);
    }

    /**
     * 獲取用戶信息
     * @param id 用戶Id
     * @return
     */
    @GetMapping("/getUser/{id}")
    public UserInfo getUser(@PathVariable("id")  Integer id){
        return userService.getUser(id);
    }

    /**
     * 刪除用戶
     * @param id
     */
    @DeleteMapping("/deleteUserByUserId/{id}")
    public void deleteUserByUserId(@PathVariable("id")  Integer id){
        userService.deleteUserByUserId(id);
    }

    /**
     * 使用@RequestBody獲取參數,用map類型接收,再取出
     * @param reqMap
     */
    @PostMapping("/createUserByMap")
    public void createUserByMap(@RequestBody Map<String,Object> reqMap){
        String tel = reqMap.get("tel").toString();
        String pwd = reqMap.get("pwd").toString();
        userService.createUser(tel,pwd);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
@RestController
@RequestMapping("/xml")
public class XMLController {

    @Autowired
    private XMLService service;

    @Autowired
    private ExceptionHandle handle;

    /**
     * 更新用戶信息
     * @param user_id 用戶ID
     * @param nickName 暱稱
     */
    @ApiOperation(value = "更新用戶信息",notes = "更新用戶暱稱")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id",value = "用戶id",required = true,dataType = "String"),
            @ApiImplicitParam(name = "nickName",value = "用戶暱稱",required = true,dataType = "String")
    })
    @PutMapping("/updateUser/{id}")
    public Result updateUser(@PathVariable("id") String user_id, @RequestParam("nickName") String nickName){
        Result result = ResultUtil.success();
        try {
            service.updateUser(user_id,nickName);
        }catch (Exception e){
            result = handle.exceptionGet(e);
        }
        return result;
//        service.updateUser(user_id,nickName);
    }

    /**
     * 獲取用戶信息
     * @param id 用戶Id
     * @return
     */
    @ApiOperation(value = "獲取用戶信息",notes = "返回用戶信息")
    @ApiImplicitParam(name = "id",value = "用戶id",required = true,dataType = "Integer",paramType = "path")
    @GetMapping("/getUser/{id}")
    public Result getUser(@PathVariable("id")  Integer id){
        Result result = ResultUtil.success();
        try {
            result.setData(service.getUser(id));
        }catch (Exception e){
            result = handle.exceptionGet(e);
        }
        return result;
//        return service.getUser(id);
    }

    /**
     * 刪除用戶
     * @param tel
     */
    @ApiOperation(value = "刪除用戶",notes = "根據用戶id刪除用戶")
    @ApiImplicitParam(name = "id",value = "用戶id",required = true,dataType = "Integer")
    @DeleteMapping("/deleteUserByUserId/{tel}")
    public Result deleteUserByUserId(@PathVariable("tel")  String tel){
        Result result = ResultUtil.success();
        try {
            UserInfo user  = new UserInfo();
            user.setTel(tel);
            service.deleteUserByUserId(user);
        }catch (Exception e){
            result = handle.exceptionGet(e);
        }
        return result;
//        UserInfo user  = new UserInfo();
//        user.setTel(tel);
//        service.deleteUserByUserId(user);
    }

    /**
     * 使用@RequestBody獲取參數,用map類型接收,再取出
     * @param reqMap
     */
    @ApiOperation(value = "創建用戶V3版本",notes = "返回用戶信息")
    @ApiImplicitParam(name = "Map",value = "map集合",required = true,dataType = "Map")
    @PostMapping("/createUserByMap")
    public Result createUserByMap(@RequestBody Map<String,Object> reqMap){
        Result result = ResultUtil.success();
        try {
            service.createUser(reqMap);
        }catch (Exception e){
            result = handle.exceptionGet(e);
        }
        return result;
//        service.createUser(reqMap);
    }


}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93

這裏我給兩個controller都加入了直接配置,因爲在使用mybatis後,spring會默認使用mybatis配置,jdbc鏈接數據庫會報錯:Invalid bound statement (not found): com.zzp.dao.UserInfoMapper.getUser。大家在做項目時,一定要使用一種方法來鏈接數據庫,不然各種錯誤會一直困擾着你。

我們完成上訴代碼的添加後就可以在剛纔的地址中看到我們配置的接口信息了

這裏寫圖片描述

並且我們可以點擊 Try it out!來測試我們的接口了。我們這裏使用Get方法來獲取用戶信息的接口測試一下,發現我們已經獲取了用戶信息,要注意的是如果你也是直接通過URL路徑中獲取參數,那需要添加paramType = “path”這個參數,不然是無法獲取到id值的。

這裏寫圖片描述

Swagger2寫在最後的話:

相比較之前我們使用EXCEl來書寫接口文檔,Swagger2的確方便了許多,並且書寫量也大大減少,看似使用Swagger2來對API文檔進行管理是一個不錯的選擇。其實不然(逃),因爲Swagger2對於代碼的污染和侵入性我認爲太大了。並且你應該也發現了,當你使用Map作爲參數時,Swagger2很難對Map內的每一個參數進行說明(你可以寫超多文字描述)。所以在實際開發中,Swagger2的使用並不是很多,如果你是個人開發者,那使用簡單的Swagger2的確可以滿足需求。如果你構建的是龐大的接口系統時。我的建議是使用Swagger2和MarkDown配合完成文檔的書寫。MarkDown書寫方便高效,語法簡單,是我們值得學習的。而Swagger2提供接口調試以及字段名匹配來保證入參與出參的一致性。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章