SprongBoot3整合Knife4j实现在线接口文档

news2024/10/5 15:22:40

大家好,我是晓凡。

写在前面

在上一篇文章,我们详细介绍了SpringBoot3 怎么整合SpringDoc实现在线接口文档。但是,有不少小伙伴

都觉得接口界面太丑了。有没有什么更美观一点的UI界面呢?

当然是有的了,毕竟这是一个看脸的时代,Knife4j这不来了么。

一、界面比较

这儿我们将上一篇文章使用swagger UIKnife4j UI做一个比较,哪个好看就不用我多说了吧。

swaggerUI界面

swaggerUI界面

Knife4j UI界面

Knife4j UI界面

二、Knife4j 是什么?

Knife4j 是一个为Java 项目生成和管理 API 文档的工具。实际上,它是 Swagger UI的一个增强工具集,

旨在让 Swagger 生成的 API在线文档更加优雅、美观、强大。

① 官方地址

http://knife4j.net/

②文档地址

https://doc.xiaominfo.com/docs/quick-start

三、为什么要使用Knife4j

使用Knife4j主要有以下优点,就问哪个不吸引我们呢?

  • 美观的UI:相比于原生 Swagger UIKnife4j 提供了更加人性化和美观的界面设计
  • 丰富的文档交互功能:支持在线调试、请求参数动态输入、接口排序等
  • 个性化配置:可自定义 API 文档的界面风格,实现文档界面的个性化展示

四、Knife4j版本介绍

目前,我们使用的SpringBoot 版本主要是2和3,不同的boot版本需要适配不同版本的Knife4j.

通过这一小节,我们将在项目中选择合适的Knife4j版本

4.1 Knife4j的前世今生

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

名称开发语言&框架状态最后版本风格
Knife4jJavaJavaScriptVue持续更新中…黑色
swagger-bootstrap-uiJavaJavaScriptjQuery停更1.9.6蓝色

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

版本说明
1.0~1.9.6名称是叫swagger-bootstrap-ui,蓝色风格Ui
1.9.6蓝色皮肤风格,开始更名,增加更多后端模块
2.0~2.0.5Ui基于Vue2.0+AntdV重写,黑色风格,底层依赖的springfox2.9.2,仅提供Swagger2规范的适配
2.0.6~2.0.9底层依赖springfox2.10.5,仅提供Swagger2规范的适配
3.0~3.0.3底层依赖springfox3.0.3,是过度版本,不建议使用
4.0~Knife4j对于支持不同协议,依赖的是第三方组件,需要引入不同依赖
OpenAPI2(Swagger2)规范,依赖Springfox项目,项目处于停更状态,不建议使用
OpenAPI3(Swagger3)规范,依赖Springdoc项目,更新频率快,建议使用该版本
4.2 Spring Boot版本兼容性
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提供的服务端增强功能,引入Knife4j的纯Ui版本没有任何限制。只需要考虑不同的规范即可

五、快速开始

通过上面的介绍,相信你已经对Knife4j有了整体的认识,接下来我们就使用SpringBoot3快速整合Knife4j

我们这选用的环境如下

  • jdk17
  • SpringBoot3.3.1
  • knife4j 4.4.0
  • OpenAPI3协议规范
5.1 新建一个web项目

建一个名为knife4j-spring-boot3-demo 的web项目,项目结构如下

项目结构

5.2 添加Knife4j 依赖

⚠️温馨提示

我们这里使用的是SpringBoot3

  • Spring Boot 3 只支持OpenAPI3规范
  • Knife4j提供的starter已经引用springdoc-openapi的jar,需注意避免jar包冲突
  • JDK版本必须 >= 17
<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
    <version>4.4.0</version>
</dependency>

5.3 新建hello接口

新建controller包,添加HelloController类,代码如下

@RestController
public class HelloController {
    @GetMapping("/hello")
    public String hello(){
        return "hello";
    }
}
5.4 访问Knife4j在线文档

浏览器输入:http://localhost:8080/doc.html 访问在线接口文档

在线接口文档

六、Knife4j 常用配置

⚠️温馨提示:

增强功能需要通过配置application.yml配置文件开启增强,后面不再赘述,默认开启

knife4j:
enable: true
6.1 项目配置

application.yml中可以自定义api-docsswagger-ui的访问路径。当然了,如果没配置,默认就是下面路径

**注:**这儿还是兼容swagger ui页面展示

springdoc:
  swagger-ui:
    path: /swagger-ui.html
    tags-sorter: alpha
    operations-sorter: alpha
  api-docs:
    path: /v3/api-docs
  group-configs:
    - group: 'default'
      paths-to-match: '/**'
      packages-to-scan: com.xiezhr.knife4jspringboot3demo.controller

浏览器输入:http://localhost:8080/swagger-ui/index.html 可按照原来ui来显示

swagger-ui

6.2 配置接口文档基本信息

① 配置接口基本信息

新建一个config包—>并在包下建立一个Knife4jConfig配置类

Knife4jConfig配置类

② 配置接口文档基础信息

这儿我们可以配置接口文档标题、接口文档版本信息、接口文档描述信息、接口文档联系人信息,接口文档license许可证信息

我们只需在配置类中添加如下代码即可

@Configuration
public class Knife4jConfig {

    @Bean
    public OpenAPI openAPI() {
        return new OpenAPI()
                // 配置接口文档基本信息
                .info(this.getApiInfo())
                ;
    }

    private Info getApiInfo() {
        return new Info()
                // 配置文档标题
                .title("SpringBoot3集成Knife4j")
                // 配置文档描述
                .description("SpringBoot3集成Knife4j示例文档")
                // 配置作者信息
                .contact(new Contact().name("程序员晓凡").url("https://www.xiezhrspace.cn").email("1666397814@163.com"))
                // 配置License许可证信息
                .license(new License().name("Apache 2.0").url("https://www.xiezhrspace.cn"))
                // 概述信息
                .summary("SpringBoot3集成Knife4j示例文档aaa")
                .termsOfService("https://www.xiezhrspace.cn")
                // 配置版本号
                .version("2.0");
    }
}

浏览器输入:http://localhost:8080/doc.html 访问显示如下

接口基本信息

6.3 i18n国际化

Knife4j提供了i18n的支持,支持的语言主要包含2种:中文(zh-CN)、英文(en-US)。默认是中文

①通过下拉框选择

通过访问doc.html打开文档界面,可以在文档的右上角看到语言的选择,如下图:

语言选择

② 通过文档地址也可以选择

  • 中文:http://host:port/doc.html#/home/zh-CN
  • 英文:http://host:port/doc.html#/home/en-US

另外,如果你是使用了knife4j提供的增强功能,你也可以这样访问

  • 中文:http://host:port/doc.html#/plus/zh-CN
  • 英文:http://host:port/doc.html#/plus/en-US

③ 通过application.yml配置文件设置

knife4j:
  enable: true
  setting:
    language: zh_cn
6.4 接口添加作者

接口代码如下,我们给hello接口添加作者“张三”

@ApiOperationSupport(author = "张三")
@GetMapping("/hello")
public String hello(){
    return "hello";
}

接口作者

6.5 自定义文档

有时候在OpenAPI不足以满足接口说明的情况下,我们可以通过.md格式文件扩充系统文档说明

①添加自定义文档

我们可以在当前项目中添加多个文件夹,文件夹中存放.md格式的markdown文件,每个.md文档代表一份自定义文档说明。

这里,我们在默认组default 下面添加接口签名认证文档说明.md自定义文档说明.md 两个文档,结构如下

文档结构

每个.md文件中,Knife4j允许一级(h1)、二级(h2)、三级(h3)标题作为最终的文档标题

比如,上面添加的自定义文档说明.md内容如下

# 自定义文档说明

## 效果说明

`knife4j`为了满足文档的个性化配置,添加了自定义文档功能

开发者可自定义`md`文件扩展补充整个系统的文档说明

开发者可以在当前项目中添加一个文件夹,文件夹中存放`.md`格式的markdown文件,每个`.md`文档代表一份自定义文档说明

**注意**:自定义文档说明必须以`.md`结尾的文件,其他格式文件会被忽略

② 配置自定义文档显示

文档添加好之后,我们在application.yml 添加如下配置信息

knife4j:
  documents:
    - group: default
      name: 其他文档
      # 某一个文件夹下所有的.md文件
      locations: classpath:markdown/*

配置说明:

  • group: 分组的名称,这儿我们还没有配置分组,所以默认的是default
  • name: 界面呈现时菜单显示
  • locations: markdown文档路径

③ 前端界面呈现效果

上述信息配置好之后,在浏览器访问doc.html 如下

自定义文档显示

6.6 访问权限控制

为了保证生产环境下接口服务安全,我们可以提供一个登陆界面的功能,只有输入用户名和密码才能访问

① 在application.yml 中添加如下配置

knife4j:
  enable: true
  basic:
    enable: true
    username: xiezhr
    password: 123456

②需要输入正确的用户名和密码才能访问

权限控制

6.7 接口排序

使用Knife4j提供的增强注解@ApiOperationSupport中的order字段可进行接口排序

HelloController 中有hellogetToken 两个接口,我们要实现getToken接口显示在前面,代码如下

① 修改application.yml

springdoc:
  swagger-ui:
    operations-sorter: order

② 调整@ApiOperationSupport中的order

@RestController
public class HelloController {
    @ApiOperationSupport(author = "张三",order = 2)
    @GetMapping("/hello")
    public String hello(){
        return "hello";
    }

    @ApiOperationSupport(author = "李四" ,order = 1)
    @GetMapping("/access-appid")
    public String getToken(){

        return "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c";
    }
}

③ 接口显示顺序如下

接口排序

6.8 接口分组

为了演示API分组,我们在controller包下面再建立admin包和common包,包下分别添加AdminControllerCommonController接口类,结构及代码如下

image-20240630152601955

AdminController

@RequestMapping("admin")
@RestController
public class AdminController {

    @GetMapping("/access-appid")
    public String getToken(){

        return "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c";
    }
}

CommonController

@RequestMapping("common")
@RestController
public class CommonController {

    @GetMapping("/hello")
    public String hello(){
        return "hello";
    }

    @GetMapping("/hi")
    public String Hi(){
        return "Hi 程序员晓凡";
    }
}

在默认情况(没有分组)的情况下,所有包下接口都显示在一一个默认组下面,如/common/* 和/admin/* 访问路径下的接口都显示在一起,如下图所示

default分组

这时,如果/common/* 下的接口比较多,/admin/* 下的接口也比较多,界面上显示就很混乱

解决办法就是添加分组信息,这里有两种配置方法

① 通过application.yml配置 admin分组和common 两个分组

springdoc:
  group-configs:
    - group: 'admin'
      paths-to-match: '/admin/**'
      packages-to-scan: com.xiezhr.knife4jspringboot3demo.controller
    - group: 'common'
      paths-to-match: '/common/**'
      packages-to-scan: com.xiezhr.knife4jspringboot3demo.controller

② 通过配置类Knife4jConfig添加两个分组

@Configuration
public class SpringDocConfig {
  // 此处省去其他配置信息......
    
    @Bean("common")
    public GroupedOpenApi webGroupApi() {
        return GroupedOpenApi.builder().group("common")
                .pathsToMatch("/common/**")
                .build();
    }

    @Bean("admin")
    public GroupedOpenApi adminGroupApi() {
        return GroupedOpenApi.builder().group("admin")
                .pathsToMatch("/admin/**")
                .build();
    }

}

以上两种配置时等效的,再访问:http://localhost:8080/doc.html 显示如下

最终分组显示

6.9 动态请求参数

在某些特定的情况下如果后端定义的是一种Map结构,或者是参数并没有定义声明,而希望也能达到一种动态添加参数进行调试的结果,这种体验有点类似于postman

① 开启动态参数配置

knife4j:
  enable: true
  setting:
  # 开启动态请求参数,true-开启,false-关闭
    enable-dynamic-parameter: true

配置完后,开启动态请求这个会勾上

动态请求

② 添加动态参数调试

添加动态参数调试

动态参数

6.10 过滤请求参数

通常我们在开发接口时,比如一个新增接口和一个修改接口,修改接口需要传递主键id、而新增接口则不需要传递此属性,但大部分情况,我们只写一个Model类,此时在新增接口时显示主键id会显得很多余.

使用自定义增强注解ApiOperationSupport中的ignoreParameters属性,可以强制忽略要显示的参数.

忽略的规则如下:

  • 例如新增接口时,某实体类不需要显示Id,即可使用该属性对参数进行忽略.ignoreParameters={"id"}
  • 如果存在多个层次的参数过滤,则使用名称.属性的方式,例如 ignoreParameters={"uptModel.id","uptModel.uptPo.id"},其中uptModel是实体对象参数名称,id为其属性,uptPo为实体类,作为uptModel类的属性名称
  • 如果参数层级只是一级的情况下,并且参数是实体类的情况下,不需要设置参数名称,直接给定属性值名称即可
  • 如果实体类属性中是通过List这种数组的方式,那么过滤规则会有所不同,在属性后面需要追加一个下标[0]ignoreParameters={"uptModel.uptPo[0].id"}

在接口过滤时,主要有两种情况

6.10.1 表单参数

我们在使用实体类直接作为参数时,在我们的ui界面中是不会显示参数名称的,此时可以直接使用实体的属性名称进行参数忽略,例如如下代码:

表单类型的请求是不需要添加参数名的

@ApiOperation(value = "新增Model接口1")
@ApiOperationSupport(ignoreParameters = {"id","orderDate.id"})
@PostMapping("/insertMode1l")
public Rest<UptModel> insertModel1(UptModel uptModel){
    Rest<UptModel> r =new Rest<>();
    r.setData(uptModel);
    return r;
}

实体类UptModel.java文件代码

public class UptModel {

    @ApiModelProperty(value = "主键id")
    private String id;

    @ApiModelProperty(value = "姓名")
    private String name;

    @ApiModelProperty(value = "邮箱")
    private String email;

    @ApiModelProperty(value = "订单信息")
    private OrderDate orderDate;
}

此时,最终过过滤掉UptModel的属性id和属性orderDate类中的id属性,不在界面显示.

img

6.10.2 JSON参数

如果请求参数是使用JSON的方式

代码如下:

@ApiOperation(value = "新增Model接口")
@ApiOperationSupport(ignoreParameters = {"uptModel.id","uptModel.name","uptModel.orderDate.id"})
@PostMapping("/insertModel")
public Rest<UptModel> insertModel(@RequestBody UptModel uptModel){
    Rest<UptModel> r =new Rest<>();
    r.setData(uptModel);
    return r;
}

此时如果要过滤id的话,需要指定带上参数名称uptModel

最终忽略的值为ignoreParameters = {"uptModel.id","uptModel.name","uptModel.orderDate.id"}

img

6.11 包含请求参数

时候需要忽略的参数太多时,我们需要写很多的忽略参数属性,此时,一个与忽略参数对立取反的特性就显得很有帮助了

使用自定义增强注解ApiOperationSupport中的includeParameters属性,可以强制包含要显示的参数.去除多余的参数

6.12 自定义Host

不同的网络环境,可以通过配置该属性,方便的进行调试

通过配置application.yml

knife4j:
  enable: true
  setting:
    # 是否启用Host
    enable-host: true
    # 启用Host后地址,例如:http://192.168.0.111:8080
    enable-host-text: "http://192.168.0.111:8080"
6.13 全局参数

Knife4j 提供全局参数设置功能,例如:我们可以设置全局token参数

全局参数功能主要提供两种参数类型:

  • query(表单)
  • header(请求头)

设置方法如下

全局参数设置

6.14 自定义主页内容

可以提供一个Markdown文件来自定义显示Home主页的显示内容,通过配置yml来进行开启,配置文件如下

knife4j:
  enable: true
  setting:
    enable-home-custom: true
    home-custom-path: classpath:markdown/home.md
  • enable-home-custom:该属性为Boolean值,默认false,如果开发者要自定义主页内容,该选项设置为true
  • home-custom-path:提供一个主页的Markdown文件位置

我们markdown目录下添加home.md 文档,并添加内容之后,最终界面显示如下

home.md

最终显示效果

6.15 自定义Footer

Knife4j 支持自定义界面底部Footer内容,可以更改为公司或者产品介绍等信息

未自定义前

未定义前

通过设置application.yml

knife4j:
  enable: true
  setting:
    enable-footer: true
    enable-footer-custom: true
    footer-custom-content: Apache License 2.0 | Copyright  2019-[程序员晓凡](https://www.xiezhrspace.cn)

image-20240630174827521

七、其他功能

7.1 导出离线文档

使用swagger的时候,导出一份精细的文档,需要很繁琐的步骤,集成了knife4j之后,导出文档变得很简单

而且还可以导出不同格式的文档

离线文档

7.2 导出postman

我们还可以将接口信息复制然后导出到postman工具进行调试

具体操作如下

导出postman

7.3 生成前端调用代码

生成前端调用代码

八、小结

SpringBoot3整合knife4j其实非常简单,界面相对于swagger UI 确实美观了不少。文章只列举了常用功能,如果小伙伴有特殊的需求,可以浏览官方文档,官方文档还是非常详细的。

作者也给出了各种场景的实战demo: https://gitee.com/xiaoym/swagger-bootstrap-ui-demo

SpringBoot各种版本的整合都有案例

各种场景整合

本期内容到这儿就结束了 ★,°:.☆( ̄▽ ̄)/$:.°★ 。 希望对您有所帮助

我们下期再见 (●’◡’●) ヾ(•ω•`)o

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1892702.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL 进阶(一)【存储引擎】

1、存储引擎 1.1、MySQL 体系结构 自上而下可以分为 连接层 接受客户端的连接&#xff0c;完成连接的处理、认证授权、安全方案和最大连接数等服务层 绝大部分的核心功能都是在服务层完成的&#xff0c;比如SQL 接口&#xff08;DDL、DML、视图、触发器、存储过程&#xff09…

【IDEA】什么maven,如何进行文件导入,并打包

maven介绍 maven是一个Java世界中&#xff0c;构建工具。 核心功能&#xff1a; 1&#xff0c;管理依赖&#xff1a; 管理文件运行的顺序逻辑依赖关系。对配置文件&#xff0c;进行构建和编译。其也是在调用jdk&#xff0c;来进行编译打包工作。 2&#xff0c;打包 通过使用…

【Python基础篇】你知道python的数据类型都有哪些吗?

文章目录 0. 前言1. 基本数据类型1.1 数值类型&#xff08;int、float&#xff09;1.1.1 整型&#xff08;int&#xff09;1.1.2 浮点型&#xff08;float&#xff09; 1.2 布尔类型&#xff08;bool&#xff09;1.3 字符串&#xff08;str&#xff09;1.4 字节串&#xff08;b…

后端之路——文件本地上传

一、基础原理 文件上传是一个很基础的知识点&#xff0c;尤其是本地上传&#xff0c;在现实开发基本都是云上传&#xff0c;但是作为一个基础要简单了解一下 首先前端我就不多讲解了&#xff0c;网页开发里用<form>表单可以上传文件&#xff0c;只需要加上这三属性&…

Yolov8模型调参大全:超详细解读每一个参数

目录 1. 代码获取方式 2. YOLOv8网络配置 3. Yolov8使用 3.1. CLI 3.2. Python 4.default.yaml文件解读 1. 代码获取方式 Yolov8项目地址&#xff1a;https://github.com/ultralytics/ultralytics 这里就不详细介绍v8了 2. YOLOv8网络配置 # Ultralytics YOLO &…

超详细的 C++中的封装继承和多态的知识总结<1.封装与继承>

引言 小伙伴们都知道C面向对象难&#xff0c;可是大家都知道&#xff0c;这个才是C和C的真正区别的地方&#xff0c;也是C深受所有大厂喜爱的原因&#xff0c;它的原理更接近底层&#xff0c;它的逻辑更好&#xff0c;但是学习难度高&#xff0c;大家一定要坚持下来呀&#xff…

上海路演服务app开发的意义与主要功能

随着经济水平与互联网技术的飞速发展&#xff0c; 金融活动也逐渐深入人们的日常生活&#xff0c;各类公司也试图通过互联网获得金融机会&#xff0c;探寻新的发展。为了让企业具有更快捷&#xff0c;更便利的宣传途径与方法&#xff0c;上海路演服务app应运而生。 一&#xf…

SSM慢性病患者健康管理系统设计与实现-计算机毕业设计源码04877

目 录 摘要 1 绪论 1.1 研究意义 1.2研究目的 1.3论文结构与章节安排 2 慢性病患者健康管理系统系统分析 2.1 可行性分析 2.1.1 技术可行性分析 2.1.2 经济可行性分析 2.1.3 法律可行性分析 2.2 系统功能分析 2.2.1 功能性分析 2.2.2 非功能性分析 2.3 系统用例分…

VS2019+QT VS tools:Debug下ok,relese下报错

报错界面 踩得坑&#xff1a; 尝试一下重装 QT VS tools&#xff0c;结果装不上。 尝试卸载原来的QT VS tools&#xff1a;卸载方法&#xff0c;到下面文件夹下可以看到有两个文件夹&#xff0c;分别是两个插件&#xff0c;找到QT的插件&#xff0c;删除文件夹即可。但是删除…

管理沟通能力测试,求职应聘和HR人才测评

什么是管理沟通能力&#xff1f; 管理沟通能力&#xff0c;包含两个方面&#xff0c;1方面是管理能力&#xff0c;另一方面是沟通能力&#xff0c;对于企业招聘来说基础管理管理、中高层管理必定会做管理和沟通能力测试。 这是从人的性格层面&#xff08;人格&#xff09;去评…

Java学习十二—Java8特性之Optional类

一、简介 Java 8 引入了 Optional​ 类作为一种容器&#xff0c;可以用来显式地表示一个值存在或不存在。它解决了传统上可能会遇到的空指针异常问题&#xff0c;同时提供了一种更优雅的方式来处理可能为null的情况。 Java 8 中引入 Optional​ 类的背景可以从以下几个方面来理…

css flex 子元素溢出时,父元素被撑开解决方案

当父元素使用flex: 1;自适应填满时&#xff0c;子元素内容溢出&#xff0c;父元素内容撑大&#xff0c;导致页面显示问题&#xff0c;或设置了overflow 为scroll 的元素没出现滚动条等问题 解决方案&#xff1a; 1.如果是横向排列&#xff0c;flex: 1;的元素加上width: 0; 此…

【Matlab 路径优化】基于蚁群算法的XX市旅游景点线路优化系统

基于蚁群算法的XX市旅游景点线路优化系统 &#xff08;一&#xff09;客户需求&#xff1a; ①考虑旅游景点的空间分布、游客偏好等因素&#xff0c;实现了旅游线路的智能规划 ②游客选择一景点出发经过所要游览的所有景点只一次&#xff0c;最后回到出发点的前提下&#xf…

实验4 宏指令及子程序设计实验

从键盘输入10个无符号十进制数&#xff08;小于256&#xff09;&#xff0c;将其转换为二进制数并存放在NUM字节型变量中&#xff0c;找出其中的最大数&#xff0c;并将找出的最大数在屏幕上显示出来。 要求&#xff1a; 1&#xff09;在屏幕上显示字符串提示信息的功能由宏指…

【PB案例学习笔记】-28制作一个右键菜单

写在前面 这是PB案例学习笔记系列文章的第28篇&#xff0c;该系列文章适合具有一定PB基础的读者。 通过一个个由浅入深的编程实战案例学习&#xff0c;提高编程技巧&#xff0c;以保证小伙伴们能应付公司的各种开发需求。 文章中设计到的源码&#xff0c;小凡都上传到了gite…

多态相关知识2

多态相关知识2 抽象基类和纯虚函数纯虚函数和多继承虚析构函数虚析构函数作用纯虚析构函数 重写 重载 重定义 抽象基类和纯虚函数 在设计时&#xff0c;常常希望基类仅仅作为其派生类的一个接口。这就是说&#xff0c;仅想对基类进行向上类型转换&#xff0c;使用它的接口&…

Wing FTP Server

文章目录 1.Wing FTP Server简介1.1主要特点1.2使用教程 2.高级用法2.1Lua脚本,案例1 1.Wing FTP Server简介 Wing FTP Server&#xff0c;是一个专业的跨平台FTP服务器端&#xff0c;它拥有不错的速度、可靠性和一个友好的配置界面。它除了能提供FTP的基本服务功能以外&#…

据阿谱尔APO Research统计,2023年全球皮肤科药物市场价值为 751.7 亿美元

据阿谱尔 (APO Research&#xff09;统计&#xff0c;2023 年全球皮肤科药物市场价值估计为 751.7 亿美元&#xff0c;预计到 2030 年将达到 1622.1 亿美元&#xff0c;预测期内&#xff08;2024-2030 年&#xff09;的复合年增长率为 11.44%。 全球最大的单一类别皮肤科药物是…

TheBrain 14:AI增强的视觉知识管理工具

TheBrain是一款与众不同的思维导图软件&#xff0c;其所有信息通过一个又一个的节点进行联系&#xff0c;最终形成一个杂而不乱的网状结构。与传统的树形思维导图相较而言&#xff0c;TheBrain更有助于整合零散的资源&#xff0c;激发创意和锻炼思维。此次thebrain13带来了很多…

基因组学系列3:基因分型Phasing与单倍型参考序列HRC

1. 基因分型Phasing概念 基因分型&#xff0c;也称为基因定相、单倍体分型、单倍体构建等&#xff0c;即将一个二倍体&#xff08;或多倍体&#xff09;基因组上的等位基因&#xff08;或杂合位点&#xff09;正确定位到父亲或母亲的染色体上&#xff0c;最终使得来自同一亲本…