SpringBoot官宣推出API工具SpringDoc,功能强大!这是不给Swagger活路了!

本文主要是介绍SpringBoot官宣推出API工具SpringDoc,功能强大!这是不给Swagger活路了!,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

大家好,我是老赵

之前在SpringBoot项目中一直使用的是SpringFox提供的Swagger库,上了下官网发现已经有接近两年没出新版本了!前几天升级了SpringBoot 2.6.x 版本,发现这个库的兼容性也越来越不好了,有的常用注解属性被废弃了居然都没提供替代!无意中发现了另一款Swagger库SpringDoc,试用了一下非常不错,推荐给大家!

SpringDoc简介

SpringDoc是一款可以结合SpringBoot使用的API文档生成工具,基于OpenAPI 3,目前在Github上已有1.7K+Star,更新发版还是挺勤快的,是一款更好用的Swagger库!值得一提的是SpringDoc不仅支持Spring WebMvc项目,还可以支持Spring WebFlux项目,甚至Spring Rest和Spring Native项目,总之非常强大,下面是一张SpringDoc的架构图。

d4b995fb5113b2d89ceb1b6961f1f4f9.png

使用

接下来我们介绍下SpringDoc的使用,使用的是之前集成SpringFox的mall-tiny-swagger项目,我将把它改造成使用SpringDoc。

集成

首先我们得集成SpringDoc,在pom.xml中添加它的依赖即可,开箱即用,无需任何配置。

<!--springdoc 官方Starter-->
<dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-ui</artifactId><version>1.6.6</version>
</dependency>

从SpringFox迁移

  • 我们先来看下经常使用的Swagger注解,看看SpringFox的和SpringDoc的有啥区别,毕竟对比已学过的技术能该快掌握新技术;

SpringFoxSpringDoc
@Api@Tag
@ApiIgnore@Parameter(hidden = true)or@Operation(hidden = true)or@Hidden
@ApiImplicitParam@Parameter
@ApiImplicitParams@Parameters
@ApiModel@Schema
@ApiModelProperty@Schema
@ApiOperation(value = "foo", notes = "bar")@Operation(summary = "foo", description = "bar")
@ApiParam@Parameter
@ApiResponse(code = 404, message = "foo")ApiResponse(responseCode = "404", description = "foo")
  • 接下来我们对之前Controller中使用的注解进行改造,对照上表即可,之前在@Api注解中被废弃了好久又没有替代的description属性终于被支持了!

/*** 品牌管理Controller* Created by macro on 2019/4/19.*/
@Tag(name = "PmsBrandController", description = "商品品牌管理")
@Controller
@RequestMapping("/brand")
public class PmsBrandController {@Autowiredprivate PmsBrandService brandService;private static final Logger LOGGER = LoggerFactory.getLogger(PmsBrandController.class);@Operation(summary = "获取所有品牌列表",description = "需要登录后访问")@RequestMapping(value = "listAll", method = RequestMethod.GET)@ResponseBodypublic CommonResult<List<PmsBrand>> getBrandList() {return CommonResult.success(brandService.listAllBrand());}@Operation(summary = "添加品牌")@RequestMapping(value = "/create", method = RequestMethod.POST)@ResponseBody@PreAuthorize("hasRole('ADMIN')")public CommonResult createBrand(@RequestBody PmsBrand pmsBrand) {CommonResult commonResult;int count = brandService.createBrand(pmsBrand);if (count == 1) {commonResult = CommonResult.success(pmsBrand);LOGGER.debug("createBrand success:{}", pmsBrand);} else {commonResult = CommonResult.failed("操作失败");LOGGER.debug("createBrand failed:{}", pmsBrand);}return commonResult;}@Operation(summary = "更新指定id品牌信息")@RequestMapping(value = "/update/{id}", method = RequestMethod.POST)@ResponseBody@PreAuthorize("hasRole('ADMIN')")public CommonResult updateBrand(@PathVariable("id") Long id, @RequestBody PmsBrand pmsBrandDto, BindingResult result) {CommonResult commonResult;int count = brandService.updateBrand(id, pmsBrandDto);if (count == 1) {commonResult = CommonResult.success(pmsBrandDto);LOGGER.debug("updateBrand success:{}", pmsBrandDto);} else {commonResult = CommonResult.failed("操作失败");LOGGER.debug("updateBrand failed:{}", pmsBrandDto);}return commonResult;}@Operation(summary = "删除指定id的品牌")@RequestMapping(value = "/delete/{id}", method = RequestMethod.GET)@ResponseBody@PreAuthorize("hasRole('ADMIN')")public CommonResult deleteBrand(@PathVariable("id") Long id) {int count = brandService.deleteBrand(id);if (count == 1) {LOGGER.debug("deleteBrand success :id={}", id);return CommonResult.success(null);} else {LOGGER.debug("deleteBrand failed :id={}", id);return CommonResult.failed("操作失败");}}@Operation(summary = "分页查询品牌列表")@RequestMapping(value = "/list", method = RequestMethod.GET)@ResponseBody@PreAuthorize("hasRole('ADMIN')")public CommonResult<CommonPage<PmsBrand>> listBrand(@RequestParam(value = "pageNum", defaultValue = "1")@Parameter(description = "页码") Integer pageNum,@RequestParam(value = "pageSize", defaultValue = "3")@Parameter(description = "每页数量") Integer pageSize) {List<PmsBrand> brandList = brandService.listBrand(pageNum, pageSize);return CommonResult.success(CommonPage.restPage(brandList));}@Operation(summary = "获取指定id的品牌详情")@RequestMapping(value = "/{id}", method = RequestMethod.GET)@ResponseBody@PreAuthorize("hasRole('ADMIN')")public CommonResult<PmsBrand> brand(@PathVariable("id") Long id) {return CommonResult.success(brandService.getBrand(id));}
}
  • 接下来进行SpringDoc的配置,使用OpenAPI来配置基础的文档信息,通过GroupedOpenApi配置分组的API文档,SpringDoc支持直接使用接口路径进行配置。

/*** SpringDoc API文档相关配置* Created by macro on 2022/3/4.*/
@Configuration
public class SpringDocConfig {@Beanpublic OpenAPI mallTinyOpenAPI() {return new OpenAPI().info(new Info().title("Mall-Tiny API").description("SpringDoc API 演示").version("v1.0.0").license(new License().name("Apache 2.0").url("https://github.com/macrozheng/mall-learning"))).externalDocs(new ExternalDocumentation().description("SpringBoot实战电商项目mall(50K+Star)全套文档").url("http://www.macrozheng.com"));}@Beanpublic GroupedOpenApi publicApi() {return GroupedOpenApi.builder().group("brand").pathsToMatch("/brand/**").build();}@Beanpublic GroupedOpenApi adminApi() {return GroupedOpenApi.builder().group("admin").pathsToMatch("/admin/**").build();}
}

结合SpringSecurity使用

  • 由于我们的项目集成了SpringSecurity,需要通过JWT认证头进行访问,我们还需配置好SpringDoc的白名单路径,主要是Swagger的资源路径;

/*** SpringSecurity的配置* Created by macro on 2018/4/26.*/
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {                                              @Overrideprotected void configure(HttpSecurity httpSecurity) throws Exception {httpSecurity.csrf()// 由于使用的是JWT,我们这里不需要csrf.disable().sessionManagement()// 基于token,所以不需要session.sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests().antMatchers(HttpMethod.GET, // Swagger的资源路径需要允许访问"/",   "/swagger-ui.html","/swagger-ui/","/*.html","/favicon.ico","/**/*.html","/**/*.css","/**/*.js","/swagger-resources/**","/v3/api-docs/**").permitAll().antMatchers("/admin/login")// 对登录注册要允许匿名访问.permitAll().antMatchers(HttpMethod.OPTIONS)//跨域请求会先进行一次options请求.permitAll().anyRequest()// 除上面外的所有请求全部需要鉴权认证.authenticated();}}
  • 然后在OpenAPI对象中通过addSecurityItem方法和SecurityScheme对象,启用基于JWT的认证功能。

/*** SpringDoc API文档相关配置* Created by macro on 2022/3/4.*/
@Configuration
public class SpringDocConfig {private static final String SECURITY_SCHEME_NAME = "BearerAuth";@Beanpublic OpenAPI mallTinyOpenAPI() {return new OpenAPI().info(new Info().title("Mall-Tiny API").description("SpringDoc API 演示").version("v1.0.0").license(new License().name("Apache 2.0").url("https://github.com/macrozheng/mall-learning"))).externalDocs(new ExternalDocumentation().description("SpringBoot实战电商项目mall(50K+Star)全套文档").url("http://www.macrozheng.com")).addSecurityItem(new SecurityRequirement().addList(SECURITY_SCHEME_NAME)).components(new Components().addSecuritySchemes(SECURITY_SCHEME_NAME,new SecurityScheme().name(SECURITY_SCHEME_NAME).type(SecurityScheme.Type.HTTP).scheme("bearer").bearerFormat("JWT")));}
}

测试

  • 接下来启动项目就可以访问Swagger界面了,访问地址:http://localhost:8088/swagger-ui.html

c27a947d7a65e1150c3bd00d580623d0.png
  • 我们先通过登录接口进行登录,可以发现这个版本的Swagger返回结果是支持高亮显示的,版本明显比SpringFox来的新;

25871c8c7bb1de588c7355f972198b17.png
  • 然后通过认证按钮输入获取到的认证头信息,注意这里不用加bearer前缀;

41c6d38ee7b93fa22abbd62116fe0b46.png
  • 之后我们就可以愉快地访问需要登录认证的接口了;

4654c007294aa75a1b9344215783af5e.png
  • 看一眼请求参数的文档说明,还是熟悉的Swagger样式!

57d8a1073625930fb2a7b9e5374d5dbd.png

常用配置

SpringDoc还有一些常用的配置可以了解下,更多配置可以参考官方文档。

springdoc:swagger-ui:# 修改Swagger UI路径path: /swagger-ui.html# 开启Swagger UI界面enabled: trueapi-docs:# 修改api-docs路径path: /v3/api-docs# 开启api-docsenabled: true# 配置需要生成接口文档的扫描包packages-to-scan: com.macro.mall.tiny.controller# 配置需要生成接口文档的接口路径paths-to-match: /brand/**,/admin/**

总结

在SpringFox的Swagger库好久不出新版的情况下,迁移到SpringDoc确实是一个更好的选择。今天体验了一把SpringDoc,确实很好用,和之前熟悉的用法差不多,学习成本极低。而且SpringDoc能支持WebFlux之类的项目,功能也更加强大,使用SpringFox有点卡手的朋友可以迁移到它试试!

参考资料

  • 项目地址:https://github.com/springdoc/springdoc-openapi

  • 官方文档:https://springdoc.org/

 

精彩推荐

1.最适合晚上睡不着看的 8 个网站,建议收藏哦
2.注解+反射优雅的实现Excel导入导出(通用版),飘了!
3.华为Java开发编程最新军规,谁违反谁滚蛋!
4.45 个 Git 经典操作场景,专治不会合代码
5.华为Java开发编程最新军规,谁违反谁滚蛋!
6.还在使用TIMESTAMP 作为日期字段?你们的服务器没崩?
7.这几行代码,真的骚!
8.尽快卸载这两款恶意浏览器插件!已有近 50 万用户安装

27b52132178c4c2d04c8175d80c3e762.png

这篇关于SpringBoot官宣推出API工具SpringDoc,功能强大!这是不给Swagger活路了!的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/205695

相关文章

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

Java判断多个时间段是否重合的方法小结

《Java判断多个时间段是否重合的方法小结》这篇文章主要为大家详细介绍了Java中判断多个时间段是否重合的方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录判断多个时间段是否有间隔判断时间段集合是否与某时间段重合判断多个时间段是否有间隔实体类内容public class D

IDEA编译报错“java: 常量字符串过长”的原因及解决方法

《IDEA编译报错“java:常量字符串过长”的原因及解决方法》今天在开发过程中,由于尝试将一个文件的Base64字符串设置为常量,结果导致IDEA编译的时候出现了如下报错java:常量字符串过长,... 目录一、问题描述二、问题原因2.1 理论角度2.2 源码角度三、解决方案解决方案①:StringBui

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在

Java中ArrayList和LinkedList有什么区别举例详解

《Java中ArrayList和LinkedList有什么区别举例详解》:本文主要介绍Java中ArrayList和LinkedList区别的相关资料,包括数据结构特性、核心操作性能、内存与GC影... 目录一、底层数据结构二、核心操作性能对比三、内存与 GC 影响四、扩容机制五、线程安全与并发方案六、工程

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.

Spring AI集成DeepSeek的详细步骤

《SpringAI集成DeepSeek的详细步骤》DeepSeek作为一款卓越的国产AI模型,越来越多的公司考虑在自己的应用中集成,对于Java应用来说,我们可以借助SpringAI集成DeepSe... 目录DeepSeek 介绍Spring AI 是什么?1、环境准备2、构建项目2.1、pom依赖2.2