当前位置: 首页 > 后端技术 > Java

神器SpringDoc诞生!最适合SpringBoot的API文档工具来了!

时间:2023-04-01 22:41:43 Java

之前在SpringBoot项目中使用了SpringFox提供的Swagger库。去官网发现已经快两年没有新版本了!前几天升级了SpringBoot2.6.x版本,发现这个库的兼容性越来越差了。一些常用的注解属性已经被废弃,没有替代品!无意中发现了另一个Swagger库SpringDoc,试用了一下,非常不错,推荐给大家!SpringBoot实战电商项目商城(50k+star)地址:https://github.com/macrozheng/mallSpringDoc介绍SpringDoc是一个API文档生成工具,可以与SpringBoot配合使用。它基于OpenAPI3,目前在Github上有1.7。K+Star,更新版本还是很用心的,是一个更好的Swagger库!值得一提的是,SpringDoc不仅支持SpringWebMvc项目,还支持SpringWebFlux项目,甚至SpringRest和SpringNative项目。简而言之,它非常强大。下面是一张SpringDoc架构图。使用接下来介绍一下SpringDoc的使用,使用之前集成SpringFox的mall-tiny-swagger项目,我将改造为使用SpringDoc。集成首先我们要集成SpringDoc,只需在pom.xml中添加它的依赖,它开箱即用,无需任何配置。org.springdocspringdoc-openapi-ui1.6.6from对于SpringFox的迁移,我们先看看常用的Swagger注解,看看SpringFox和SpringDoc的区别。毕竟,与我们所学的技术相比,我们可以快速掌握新技术;SpringFoxSpringDoc@Api@Tag@ApiIgnore@Parameter(hidden=true)或@Operation(hidden=true)或@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属性终于被支持了!/***品牌管理控制器*宏创建于2019/4/19。*/@Tag(name="PmsBrandController",description="产品品牌管理")@Controller@RequestMapping("/brand")public类PmsBrandController{@AutowiredprivatePmsBrandServicebrandService;privatestaticfinalLoggerLOGGER=LoggerFactory.getLogger(PmsBrandController.class);@Operation(summary="获取所有品牌列表",description="需要登录后访问")@RequestMapping(value="listAll",method=RequestMethod.GET)@ResponseBodypublicCommonResult>getBrandList(){返回CommonResult.success(brandService.listAllBrand());}@Operation(summary="添加品牌")@RequestMapping(value="/create",method=RequestMethod.POST)@ResponseBody@PreAuthorize("hasRole('ADMIN')")publicCommonResultcreateBrand(@RequestBodyPmsBrandpmsBrand){共同结果共同结果;intcount=brandService.createBrand(pmsBrand);if(count==1){commonResult=CommonResult.success(pmsBrand);LOGGER.debug("创建品牌成功s:{}",pmsBrand);}else{commonResult=CommonResult.failed("操作失败");LOGGER.debug("createBrandfailed:{}",pmsBrand);}returncommonResult;}@Operation(summary="更新指定id品牌信息")@RequestMapping(value="/update/{id}",method=RequestMethod.POST)@ResponseBody@PreAuthorize("hasRole('ADMIN')")publicCommonResultupdateBrand(@PathVariable("id")Longid,@RequestBodyPmsBrandpmsBrandDto,BindingResultresult){CommonResultcommonResult;intcount=brandService.updateBrand(id,pmsBrandDto);if(count==1){commonResult=CommonResult.success(pmsBrandDto);LOGGER.debug("updateBrandsuccess:{}",pmsBrandDto);}else{commonResult=CommonResult.failed("操作失败");LOGGER.debug("updateBrandfailed:{}",pmsBrandDto);}返回共同结果;}@Operation(summary="删除指定id的品牌")@RequestMapping(value="/delete/{id}",method=RequestMethod.GET)@ResponseBody@PreAuthorize("hasRole('ADMIN')")publicCommonResultdeleteBrand(@PathVariable("id")Longid){intcount=brandService.deleteBrand(id);if(count==1){LOGGER.debug("deleteBrand成功:id={}",id);返回CommonResult.success(null);}else{LOGGER.debug("deleteBrand失败:id={}",id);returnCommonResult.failed("操作失败");@Operation(summary="分页查询品牌列表")@RequestMapping(value="/list",method=RequestMethod.GET)@ResponseBody@PreAuthorize("hasRole('ADMIN')")publicCommonResult>listBrand(@RequestParam(value="pageNum",defaultValue="1")@Parameter(description="pagenumber")IntegerpageNum,@RequestParam(value="pageSize",defaultValue="3")@Parameter(description="Numberperpage")IntegerpageSize){ListbrandList=brandService.listBrand(pageNum,pageSize);returnCommonResult.success(CommonPage.restPage(brandList));}@Operation(summary="获取指定id的品牌详情")@RequestMapping(value="/{id}",method=RequestMethod.GET)@ResponseBody@PreAuthorize("hasRole('ADMIN')")publicCommonResultbrand(@PathVariable("id")Longid){returnCommonResult.success(brandService.getBrand(id));}}接下来配置SpringDoc,使用OpenAPI配置文档基础信息,通过GroupedOpenApi配置分组API文档,SpringDoc支持直接使用接口路径配置/***SpringDocAPI文档相关配置*宏创建于2022/3/4。*/@ConfigurationpublicclassSpringDocConfig{@BeanpublicOpenAPImallTinyOpenAPI(){returnnewOpenAPI().info(newInfo().title("Mall-TinyAPI").description("SpringDocAPIDemo").version("v1.0.0").license(newLicense().name("Apache2.0").url("https://github.com/macrozheng/mall-learning"))).externalDocs(newExternalDocumentation().description(《SpringBoot实战电商项目商城(50K+Star)全套文档》).url("http://www.macrozheng.com"));}@BeanpublicGroupedOpenApipublicApi(){returnGroupedOpenApi.builder().group("brand").pathsToMatch("/brand/**").build();}@BeanpublicGroupedOpenApiadminApi(){返回GroupedOpenApi.builder().group("admin").pathsToMatch("/admin/**").build();}}结合SpringSecurity由于我们的项目集成了SpringSecurity,所以需要JWT认证才能访问header,还需要配置SpringDoc的白名单路径,主要是Swagger的资源路径;/***SpringSecurity配置*宏创建于2018/4/26。*/@Configuration@EnableWebSecurity@EnableGlobalMethodSecurity(prePostEnabled=true)publicclassSecurityConfigextendsWebSecurityConfigurerAdapter{@Overrideprotectedvoidconfigure(HttpSecurityhttpSecurity)throwsException{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")//登录允许匿名访问registration.permitAll().antMatchers(HttpMethod.OPTIONS)//跨域请求会先做一个optionsrequest.permitAll().anyRequest()//除上述之外的所有请求所有必需的身份验证authentication.authenticated();}}然后通过OpenAPI对象中的addSecurityItem方法和SecurityScheme对象启用基于JWT的认证功能/***SpringDocAPI文档相关配置*宏创建于2022/3/4。*/@ConfigurationpublicclassSpringDocConfig{privatestaticfinalStringSECURITY_SCHEME_NAME="BearerAuth";@BeanpublicOpenAPImallTinyOpenAPI(){returnnewOpenAPI().info(newInfo().title("Mall-TinyAPI").description("SpringDocAPIDemo").version("v1.0.0").license(newLicense().name("Apache2.0").url("https://github.com/macrozheng/mall-learning"))).externalDocs(newExternalDocumentation().description("SpringBoot实战e-commerce项目商城(50K+Star)全套文件").url("http://www.macrozheng.com")).addSecurityItem(newSecurityRequirement().addList(SECURITY_SCHEME_NAME)).components(newComponents().addSecuritySchemes(SECURITY_SCHEME_NAME,newSecurityScheme().name(SECURITY_SCHEME_NAME).type(SecurityScheme.Type.HTTP).scheme("bearer").bearerFormat("JWT")));}}测试接下来启动项目,就可以访问Swagger接口了,访问地址为:http://localhost:8088/swagger...我们首先通过登录界面登录,可以发现这个版本的Swagger返回结果支持高亮显示,版本明显比SpringFox新;然后通过认证按钮输入获取到的认证头信息,注意这里不需要添加承载前缀;那么我们就可以愉快的访问需要登录认证的界面了;看看请求参数的文档说明,还是熟悉的Swagger风格!常用配置SpringDoc也有一些常用配置可以了解,更多配置可以参考官方文档springdoc:swagger-ui:#修改SwaggerUI路径path:/swagger-ui.html#打开SwaggerUI界面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有点卡的朋友可以迁移到它试试看!如果想了解更多SpringBoot实用技巧,可以试试这个实用项目,全套教程(50K+Star):https://github.com/macrozheng/mall参考项目地址:https://github.com/springdoc/...官方文档:https://springdoc.org/项目源码地址https://github.com/macrozheng...