Java Spring Boot 集成 Swagger 生成 API文档(SpringDoc)

发布时间 2023-12-18 14:31:19作者: 进击的davis

在我们进行项目开发的时候,有些文档是必不可少的,或者也有利于自己查阅,比如 API接口文档。

在 Spring Boot 中通常有有个选择:

  • springfox
  • springdoc

因为 springfox和 Spring Boot 版本适配问题是个坑,这里我们选用更加友好的 springDoc,而且用起来更顺手,很丝滑。

以下是环境:

  • Spring Boot:3.1.6
  • JDK:17

依赖

以下项目中用到的依赖:

<!--   swagger     -->
<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
    <version>2.0.2</version>
</dependency>

<!--  lombok for class    -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.30</version>
</dependency>

<!--  params validate -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

配置

我们在项目中应用也很简单,首先配置 swagger:

package com.example.swaggerdemo;

import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class OpenApiConfig {

    @Bean
    public OpenAPI springOpenAPI() {
        return new OpenAPI().info(new Info() //
                .title("SpringDoc API Demo") //
                .description("SpringDoc Simple Application Demo") //
                .version("1.0.0"));
    }
}

另外我们对 swagger文档 开启和访问的uri做些配置,见于applicaiton.yaml:

springdoc:
  api-docs:
    # default: /v3/api-docs
    path: /api-docs
  swagger-ui:
    # 访问路径
    path: swagger-ui-custom.html
    # 是否开启 非prod -> true, prod -> false
    enabled: true

接下来我们为后面的文档做些准备工作。

统一的响应结构

枚举类

package com.example.swaggerdemo;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public enum RespEnums {
    SUCCESS(0, "Success"),
    FAIL(1, "Operation failed.");

    private Integer code;

    private String msg;
}

统一响应体

package com.example.swaggerdemo;

import lombok.Data;

@Data
public class RespInfo<T> {
    private Integer code;

    private String msg;

    private T data;

    /**
     * 全参方法
     * @param code
     * @param msg
     * @param data
     * @param <T>
     * @return
     */
    private static <T> RespInfo<T> response(int code, String msg, T data) {
        RespInfo<T> respInfo = new RespInfo<>();
        respInfo.setCode(code);
        respInfo.setMsg(msg);
        respInfo.setData(data);

        return respInfo;
    }

    /**
     * 缺失data方法
     * @param code
     * @param msg
     * @param <T>
     * @return
     */
    private static <T> RespInfo<T> response(int code, String msg) {
        RespInfo<T> respInfo = new RespInfo<>();
        respInfo.setCode(code);
        respInfo.setMsg(msg);

        return respInfo;
    }

    public static <T> RespInfo<T> success() {
        return response(RespEnums.SUCCESS.getCode(), RespEnums.SUCCESS.getMsg());
    }

    public static <T> RespInfo<T> success(T data) {
        return response(RespEnums.SUCCESS.getCode(), RespEnums.SUCCESS.getMsg(), data);
    }

    public static <T> RespInfo<T> fail() {
        return response(RespEnums.FAIL.getCode(), RespEnums.FAIL.getMsg());
    }

    public static <T> RespInfo<T> fail(int code, String msg) {
        return response(code, msg);
    }

    public static <T> RespInfo<T> fail(int code, String msg, T data) {
        return response(code, msg, data);
    }

}

由于我们以用户信息为示例,这里构建个 user bean:

package com.example.swaggerdemo;

import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Data;

@Data
public class User {
    @Min(value = 1000)
    private Integer id;

    @NotBlank(message = "name not null.")
    @Size(min = 3, max = 20, message = "name's length should be 3 ~ 20.")
    private String name;

    @Min(value = 18, message = "should be adult.")
    @Max(value = 100, message = "should in rational range.")
    private Integer age;
}

接下来编写我们的控制器类。

控制器类

登陆控制器类

package com.example.swaggerdemo;

import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Tag(name = "认证管理接口",description = "登陆登出接口")
@RequestMapping("/auth")
public class AuthController {

    @PostMapping("/login")
    public RespInfo login() {
        return RespInfo.success();
    }

    @DeleteMapping("/logout")
    public RespInfo logout() {
        return RespInfo.success();
    }
}

用户管理类

package com.example.swaggerdemo;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.*;

@RestController
@Tag(name = "用户信息管理接口", description = "用户信息管理的增删改查")
@RequestMapping("/user")
public class UserController {

    @GetMapping("/getInfo/{id}")
    @Operation(method = "GET", summary = "获取用户信息")
    @ApiResponses(value = { // 输出不同的结果响应
            @ApiResponse(responseCode = "200", description = "Found the user", content = {
                    @Content(mediaType = "application/json", schema = @Schema(implementation = RespInfo.class))
            }),
            @ApiResponse(responseCode = "404", description = "User not found", content = @Content)
    })
    public RespInfo<User> getUserInfo(@PathVariable(name = "id", required = true) final int id) {
        User user = new User();
        user.setId(id);
        user.setName("alice");
        return RespInfo.success(user);
    }

    @PostMapping("/adduser")
    @Operation(method = "POST", summary = "添加用户信息")
    public RespInfo addUser(@RequestBody User user) {
        return RespInfo.success();
    }

    @PostMapping("/updateInfo")
    @Operation(method = "POST", summary = "更改用户信息")
    public RespInfo updateInfo(@RequestBody User user) {
        return RespInfo.success();
    }

    @DeleteMapping("/deleteInfo")
    @Operation(method = "DELETE", summary = "删除用户信息")
    public RespInfo deleteInfo(@RequestBody User user) {
        return RespInfo.success();
    }
}

测试结构

这些工作结束后,运行程序,通过 http://localhost:8080/swagger-ui/index.html 就可以访问 API文档了:

image.png

每个接口信息:

image.png

响应体结构:

image.png

参考: