当前位置: 首页 > article >正文

SpringDoc【使用详解】

SpringDoc使用详解

  • 一、何为SpringDoc
  • 二、概念解释
  • 三、SpringDoc使用
    • 2.1简单集成
    • 2.2 配置SpringDoc
      • 2.2.1 yml方式配置
      • 2.2.2配置文档信息
    • 2.3配置文档分组
    • 2.4使用注解
      • 2.4.1 @Tag
      • 2.4.2 @Operation
      • 2.4.3 @Schema
      • 2.4.4 @NotNull
      • 2.4.5 @Parameter
      • 2.4.6 @Parameters
      • 2.4.7 @ApiResponses 和@ApiResponse
  • 四、认证授权
    • 3.1无需认证
    • 3.2需要认证
  • 五、SpringDoc整合Knife4j
    • 1.前世今生
    • 2.Spring Boot版本兼容性
    • 3.Spring Boot 3
    • 4.Spring Boot 2

一、何为SpringDoc

SpringDoc是一个用来自动生成API文档的库。它是基于SpringBoot项目的,遵循OpenAPI3(一个组织规定的规范)规范。它是通过检查我们运行中的程序,推断出基于Spring配置、类结构和各种注解的API语义,从而自动生成JSON、YAML和HTML格式的接口文档。
而我们不得不提的就是Swagger。Swagger是一个公司的开源项目,将自己的API设计贡献给了OpenAPI并由其标准化。在SpringDoc之前我们还可以使用Springfox,和SpringDoc一样是一个用于生成API文档的库,2020年起不再更新。
SpringDoc官网

二、概念解释

谈到API文档,那就绕不开大名鼎鼎的Swagger,但是你是否还听说过:OpenAPI,Springfox,Springdoc?你第一次看到这些脑瓜子是不是嗡嗡的?

  • OpenAPI
    是一个组织(OpenAPI Initiative),他们指定了一个如何描述HTTP API的规范(OpenAPI Specification)。既然是规范,那么谁想实现都可以,只要符合规范即可。

  • Swagger
    它是SmartBear这个公司的一个开源项目,里面提供了一系列工具,包括著名的 swagger-ui。swagger是早于OpenApi的,某一天swagger将自己的API设计贡献给了OpenApi,然后由其标准化了。

  • Springfox
    是Spring生态的一个开源库,是Swagger与OpenApi规范的具体实现。我们使用它就可以在spring中生成API文档。以前基本上是行业标准,目前最新版本可以支持 Swagger2, Swagger3 以及 OpenAPI3 三种格式。但是其从 2020年7月14号就不再更新了,不支持springboot3,所以业界都在不断的转向我们今天要谈论的另一个库Springdoc,新项目就不要用了。

  • Springdoc
    算是后起之秀,带着继任Springfox的使命而来。其支持OpenApi规范,支持Springboot3,我们的新项目都应该使用这个。

三、SpringDoc使用

我们可以在springboot中使用SpringDoc来生成API文档,详情可以参考官网,下面我们来简单的实践一下。

2.1简单集成

在springboot中使用springdoc起步非常容易,只需要引入其starter即可

<dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-starter-webmvc-ui</artifactId><version>2.8.6</version></dependency>

运行后访问下面的链接即可

http://server:port/context-path/swagger-ui.html

例如

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

例如我们有如下代码:

@RestController
@RequestMapping("/api/programmer")
public class ProgrammerController {@PostMapping()public Programmer createProgrammer(@RequestBody CreateProgrammerRequest request) {return new Programmer(1, request.getAge(), request.getProgrammingLang());}@GetMapping("/{id}")public Programmer getProgrammer(@PathVariable Integer id) {return new Programmer(1, 35, List.of("Java,Python,SQL"));}
}

添加依赖运行后访问http://localhost:8080/swagger-ui.html后结果如下
在这里插入图片描述
是不是特牛逼?当然springdoc的集成不可能就这点东西,不然也没有这篇文章了,咱接着往下看。苦于网上的一些教程不直观,对初学者不友好,所以本文以代码和其效果的形式来展示,保你一看就会。

2.2 配置SpringDoc

2.2.1 yml方式配置

springdoc:api-docs:# 是否开启接口文档enabled: trueswagger-ui:# 持久化认证数据persistAuthorization: trueinfo:# 标题title: '标题:${demo.name}多租户管理系统_接口文档'# 描述description: '描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...'# 版本version: '版本号: ${demo.version}'# 作者信息contact:name: Agazigiemail: 123456789@qq.comurl: www.baidu.comcomponents:# 鉴权方式配置security-schemes:apiKey:type: APIKEYin: HEADERname: ${sa-token.token-name}#这里定义了两个分组,可定义多个,也可以不定义group-configs:- group: 1.演示模块packages-to-scan: org.dromara.demo- group: 2.通用模块packages-to-scan: org.dromara.web- group: 3.系统模块packages-to-scan: org.dromara.system- group: 4.代码生成模块packages-to-scan: org.dromara.generator

在这里插入图片描述

2.2.2配置文档信息

得益于springboot的强大,我们只需添加一个依赖就可以使用API文档了,但是使用的都是默认值,我们当然也希望对其进行各种自定义的配置

  • 配置文档信息
    创建一个OpenAPI 的bean,配置文档名称等信息
@Configuration
public class SpringDocConfig {@Beanpublic OpenAPI myOpenAPI() {return new OpenAPI().info(new Info() //设置信息.title("程序员API") //标题.description("程序员的大本营") //描述信息.version("v1.0.0")  //版本.license(new License() //许可证.name("许可协议").url("https://shusheng007.top")).contact(new Contact() //作者信息.name("书生007").email("wangben850115@gmail.com"))).externalDocs(new ExternalDocumentation() //外部文档.description("ShuSheng007博客").url("https://shusheng007.top"));}// 指定扫描的包路径@Beanpublic GroupedOpenApi publicApi() {return GroupedOpenApi.builder().group("my_api") // 分组名称(自定义).packagesToScan("com.ls.ai.demo.controller") // 包路径.addOpenApiMethodFilter(methodPredicate()) // 方法级注解过滤.build();}// 定义过滤条件:仅包含带有 @Operation 注解的方法private Predicate<HandlerMethod> methodPredicate() {return handlerMethod ->handlerMethod.hasMethodAnnotation(io.swagger.v3.oas.annotations.Operation.class);}// 可选:过滤类级别的注解(如 @Tag)private Predicate<HandlerMethod> classPredicate() {return handlerMethod ->handlerMethod.getBeanType().isAnnotationPresent(io.swagger.v3.oas.annotations.tags.Tag.class);}}

效果:
在这里插入图片描述
里面的配置项很多,可以根据代码和截图对照一下,按照自己的需求配置即可

2.3配置文档分组

用来配置分组的,假如你有两类controller一类以/api为前缀,一类以/admin为前缀,就可以将其配置为两个分组。很多时候我们只有一个分组,所以就不需要下面的配置。

@Configuration
public class SpringDocConfig {...@Beanpublic GroupedOpenApi publicApi() {return GroupedOpenApi.builder().group("api").pathsToMatch("/api/**").build();}@Beanpublic GroupedOpenApi adminApi() {return GroupedOpenApi.builder().group("admin").pathsToMatch("/admin/**").build();}
}

效果:
在这里插入图片描述
可以通过右上角的下拉框选择要展示的group。

2.4使用注解

这个是咱们的重头戏,OpenApi规范提供了很多注解,下面是一些常用的

注解含义
@Tag用在controller类上,描述此controller的信息
@Operation用在controller的方法里,描述此api的信息
@Parameter用在controller方法里的参数上,描述参数信息
@Parameters用在controller方法里的参数上
@Schema用于Entity,以及Entity的属性上
@ApiResponse用在controller方法的返回值上
@ApiResponses用在controller方法的返回值上
@Hidden用在各种地方,用于隐藏其api

下面我们一起来看看效果

2.4.1 @Tag

@Tag(name = "程序员", description = "程序员乐园")
@RestController
@RequestMapping("/api/programmer")
public class ProgrammerController {
...
}

效果
在这里插入图片描述

2.4.2 @Operation

@Operation(summary = "创建程序员", description = "用于创建一个闷骚的程序员")
@PostMapping()
public Programmer createProgrammer(@RequestBody CreateProgrammerRequest request) {return new Programmer(666, "王二狗", request.getAge(), request.getProgrammingLang());
}

在这里插入图片描述
@Operation 其实很复杂的,我们可以将下面要用的@Parameter以及@ApiResponse都可以配置在它里面。

2.4.3 @Schema

@Schema 用于实体类和其属性,例如有如下代码:

@Schema(description = "创建程序员入参")
public class CreateProgrammerRequest {@Schema(description = "名称", example = "王二狗")private String name;@Schema(description = "年龄", example = "35")private Integer age;@Schema(description = "掌握的编程语言", type = "List", example = "[\"Java\",\"Sql\"]")private List<String> programmingLang;
}

效果:
在这里插入图片描述
还可以切换到 Schema选项进行查看
在这里插入图片描述

2.4.4 @NotNull

同时,Springdoc还支持 Java Bean Validation API 的注解,例如@NotNull

@Schema(description = "创建程序员入参")
public class CreateProgrammerRequest {@NotNull@Schema(description = "名称", example = "王二狗")private String name;@NotNull@Min(18)@Max(35)@Schema(description = "年龄", example = "35")private Integer age;...
}

效果:
在这里插入图片描述
注意红框中的内容,name和age右上角都有出现了一个红色的星星,表示是必填的。age也被限制了范围。

2.4.5 @Parameter

用于添加接口参数信息

@GetMapping("/{id}")
public Programmer getProgrammer(@Parameter(description = "程序员id") @PathVariable Integer id) {...
}

效果
在这里插入图片描述

2.4.6 @Parameters

@Parameter作用一样,但是可以批量添加,不用一个一个的写在参数前面

@Parameters(value = {@Parameter(name = "name", description = "姓名", in = ParameterIn.PATH),@Parameter(name = "age", description = "年龄", in = ParameterIn.QUERY)
})
@GetMapping("/{name}")
public List<Programmer> getProgrammers(@PathVariable("name") String name, @RequestParam("age") Integer age) { ...
}

parameters里的parameter使用name来找到方法中的入参,这块要对应上。

效果:

在这里插入图片描述

2.4.7 @ApiResponses 和@ApiResponse

顾名思义,此注解用来描述返回值的。

@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "成功",content = {@Content(mediaType = "application/json",schema = @Schema(implementation = Programmer.class))}),@ApiResponse(responseCode = "405", description = "非法输入",content = @Content)})@PostMapping()public Programmer createProgrammer(@RequestBody CreateProgrammerRequest request) {...}

效果
在这里插入图片描述
可见,我们成功配置了两种情况的返回值。但是我们一般不会手动给每个API 写上一堆@ApiResponse,那的多烦啊。业界通常会有一个统一的返回类型,例如

public class Result<T> implements Serializable {private int code;private String message;private T data;private String traceId;
}

还会有一个统一的异常处理类,使用@RestControllerAdvice标记,然后每个方法会捕捉对应的异常,只要我们使用@ResponseStatus来标记这些方法,springdoc就会自动生成相应的文档

@RestControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(value = Exception.class)@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)public Result handleException(HttpServletRequest httpServletRequest, Exception e) {return new Result(StatusCode.FAILED.getCode(), StatusCode.FAILED.getMessage(), null);}@ExceptionHandler(value = ApiException.class)@ResponseStatus(HttpStatus.BAD_REQUEST)public Result handleBusinessException(HttpServletRequest httpServletRequest, ApiException e) {return new Result(e.getCode(), e.getMessage(), null);}
}

例如我们有如下代码:

...
@RequestMapping(value = "/api/programmer",produces =  "application/json")
public class ProgrammerController {@GetMapping("/{id}")public Result<Programmer> getProgrammer(@Parameter(description = "程序员id") @PathVariable Integer id) {...}
}

生成的api文档如下:

在这里插入图片描述
可见,多了400和500。

四、认证授权

我们知道·swagger-ui·不仅可以看API文档也可以直接调用API,这点很牛逼。但有时我们的服务需要认证,否则就调用不通,那怎么办?稍安勿躁,OpenApi规范也考虑到了这个问题。

OpenAPI 3.0 支持下面的认证模式:

  • HTTP authentication schemes (使用Authorization header):
  • Basic
  • Bearer
  • Other HTTP schemes as defined by RFC 7235 and HTTP Authentication Scheme Registry
  • API keys in headers, query string or cookies
  • Cookie authentication
  • OAuth 2
  • OpenID Connect Discovery
    有的我也没用过,我们常用的就是Http Auth,以及OAuth2。本文以HTTP Bearer来作为我们服务的认证授权模式,如下图所示。
    在这里插入图片描述

3.1无需认证

当你的服务没有认证机制的话是可以直接调用的:

每个API 右上角都有一个try it out按钮,点击输入参数点击execute按钮即可,如下所示。
在这里插入图片描述

3.2需要认证

如果你的服务需要认证后才能调用,那么默认情况下就不行了。例如你使用了Spring Security,或者你自己写了个Filter 来实现认证功能。

下面是demo服务用来做认证的Filter,采用HTTP Bearer 模式。所以需要在请求的Authentication Header 里 携带token 123才能通过认证。

@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {...@Overrideprotected void doFilterInternal(HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull FilterChain filterChain) throws ServletException, IOException {...// get token from header [Authorization: Bearer <token>]String authHeader = request.getHeader(AUTH_HEADER);...String authToken = authHeader.split(" ")[1];if (!"123".equals(authToken)) {genUnauthResponse(response);return;}filterChain.doFilter(request, response);}

所以当从swagger-ui上调用API时,返回了401,如下图所示。那怎么才能正常调用API呢?接下来让我们看一下
在这里插入图片描述

Springdoc 使用@SecurityScheme 来定义一个安全模式,我们可以定义全局的,也可以针对某个controller定义类级别的,我们这里定义一个全局的。

  1. 在Application类上添加@SecurityScheme
@SecurityScheme(name = "api_token", type = SecuritySchemeType.HTTP, scheme ="bearer", in = SecuritySchemeIn.HEADER)
@SpringBootApplication
public class SpringdocIntegrateApplication {public static void main(String[] args) {SpringApplication.run(SpringdocIntegrateApplication.class, args);}
}

我们定义了一个名为api_token的安全模式,并指定了其使用HTTP Bearer的方式。

  1. 使此安全模式生效
@Configuration
public class SpringDocConfig {@Beanpublic OpenAPI myOpenAPI() {return new OpenAPI()....security(List.of(new SecurityRequirement().addList("api_token")));}
}

注意api_token正是我们第一步定义的那个Security schema。

经过上面两步后查看生成的API文档,你会发现其右上角出现了一个Authorize的按钮, 而且每个API的右边也出现了一把小锁,如下图所示。
在这里插入图片描述
当点击Authorize按钮后会弹出一个让你提供认证信息的弹出,其根据不同的认证方式会有所区别。

在这里插入图片描述
我们这里需要输入一个token,然后点击Authorize按钮后关闭此弹窗。你会发现每个API右边的那把小锁从打开状态变为了关闭状态,颜色也从灰色变成了黑色,证明其生效了。

然后我们再来请求一下API,就会正常返回了。

  1. 声明是否需要认证
    默认情况下按照上面两步设置后,整个应用程序的API生效,但是有的API是不需要认证的,例如登录。 对于这种情况,我们可以使用@SecurityRequirements()来设置。
@RestController
@RequestMapping(value = "/admin",produces =  "application/json")
public class AuthController {...@SecurityRequirements()@PostMapping("/login")public Result<String> login(@RequestBody LoginRequest request){return Result.ok("123");}
}

@SecurityRequirements() 里面需要一个String数组,里面列出需要使用的@SecurityScheme,例如我们这里的api_token。如果不写就说明不需要任何的安全模式,这里就是这种情况。
在这里插入图片描述
从上图可以看出,/admin/login这个API右边没有小锁的标志,表示其不需要认证。针对本案例来说,不需要认证的意思就是:在发起这个请求的时候,不在Authentication header里面附加token。

这里只是展示了HTTP bearer 这种安全模式,其他的原理类似,小朋友们可以开动你们聪明的大脑研究一下,给补充到这里。

五、SpringDoc整合Knife4j

1.前世今生

在更名为Knife4j之前,原来的名称是叫swagger-bootstrap-ui,这是两种不一样风格的Ui,对比情况如下:

名称开发语言&框架状态最后版本风格
Knife4jJava、JavaScript、Vue持续更新中…黑色
swagger-bootstrap-uiJava、JavaScript、jQuery停更1.9.6蓝色

Knife4j从开源至今,目前主要经历版本的变化,分别如下:

版本说明
1.0~1.9.6名称是叫swagger-bootstrap-ui,蓝色风格Ui
1.9.6蓝色皮肤风格,开始更名,增加更多后端模块
2.0~2.0.5Ui基于Vue2.0+AntdV重写,黑色风格,参考示例,底层依赖的springfox框架版本是2.9.2,仅提供Swagger2规范的适配
2.0.6~2.0.9底层springfox框架版本升级至2.10.5,仅提供Swagger2规范的适配
3.0~3.0.3底层依赖springfox框架版本升级至3.0.3,OpenAPI规范是v3,过度版本,建议开发者不要使用
4.0~区分OpenAPI2和Swagger3的Maven坐标artifactId
OpenAPI2规范服务端解析框架稳定在springfox2.10.5
OpenAPI3框架服务端解析跟随springdoc项目更新迭代
建议开发者使用该版本,请参考4.x升级文档

2.Spring Boot版本兼容性

首先,确保您了解您的项目所使用的Spring Boot版本。
以下是一些常见的Spring Boot版本及其对应的Knife4j版本兼容推荐:

Spring Boot版本Knife4j Swagger2规范Knife4j OpenAPI3规范
1.5.x~2.0.0<Knife4j 2.0.0>=Knife4j 4.0.0
2.0~2.2Knife4j 2.0.0 ~ 2.0.6>=Knife4j 4.0.0
2.2.x~2.4.0Knife4j 2.0.6 ~ 2.0.9>=Knife4j 4.0.0
2.4.0~2.7.x>=Knife4j 4.0.0>=Knife4j 4.0.0
>= 3.0>=Knife4j 4.0.0>=Knife4j 4.0.0

Knife4j在之前的版本更新中,逐渐提供了一些服务端适配的增强特性功能。

但是开发者应该明白,不管是Swagger2规范还是OpenAPI3规范,Knife4j的最新版本的纯Ui版本,是可以适配Spring Boot所有版本的。

如果你不考虑使用Knife4j提供的服务端增强功能,引入Knife4j的纯Ui版本没有任何限制。只需要考虑不同的规范即可

3.Spring Boot 3

提示
Spring Boot 3 只支持OpenAPI3规范
Knife4j提供的starter已经引用springdoc-openapi的jar,开发者需注意避免jar包冲突
JDK版本必须 >= 17
详细Demo请参考knife4j-spring-boot3-demo

首先,引用Knife4j的starter,Maven坐标如下:

<dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId><version>4.5.0</version>
</dependency>

其实现在就可以使用Knife4j了,暂不做其他配置,启动项目,浏览器输入http://localhost:8080/doc.html查看接口文档
由于我们没有进行任何的属性配置,所以看到的页面是knife4j的初始页面
在这里插入图片描述

引入之后,其余的配置,开发者即可完全参考springdoc-openapi的项目说明,Knife4j只提供了增强部分,如果要启用Knife4j的增强功能,可以在配置文件中进行开启

部分配置如下:

# springdoc-openapi项目配置
springdoc:swagger-ui:path: /swagger-ui.htmltags-sorter: alphaoperations-sorter: alphaapi-docs:path: /v3/api-docsgroup-configs:- group: 'default'paths-to-match: '/**'packages-to-scan: com.xiaominfo.knife4j.demo.web
# knife4j的增强配置,不需要增强可以不配
knife4j:enable: truesetting:language: zh_cn

Knife4j更多增强配置明细,请移步文档进行查看

最后,使用OpenAPI3的规范注解,注释各个Spring的REST接口,示例代码如下:

@RestController
@RequestMapping("body")
@Tag(name = "body参数")
public class BodyController {@Operation(summary = "普通body请求")@PostMapping("/body")public ResponseEntity<FileResp> body(@RequestBody FileResp fileResp){return ResponseEntity.ok(fileResp);}@Operation(summary = "普通body请求+Param+Header+Path")@Parameters({@Parameter(name = "id",description = "文件id",in = ParameterIn.PATH),@Parameter(name = "token",description = "请求token",required = true,in = ParameterIn.HEADER),@Parameter(name = "name",description = "文件名称",required = true,in=ParameterIn.QUERY)})@PostMapping("/bodyParamHeaderPath/{id}")public ResponseEntity<FileResp> bodyParamHeaderPath(@PathVariable("id") String id,@RequestHeader("token") String token, @RequestParam("name")String name,@RequestBody FileResp fileResp){fileResp.setName(fileResp.getName()+",receiveName:"+name+",token:"+token+",pathID:"+id);return ResponseEntity.ok(fileResp);}
}

最后,访问Knife4j的文档地址:http://ip:port/doc.html即可查看文档

4.Spring Boot 2

提示
Spring Boot 版本建议 2.4.0~3.0.0之间
Spring Boot 版本 < 2.4 版本则建议选择Knife4j 4.0之前的版本
Spring Boot 2 + OpenAPI2 demo:knife4j-spring-boot27-demo
Spring Boot 2 + OpenAPI3 demo:knife4j-springdoc-openapi-demo

OpenAPI2
OpenAPI2(Swagger)规范是Knife4j之前一直提供支持的版本,底层依赖框架为Springfox,此次在4.0版本开始

Knife4j有了新的变化,主要有以下几点:

  • Springfox版本选择的依然是2.10.5版本,而并非springfox最新3.0.0版本
  • 不支持以Springfox框架为基础的OpenAPI3规范,放弃Springfox项目的后续版本适配支持工作
  • Spring Boot 版本建议 2.4.0~3.0.0之间
    可以使用 knife4j-openapi2-spring-boot-starter,maven 坐标如下:
<dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-openapi2-spring-boot-starter</artifactId><version>4.5.0</version>
</dependency>

配置yml属性,如下:

knife4j:enable: trueopenapi:title: Knife4j官方文档description: "`我是测试`,**你知道吗**# aaa"email: xiaoymin@foxmail.comconcat: 八一菜刀url: https://docs.xiaominfo.comversion: v4.0license: Apache 2.0license-url: https://stackoverflow.com/terms-of-service-url: https://stackoverflow.com/group:test1:group-name: 分组名称api-rule: packageapi-rule-resources:- com.knife4j.demo.new3

最后,访问Knife4j的文档地址:http://ip:port/doc.html即可查看文档
OpenAPI3
OpenAPI3的规范,目前针对Java的Spring Boot项目,主要支持的有2个版本

  • springfox 3.0.0: 同时兼容OpenAPI2以及OpenAPI3,但是停更很久了
  • springdoc-openapi: 兼容OpenAPI3规范,更新速度频繁
    Knife4j在只有的OpenAPI3规范中,底层基础框架选择springdoc-openapi项目

针对Springfox3.0.0版本会放弃。

建议开发者如果使用OpenAPI3规范的话,也尽快迁移过来。

可以使用 knife4j-openapi3-spring-boot-starter,maven 坐标如下:

<dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-openapi3-spring-boot-starter</artifactId><version>4.5.0</version>
</dependency>

引入jar包后,同上面的Spring Boot 3版本使用方式一样,进行配置即可。

相关文章:

SpringDoc【使用详解】

SpringDoc使用详解 一、何为SpringDoc二、概念解释三、SpringDoc使用2.1简单集成2.2 配置SpringDoc2.2.1 yml方式配置2.2.2配置文档信息 2.3配置文档分组2.4使用注解2.4.1 Tag2.4.2 Operation2.4.3 Schema2.4.4 NotNull2.4.5 Parameter2.4.6 Parameters2.4.7 ApiResponses 和Ap…...

Redis持久化 | RDB AOF | 常见问题

目录 RDB&#xff08;Redis DataBase&#xff09; 给什么内存数据做快照——&#xff08;全量&#xff09; 触发机制 RDB文件生成的时候会阻塞主线程吗&#xff1f; 关闭持久化命令 bgsave执行流程 RDB文件怎么配置&#xff1f;有哪些优缺点 优点&#xff1a; 缺点&am…...

判断矩阵A是否可以相似对角化

【例题1】 【例题2】...

React 列表渲染

开发环境&#xff1a;Reacttsantd 你可能经常需要通过 JavaScript 的数组方法 来操作数组中的数据&#xff0c;从而将一个数据集渲染成多个相似的组件。在这篇文章中&#xff0c;你将学会如何在 React 中使用 filter() 筛选需要渲染的组件和使用 map() 把数组转换成组件数组。 …...

C#核心学习(八)面向对象--封装(7)终章 C#内部类和分部类、密封类

目录 一、内部类&#xff08;Inner Class&#xff09; 1. ​什么是内部类&#xff1f; 2. ​内部类的作用 3. ​如何定义内部类&#xff1f; 4. ​常见应用场景 二、分部类&#xff08;Partial Class&#xff09; 1. ​什么是分部类&#xff1f; 2. ​分部类的写法 3.…...

[ctfshow web入门] web25

信息收集 要想拿到flag&#xff0c;需要突破两层if。 解题 第一个if 传入r0&#xff0c;拿到mt_rand的值&#xff0c;由于每一次访问都会重新设置种子&#xff0c;所以每一次访问都是一样的随机数。 所以我们的r mt_rand-显示的值 1799250188 r1799250188就可以突破第一…...

局域网访问 Redis 方法

局域网访问 Redis 方法 默认情况下&#xff0c;Redis 只允许本机 (127.0.0.1) 访问。如果你想让局域网中的其他设备访问 Redis&#xff0c;需要 修改 Redis 配置&#xff0c;并确保 防火墙放行端口。 方法 1&#xff1a;修改 Redis 配置 1. 修改 redis.conf&#xff08;或 me…...

oracle 索引失效

在 Oracle 11g 中&#xff0c;索引失效的常见原因包括函数修改列、隐式类型转换、统计信息过时等&#xff0c;解决方法需结合版本特性&#xff08;如虚拟列、索引跳跃扫描&#xff09;。通过执行计划分析、统计信息维护和合理使用提示&#xff08;Hints&#xff09;&#xff0c…...

网络安全-等级保护(等保) 0. 前言

各位伙伴好&#xff1a; 招投标总结已过去一年了&#xff0c;时间飞逝&#xff0c;一直忙于工作&#xff0c;等保相关的内容断断续续整理了近半年的时间&#xff0c;但一直无暇完成博客内容。 等保已经是一个成熟的体系&#xff0c;现在已进入等保2.0时代&#xff0c;相关政策…...

【数据结构】树的介绍

目录 一、树1.1什么是树&#xff1f;1.2 树的概念与结构1.3树的相关术语1.4 树形结构实际运用场景 二、二叉树2.1 概念与结构2.2 特殊的二叉树2.2.1 满二叉树2.2.2 完全二叉树 个人主页&#xff0c;点击这里~ 数据结构专栏&#xff0c;点击这里~ 一、树 1.1什么是树&#xff1…...

大模型是如何把向量解码成文字输出的

hidden state 向量 当我们把一句话输入模型后&#xff0c;例如 “Hello world”&#xff1a; token IDs: [15496, 995]经过 Embedding Transformer 层后&#xff0c;会得到每个 token 的中间表示&#xff0c;形状为&#xff1a; hidden_states: (batch_size, seq_len, hidd…...

Android源码之App启动

目录 App启动概述 App启动过程 App启动过程图 源码概述 跨进程启动 进程内启动 下面以应用桌面Launcher启动App的MainActivity来举例&#xff1a; App启动概述 首先&#xff0c;MainActivity是由Launcher组件来启动的&#xff0c;而Launcher又是通过Activity管理服务Act…...

nginx如何实现负载均衡?

Nginx 是一款高性能的 Web 服务器和反向代理服务器&#xff0c;它可以通过配置实现负载均衡功能。以下是实现负载均衡的详细步骤和方法&#xff1a; 1. 基本概念 负载均衡是将客户端请求分发到多个后端服务器上&#xff0c;以提高系统的可用性和性能。Nginx 支持多种负载均衡策…...

【GESP】C++二级练习 luogu-B3721 [语言月赛202303] Stone Gambling S

GESP二级练习&#xff0c;多层循环分支练习&#xff0c;难度★✮☆☆☆。 题目题解详见&#xff1a;https://www.coderli.com/gesp-2-luogu-b3721/ 【GESP】C二级练习 luogu-B3721 [语言月赛202303] Stone Gambling S | OneCoderGESP二级练习&#xff0c;多层循环分支练习&am…...

2. Qt界面文件原理

本节主要介绍ui文件如何与窗口关联&#xff0c;并通过隐式连接方式显示对话框 本文部分ppt、视频截图原链接&#xff1a;[萌马工作室的个人空间-萌马工作室个人主页-哔哩哔哩视频] 1 UI文件如何与窗口关联 1.1 mainwindow.cpp的头文件ui_mainwindow.h 根据编译原理的基本规…...

Elastic 的 OpenTelemetry 分发版(EDOT)现已正式发布:开源、可用于生产环境的 OTel

作者&#xff1a;来自 Elastic Miguel Luna 及 Bahubali Shetti Elastic 自豪地宣布正式发布 Elastic OpenTelemetry 分发版&#xff08;Elastic Distributions of OpenTelemetry - EDOT&#xff09;&#xff0c;其中包含 Elastic 自定义版本的 OpenTelemetry Collector 以及多…...

docker部署jenkins并成功自动化部署微服务

一、环境版本清单&#xff1a; docker 26.1.4JDK 17.0.28Mysql 8.0.27Redis 6.0.5nacos 2.5.1maven 3.8.8jenkins 2.492.2 二、服务架构&#xff1a;有gateway&#xff0c;archives&#xff0c;system这三个服务 三、部署步骤 四、安装linux 五、在linux上安装redis&#…...

UML对象图

UML对象图 一、对象图核心概念 对象图&#xff08;Object Diagram&#xff09;描述的是系统在某一时刻对象&#xff08;实例&#xff09;的状态快照。它关注的是实际对象之间的实例关系&#xff0c;而不是类与类之间的静态结构。主要特点有&#xff1a; ​对象&#xff08;Ob…...

【NLP 53、投机采样加速推理】

目录 一、投机采样 二、投机采样改进&#xff1a;美杜莎模型 流程 改进 三、Deepseek的投机采样 流程 Ⅰ、输入文本预处理 Ⅱ、引导模型预测 Ⅲ、候选集筛选&#xff08;可选&#xff09; Ⅳ、主模型验证 Ⅴ、生成输出与循环 骗你的&#xff0c;其实我在意透了 —— 25.4.4 一、…...

[250403] HuggingFace 新增检查模型与电脑兼容性的功能 | Firefox 发布137.0 支持标签组

目录 Hugging Face 让寻找兼容的 AI 模型变得更容易Firefox 137 版本更新摘要 Hugging Face 让寻找兼容的 AI 模型变得更容易 Hugging Face 是一个流行的在线平台&#xff0c;用于访问开源人工智能 (AI) 工具和模型。该平台推出了一项有用的新功能&#xff0c;允许个人轻松检查…...

VScode连接CentOS 7.6虚拟机

本文内容&#xff1a;在Windows上使用VMware运行虚拟机&#xff0c;然后使用VScode连接CentOS 7.6虚拟机。 进入系统前 安装VMware 安装教程参考&#xff1a;VMware安装 下载CentOS 7.6镜像 可以使用国内镜像源&#xff0c;但是一般国内镜像源要么已经不维护CentOS 7.6这个…...

Android Hilt 教程

Android Hilt 教程 —— 一看就懂&#xff0c;一学就会 1. 什么是 Hilt&#xff1f;为什么要用 Hilt&#xff1f; Hilt 是 Android 官方推荐的 依赖注入&#xff08;DI&#xff09;框架&#xff0c;基于 Dagger 开发&#xff0c;能够大大简化依赖注入的使用。 为什么要用 Hi…...

高德地图 3D 渲染-区域纹理图添加

引入-初始化地图&#xff08;关键代码&#xff09; // 初始化页面引入高德 webapi -- index.html 文件 <script src https://webapi.amap.com/maps?v2.0&key您申请的key值></script>// 添加地图容器 <div idcontainer ></div>// 地图初始化应该…...

K8S核心技术点

Pod&#xff0c;Service和Deployment的关系 Pod&#xff1a;Kubernetes 中最小的部署单元&#xff0c;用于运行容器化应用。 Service&#xff1a;提供服务发现和负载均衡&#xff0c;为 Pod 提供稳定的网络端点&#xff0c;ClusterIP&#xff0c;NodePort&#xff0c;LoadBala…...

Spring Boot 与 TDengine 的深度集成实践(二)

创建数据模型 定义实体类 在完成数据库连接配置后&#xff0c;我们需要创建与 TDengine 表对应的 Java 实体类。实体类是 Java 对象与数据库表之间的映射&#xff0c;通过定义实体类&#xff0c;我们可以方便地在 Java 代码中操作数据库中的数据&#xff0c;实现数据的持久化…...

搭建hadoop集群模式并运行

3.1 Hadoop的运行模式 先去官方看一看Apache Hadoop 3.3.6 – Hadoop: Setting up a Single Node Cluster. 本地模式&#xff1a;数据直接存放在Linux的磁盘上&#xff0c;测试时偶尔用一下 伪分布式&#xff1a;数据存放在HDFS&#xff0c;公司资金不足的时候用 完全分布式&a…...

Qt实现鼠标右键弹出弹窗退出

Qt鼠标右键弹出弹窗退出 1、鼠标右键实现1.1 重写鼠标点击事件1.2 添加头文件1.3 添加定义2、添加菜单2.1添加菜单头文件2.2创建菜单对象2.3 显示菜单 3、添加动作3.1添加动作资源文件3.2 添加头文件3.3 创建退出动作对象3.4菜单添加动作对象 4、在当前鼠标位置显示菜单4.1当前…...

Spring 服务调用接口时,提示You should be redirected automatically to target URL:

问题 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><title>Redirecting...</title><h1>Redirecting...</h1><p>You should be redirected automatically to target URL: <a href"http://xxx/api/v1/branch…...

Springboot整合Mybatis+Maven+Thymeleaf学生成绩管理系统

前言 该系统为学生成绩管理系统&#xff0c;可以当作学习参考&#xff0c;也可以成为Spirng Boot初学者的学习代码&#xff01; 系统描述 学生成绩管理系统提供了三种角色&#xff1a;学生&#xff0c;老师&#xff0c;网站管理员。主要实现的功能如下&#xff1a; 登录 &a…...

马井堂js设置倒计时页面

js-倒计时页面 提示&#xff1a;这里简述项目相关背景&#xff1a; 例如&#xff1a;项目场景&#xff1a;倒计时需求 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible&…...