首页
学习
活动
专区
圈层
工具
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

项目大升级,在SpringBoot3.4.3使用SpringDoc取代springfox-swagger,调整的代码不止一点点

写接口文档是件苦力活,之前使用 springfox-swagger 框架来生成接口文档。Springfox 是早期基于 Swagger 2 的开源工具,通过解析 Spring 注解生成 API 文档,曾广泛用于 Spring Boot 项目。但随着 OpenAPI 规范的发展,Springfox 逐渐停止维护,且与 Spring Boot 2.6.x+ 版本存在兼容性问题。

Springdoc 是基于 OpenAPI 3 规范设计的现代化工具,完全兼容 Spring Boot 2.x 和 3.x,支持最新的 Spring 功能(如响应式编程),并内置 Swagger UI 和 ReDoc,无需额外配置。

一、什么是SpringDoc

上面所说的 Springdoc 就是 springdoc-openapi-starter-webmvc-ui 框架,它是 Springdoc OpenAPI 提供的一个 Starter 依赖,它为 Spring Boot 项目提供了 OpenAPI 规范支持,完美支持 Spring Boot 3.x 和 Jakarta EE 9+。它主要优势如下:

自动生成:根据控制器自动生成 OpenAPI 文档

实时预览:内置 Swagger UI 界面

注解支持:丰富的注解系统用于增强文档

响应式支持:兼容 WebFlux 项目

模块化设计:可按需引入不同功能模块

相比 springfox-swagger 框架,它多了响应式支持和模块化设计,或许还有其他功能特性。

二、SpringDoc快速上手,简单应用

1、在pom.xml中添加依赖

 <groupId>org.springdoc</groupId>

 <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>

  <version>2.8.6</version>

springfox-swagger 的使用需要引入三个框架,相比之下 SpringDoc 只需引入一个框架。

2、在application.properties增加配置

# 开启 swagger-ui 文档展示

springdoc.swagger-ui.enabled=true

# UI访问路径

springdoc.swagger-ui.path=/swagger-ui.html

# 标签排序方式

springdoc.swagger-ui.tags-sorter=alpha

# 操作排序方式

springdoc.swagger-ui.operations-sorter=alpha

# 开启 OpenAPI 展示

springdoc.api-docs.enabled=true

# OpenAPI JSON路径

springdoc.api-docs.path=/v3/api-docs

springdoc.default-consumes-media-type=application/json

springdoc.default-produces-media-type=application/json

# 关闭文档缓存

springdoc.cache.disabled=false

# 显示actuator端点

springdoc.show-actuator=true

# 推荐保持默认,显示结构化参数

# springdoc.default-flat-param-object=true

# 允许在文档中展示 Spring MVC 的 ModelAndView 返回类型

springdoc.model-and-view-allowed=true

# 推荐关闭以确保文档精确性

springdoc.override-with-generic-response=false

以上配置根据需要添加。简单一点,只需要头两个配置就够了。

到这一步,我们就可以启动项目访问 swagger-ui.html 页面了,相关的接口即使没有任何注解也能生成接口文档。

但是呢,仅仅到这一步还不够,我还想把接口文档整的更有仪式感一些。

3、配置文件

通过配置文件设置接口文档的脸面。

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import io.swagger.v3.oas.models.ExternalDocumentation;

import io.swagger.v3.oas.models.OpenAPI;

import io.swagger.v3.oas.models.info.Contact;

import io.swagger.v3.oas.models.info.Info;

import io.swagger.v3.oas.models.security.SecurityRequirement;

/**

*

* @Profile("!prod") 开发环境配置

* @Profile("prod") 生成环境配置

*/

@Configuration

publicclassOpenApiConfig{

@Bean

OpenAPI customOpenAPI(){

return new OpenAPI()

              .info(new Info()

                      .title("接口API")

                      .version("1.0")

                      .description("接口API文档")

                      .contact(new Contact()

                              .name("技术支持")

                              .url("https://example.com")

                              .email("support@example.com")))

              .externalDocs(new ExternalDocumentation()

                      .description("更多文档")

                      .url("https://docs.example.com"))

              .addSecurityItem(new SecurityRequirement().addList("JWT"));

  }

}

通过这个配置,我们可以给接口文档设置一个有模有样的头部信息。

4、控制层注解应用

增删改查来一套,注解简单用用。

@RestController

@RequestMapping("/api/users")

@Tag(name = "用户管理", description = "用户相关操作API")

publicclassUserController{

/**

* 获取用户列表

* @return

*/

@Operation(summary = "获取用户列表", description = "返回所有用户信息")

@GetMapping

public List<User> getAllUsers(){

  // 实现代码

  List<User> users = new ArrayList<>();

  users.add(new User(10001,"feng","ADMIN"));

   return users;

}

/**

* 新增用户

* @param user

* @return

*/

@PostMapping

public ResponseEntity<User> createUser(@Validated @RequestBody User user){

  // 实现代码

  return new ResponseEntity(user, HttpStatusCode.valueOf(200));

}

/**

* 删除用户

* @param user

* @return

*/

@DeleteMapping

public ResponseEntity<User> delUser(@RequestBody User user){

 // 实现代码

 return new ResponseEntity(user, HttpStatusCode.valueOf(200));

}

/**

* 修改用户

* @param user

* @return

*/

@PutMapping

public ResponseEntity<User> updateUser(@Validated @RequestBody User user){

  // 实现代码

  return new ResponseEntity(user, HttpStatusCode.valueOf(200));

}

/**

* 获取单个用户信息

* @param id

* @return

*/

@GetMapping("/{id}")

@Parameters({

@Parameter(in = ParameterIn.PATH, name = "id", description = "用户uid", required = true)

  })

@Operation(summary = "获取用户信息", description = "通过用户id获取用户信息")

@ApiResponse(responseCode = "200", description = "User found")

@ApiResponse(responseCode = "404", description = "User not found")

public ResponseEntity<User> getUserById(@PathVariable Long id){

  // 实现代码

  return new ResponseEntity(new User(10001,"feng","ADMIN"), HttpStatusCode.valueOf(200));

  }

}

这些是需要展示给客户端的接口文档,增删改查一个不能少。

@Operation:用来描述 API 操作,summary 是简要说明,description 是详细描述。

@ApiResponse:用来描述 API不同响应码的含义,比如 200 表示成功,404 表示未找到用户。

@Validated:对提交的实体类进行验证,验证不通过时返回。

@Parameters:用来描述参数,可以包含多个 @Parameter 参数,in代表参数类型,name代表参数名称,description 代表参数描述,required 代表参数是否必须输入。

5、模型注解应用

import io.swagger.v3.oas.annotations.media.Schema;

import io.swagger.v3.oas.annotations.media.Schema.RequiredMode;

import jakarta.validation.constraints.Email;

import jakarta.validation.constraints.Size;

@Schema(description = "用户实体")

publicclassUser{

@Schema(description = "用户ID", example = "1001")

private Integer id;

@Schema(description = "用户名", example = "john_doe", requiredMode = RequiredMode.REQUIRED)

@Size(min = 3, max = 20, message = "用户名长度必须在3到20个字符之间")

private String username;

@Schema(description = "用户角色", allowableValues = {"ADMIN", "USER", "GUEST"})

private String role;

@Schema(description = "邮箱", example = "john_doe@mail.com")

@Email

private String email;

publicUser(Integer id, @Size(min = 3, max = 20) String username, String role) {

super();

this.id = id;

this.username = username;

this.role = role;

  }  

// get 和 set...

}

6、环绕通知全局捕捉验证异常

import java.util.stream.Collectors;

import org.springframework.http.HttpStatus;

import org.springframework.http.ResponseEntity;

import org.springframework.validation.BindException;

import org.springframework.web.bind.annotation.ExceptionHandler;

import org.springframework.web.bind.annotation.RestControllerAdvice;

/**

* Controller 环绕通知

*/

@RestControllerAdvice

publicclassGlobalExceptionHandler{

@ExceptionHandler(BindException.class)

public ResponseEntity<String> handleBindException(BindException ex){

  // 提取校验错误信息并返回

  String errorMessage = ex.getBindingResult().getAllErrors()

  .stream()

  .map(error -> error.getDefaultMessage())

  .collect(Collectors.joining(", "));

return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("校验失败: " + errorMessage);

  }

}

这个环绕通知,还可以进一步优化,比如返回json格式的数据。

7、访问 Swagger UI

启动 Spring Boot 应用程序后,可以通过浏览器查看Swagger UI

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

查看 OpenAPI JSON

http://localhost:8101/v3/api-docs

初始效果图和springfox-swagger很像。

1)新增用户,确认验证方法的有效性

故意输入一位的用户名,数据被拦截,返回错误信息。这里的返回还可以再优化。

2)查看 Schema

客户端通过Schema查看要提交数据的每种参数限制。

到这里就算简单入门了。

三、与springfox-swagger的注解对比

Swagger UI 的一些注解上可以用OpenAPI 中的注解对等替换:

官网地址:https://springdoc.org/

如果是从 springfox-swagger 的使用迁移到SpringDoc,修改有点多,改动有点大,需要对照这个清单一路改过去,辛苦。即使是全局替换,也需要做一个上午的工作量,牛马的生活逃不掉!

四、最后总结

通过上面的操作,算是SpringDoc 使用入门了。

springdoc-openapi-starter-webmvc-api 的功能还是非常强大的,它集成了swagger-ui、spring-boot-starter-security、spring-boot-starter-actuator 等多个框架。

通过包含的依赖,可以发现还有更高级的功能,比如通过权限进行限制接口的访问、模块化访问等等功能等有空了再去探讨。

希望本文对你有所帮助。

  • 发表于:
  • 原文链接https://page.om.qq.com/page/OZ76aQAj6W_ZdcMkk-IEropQ0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券