【微服务】springboot整合swagger多种模式使用详解

news2024/11/26 11:22:44

目录

一、前言

1.1 编写API文档

1.2 使用一些在线调试工具

1.3 postman

1.4 swagger

二、swagger简介

2.1 背景

2.2 swagger优缺点

2.2.1 swagger优点

2.2.2 swagger缺点

2.2.3 swagger使用场景

三、swagger常用的几种整合模式

3.1 swagger2

3.2 knife4j

3.2.1 knife4j特点

3.2.2 knife4j版本说明

3.3 Springdoc

3.3.1 SpringDoc简介

四、springboot整合swagger多种模式案例

4.1 springboot整合swagger2

4.1.1 添加如下核心依赖

4.1.2 配置文件

4.1.3 自定义swagger配置类

4.1.4 自定义测试接口

4.1.5 自定义实体类

4.1.6 访问swagger界面

4.2 springboot整合knife4j

4.2.1 引入核心依赖

4.2.2 自定义配置类

4.2.3 添加测试接口

4.2.4 自定义实体类

4.2.5 访问UI界面

4.3 springboot整合springdoc

4.3.1 添加核心依赖

4.3.2 核心配置文件

4.3.3 自定义配置类

4.3.4 自定义测试接口

4.3.5 访问UI界面

五、写在结尾


一、前言

在如今迭代速度越来越快的开发模式下,使用springboot作为服务端框架进行开发的项目越来越多,当后端API开发并自测完成后,如何能让前端同事与你快速高效的对接API呢?可能大家知道的有下面几种方式:

1.1 编写API文档

这是很多公司比较传统的做法,一般来说,这种方式对API开发者有着较高的要求,因为文档的编写过程相对耗时,所以API在开发之前,需要对API的各项参数进行严格的评审,以便减少在对接过程中的改动带来的事件成本。文档可以使用传统的word文档,或者使用markdown编辑。

1.2 使用一些在线调试工具

如今市面上出现了很多在线接口调试工具,只需要将你的API服务部署到服务器,然后就可以在线远程调试了。

1.3 postman

这是一个比较传统但也很好用的本地调试工具,对于团队来说,服务端开发人员可将A开发完成的API录入进去,然后通过团队分享的模式将API分享出去,前端就可以拿到API列表进行调试对接了。

1.4 swagger

随着swagger的使用规模越来越大,知名度也越来越高,尤其是在敏捷开发模式下具备更多的优势而被很多开发团队接纳,只需要服务端集成swagger依赖,再做简单的配置即可使用了,而且使用学习成本可以说几乎为零。

二、swagger简介

2.1 背景

在当前前后端分离成了产品快速迭代的基本模式后,如何快速完成API与前端的快速联调成了产品阶段性发布的关键因素,在这个背景下,尽管前端可以通过mock数据完成自身的功能验证,但是没有与服务端进行真实数据的联调,总觉得不踏实,但不同的团队联调的方式不一样,这就造成了有的团队使用的工具简单,联调效率高,有的复杂,造成联调效率很低,甚至带来了新的学习成本。

在这样的背景下,如何提升与API的快速联调,并尽可能的降低团队人员的学习成本呢?于是swagger的出现就很好的解决了这样一个难题。

2.2 swagger优缺点

2.2.1 swagger优点

使用swager具备如下优点:

  • 整合简单,只需要引入一个swagger的jar包,并做简单的配置即可;
  • 自动生成文档,只需在接口中使用swagger的相关注解进行标注,就能生成对应的接口文档;
  • 自动更新文档,由于是动态生成的,所以如果你修改了接口,文档也会自动对应修改(如果你也更新了注解的话)。这样就不会发送我修改了接口,却忘记更新接口文档的情况;
  • 支持在线调试,swagger提供了在线调用接口的功能;

2.2.2 swagger缺点

尽管swagger为API的管理带来了便利,但仍然存在一些缺点,

  • 不能创建测试用例,只能提供一个简单的在线调试,如果你想存储测试用例,则需要选择其他的工具了,比如postman,或者通过swagger导出yaml文件进行存储;
  • 程序中需要遵循一些基本的编码规范。比如你需要返回一个json数据,而这个数据可能是一个Map格式的,那么我们此时不能标注这个Map格式的返回数据的每个字段的说明,而如果是一个实体类的话,则需要为实体类中的属性标注特定的注解,这样带来的问题很明显就是程序的实体类中看起来有些乱,不够整洁,显得冗余;
  • 做不到API的动态刷新,假如当前前端正在使用的某个接口你在本地改了之后忘了重启,可能前端用到的还是老接口;
  • 存在一定程度的安全问题,UI界面上会暴露太多的信息,比如某个接口中,前端可能只需要3个必填的参数,但是在swagger的UI界面上,会把对象的所有字段信息都填进去,这样看起来显得比较凌乱冗余;

2.2.3 swagger使用场景

并不是所有的项目都适合使用swagger,比如一些比较老的项目,可能因为版本的问题如果强势集成,带来的时间人力成本巨大,还有一些比如对安全性要求特别高的项目,不允许随意暴露服务端的API到外网,使用swagger就不太合适了,不过从目前的趋势来看,swagger的使用还是能够整体提升开发和对接效率的,这里总结下面的一些场景提供参考:

  • 业务体量较小,功能迭代迅速,对开发时间要求很紧的项目,可以考虑使用swagger;
  • 对安全性要求较低,或者仅在公司内网环境使用,或者仅仅是开发阶段使用,这种也是可以考虑在开发阶段使用swagger的;
  • 服务端框架是springboot的,springboot目前占据着微服务框架的主流,因此与swagger的集成比较方便;

三、swagger常用的几种整合模式

以springboot与swagger整合为例,提供了多种方式可以使用,常用的主要有下面几种,掌握这几种应该足够可以应对大多数的场景了,

3.1 swagger2

这是原始的一种方式,也是很多小团队经常使用的一种方式,直接引入swagger的基本依赖jar包就可以使用了。与springboot的整合主要包括下面几个包:

  • springfox-swagger2;
  • springfox-swagger-ui;

3.2 knife4j

Knife4j的前身是swagger-bootstrap-ui,前身swagger-bootstrap-ui是一个纯swagger-ui的ui皮肤项目;

项目初衷是为了写一个增强版本的swagger的前端ui,但随着项目的发展,面对越来越多个性化需求,不得不编写后端Java代码以满足新的需求。

在swagger-bootstrap-ui的1.8.5~1.9.6版本之间,采用的是后端Java代码和Ui都混合在一个Jar包里面的方式提供给开发者使用。这种方式虽说对于集成swagger来说很方便,只需要引入jar包即可,但是在微服务架构下显得有些臃肿。因此项目正式更名为knife4j,取名knife4j是希望她能像一把匕首一样小巧,轻量,并且功能强悍。更名也是希望把她做成一个为Swagger接口文档服务的通用性解决方案,不仅仅只是专注于前端Ui前端。

3.2.1 knife4j特点

  • swagger-bootstrap-ui的所有特性都会集中在knife4j-spring-ui包中,并且后续规划也会满足开发者更多的个性化需求;
  • 主要的变化是,项目的相关类包路径更换为com.github.xiaoymin.knife4j前缀,开发者使用增强注解时需要替换包路径;
  • 后端Java代码和ui包分离为多个模块的jar包,以面对在目前微服务架构下,更加方便的使用增强文档注解(使用SpringCloud微服务项目,只需要在网关层集成UI的jar包即可,因此分离前后端);
  • knife4j沿用swagger-bootstrap-ui的版本号,第1个版本从1.9.6开始,关于使用方法,请参考文档(摘自 knife4j 官方介绍);

3.2.2 knife4j版本说明

knife4j 主要的版本基本如下

1.9.6蓝色皮肤风格,开始更名,增加更多后端模块
2.0~2.0.5Ui重写,底层依赖的springfox框架版本是2.9.2
2.0.6~springfox框架版本升级知2.10.5,OpenAPI规范是v2
3.0~底层依赖springfox框架版本升级至3.0.3,OpenAPI规范是v3

3.3 Springdoc

相对前两种来说,目前springdoc的热度很高,一是这个框架比较新,而且代码维护更新速度快,而且在与springboot项目整合的时候还提供了安全插件,可以在一定程度上提升使用的安全性。git的地址为:springdoc源码地址

3.3.1 SpringDoc简介

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

四、springboot整合swagger多种模式案例

以上从理论上对swagger常用的几种使用方式做了了解,接下来将通过实际案例分别做详细的说明。

4.1 springboot整合swagger2

前置准备,搭建springboot工程,目录结构如下

4.1.1 添加如下核心依赖

如下仅为核心依赖,可以根据自身情况酌情添加

<dependencies>

        <dependency>
            <groupId>org.modelmapper</groupId>
            <artifactId>modelmapper</artifactId>
            <version>3.1.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--swagger API获取-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>

        <!--swagger-ui API获取-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>


    </dependencies>

4.1.2 配置文件

使用这种方式不需要有太多配置,这里只配置一个端口即可

server.port=8088

4.1.3 自定义swagger配置类

该类是整个整合过程中最重要的一个配置,主要包括:

  • 定义接口的扫描路径;
  • swagger-ui的界面显示信息;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class SwaggerConfig {


    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                //用于生成API信息
                .apiInfo(apiInfo())
                //select()函数返回一个ApiSelectorBuilder实例,用来控制接口被swagger做成文档
                .select()
                //用于指定扫描哪个包下的接口
                .apis(RequestHandlerSelectors.basePackage("com.congge.controller"))
                //选择所有的API,如果你想只为部分API生成文档,可以配置这里
                .paths(PathSelectors.any())
                .build();
    }

    /**
     * 用于定义API主界面的信息,比如可以声明所有的API的总标题、描述、版本
     * @return
     */
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                //用来自定义API的标题
                .title("SpringBoot项目SwaggerAPIAPI测试")
                //用来描述整体的API
                .description("SpringBoot项目SwaggerAPI描述信息")
                //创建人信息
                .contact(new Contact("测试人员","http://localhost:8082/swagger-ui.html","congge@qq.com"))
                //用于定义服务的域名
                //.termsOfServiceUrl("")
                .version("1.0") //可以用来定义版本
                .build();
    }

}

4.1.4 自定义测试接口

自定义一个测试接口,可以说为了能够让工程中的接口在swagger-ui中能够调试,最重要的就是需要在类上添加这个注解:@Api,其他的方法上面的一些注解,可以参考官方文档进行配置即可;

//http://localhost:8088/swagger-ui.html  主页访问地址

@RestController
@Api(tags = "UserController", description = "UserController | 测试swagger")
public class UserController {

    @GetMapping("getById")
    @ApiOperation(value="getById 方法", notes="getById,根据ID获取账户信息")
    public User getById(){
        return new User("001","jerry","123456");
    }

    @PostMapping("/save")
    public String saveUser(UserRequest userRequest){
        User user = new User();
        BeanUtils.copyProperties(userRequest,user);
        return "success";
    }

}

4.1.5 自定义实体类

在很多情况下,接口中的参数是对象类型,这时候为了让前端对接的同事知道对象中的每个参数的含义,最好按照swagger的规范,给每个对象的属性添加一些swagger的注解,下面提供一个示例;

@Data
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(value="用户登录表单对象",description="用户登录表单对象")
public class User implements Serializable {

    private static final long serialVersionUID = -2896873555774275129L;

    @ApiModelProperty(value = "用户ID",required = true,example = "001")
    private String id;

    @ApiModelProperty(value = "用户名称",required = true,example = "jerry")
    private String userName;

    @ApiModelProperty(value = "密码",required = true,example = "123456")
    private String passWord;

}

4.1.6 访问swagger界面

启动服务,然后浏览器访问:http://localhost:8088/swagger-ui.html,至于怎么调试使用的话,有兴趣的同学可以自行尝试下,还是比较简单的;

4.2 springboot整合knife4j

上文简单介绍了knife4j的背景,接下来看看在springboot中整合knife4j的详细步骤,首先还是提前创建一个空的springboot工程,目录结构如下

4.2.1 引入核心依赖

这里做演示只需要两个包,如果有其他的需求可以继续追加即可;

    <dependencies>
        <!-- Spring Boot Web依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

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

    </dependencies>

4.2.2 自定义配置类

这个和上面整合swagger2类似,需要自定义一个类,里面定义UI界面的显示信息,以及扫描的接口类所在的包路径等信息

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class Knife4jConfiguration {

    @Bean(value = "defaultApi2")
    public Docket defaultApi2() {
        String groupName="3.X版本";
        Docket docket=new Docket(DocumentationType.OAS_30)
                .apiInfo(new ApiInfoBuilder()
                        .title("这是knife4j API ")
                        .description("这是knife4j,记录了API相关的出参和入参信息")
                        .termsOfServiceUrl("http://yaomaoyang.com")
                        .contact(new Contact("congge","http://127.0.0.1","congge@qq.com"))
                        .version("3.0")
                        .build())
                //分组名称
                .groupName(groupName)
                .select()
                //这里指定Controller扫描包路径
                .apis(RequestHandlerSelectors.basePackage("com.congge.controller"))
                .paths(PathSelectors.any())
                .build();
        return docket;
    }
}

4.2.3 添加测试接口

为了能够让接口在UI界面上展示,最重要的就是在类上添加的这个@Api注解,其他的注解可根据需要在接口类方法上进行标注即可,和上面使用swagger类似;

@RestController
@RequestMapping(value = "/user")
@Api(tags = "用户管理API")
public class UserController {

    /**
     * 根据ID获取账户信息
     * @param id
     * @return
     */
    @GetMapping(value = "/getById")
    @ApiImplicitParam(name = "name",value = "姓名",required = true)
    @ApiOperation("根据ID获取账户信息")
    public User test(@RequestParam("id") String id){
        User user = new User();
        user.setId(id);
        user.setPassWord("123456");
        user.setUserName("jerry");
        return user;
    }

}

4.2.4 自定义实体类

某些接口中接收的参数如果是一个对象的话,为了让其他同学能够看懂对象中的参数,可以在对象上添加knife4j提供的注解,下面给一个示例

@Data
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(value="用户登录表单对象",description="用户对象参数")
public class User implements Serializable {

    private static final long serialVersionUID = -2896873555774275129L;

    @ApiModelProperty(value = "用户ID",required = true,example = "001")
    private String id;

    @ApiModelProperty(value = "用户名称",required = true,example = "jerry")
    private String userName;

    @ApiModelProperty(value = "密码",required = true,example = "123456")
    private String passWord;

}

4.2.5 访问UI界面

启动工程,然后通过这个地址访问界面:http://localhost:8082/doc.html,看这个界面是不是觉得风格上显得更专业一点;

4.3 springboot整合springdoc

springdoc相比前两种,出现的稍晚,但是目前来看,其受欢迎的程度似乎更好,一方面来说swagger的基本功能它都有,同时,在访问的安全性上有一定的保障,下面来看具体的整合步骤,提前创建一个springboot工程,目录结构如下:

4.3.1 添加核心依赖

 其他的依赖柯根据自身的情况酌情引用

    <dependencies>
        <!-- Spring Boot Web依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- springdoc swagger ui -->
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-ui</artifactId>
            <version>1.7.0</version>
        </dependency>

        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-javadoc</artifactId>
            <version>1.7.0</version>
        </dependency>
    </dependencies>

4.3.2 核心配置文件

在application.yml文件中添加如下配置,这些配置见名知意这里就不做过多解释,其中:

api-docs.path: /v3/api-docs这个配置是为了获取接口的yml文档的地址

里面还有更丰富的配置可以参阅网上的资料,都有比较详细的说明,比如还可以配置打开UI界面的前置路径等;

# springdoc配置
springdoc:
  # 分组配置
  group-configs:
    - group: 用户管理
      packages-to-scan: com.congge.controller
      paths-to-match: /users/**
    - group: 角色管理
      packages-to-scan: com.congge.controller
      paths-to-match: /roles/**
  api-docs:
    enabled: true
    path: /v3/api-docs

server:
  port: 8087

4.3.3 自定义配置类

自定义配置可以对项目中的各类API进行分组管理,以bean的方式注入到spring容器中;

import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.ExternalDocumentation;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.servers.Server;
import org.springdoc.core.GroupedOpenApi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Arrays;

@Configuration
public class OpenApiConfig {

    /*@Bean
    public OpenAPI springShopOpenAPI() {
        return new OpenAPI()
                .info(new Info().title("Springdoc OAS3.0 - RESTful API")
                        .description("Springdoc OAS3.0 构建RESTful API")
                        .version("1.0")
                        .license(new License().name("Apache 2.0").url("http://springdoc.org")))
                .servers(Arrays.asList(
                        new Server().description("开发环境").url("http://localhost:8087")
                ))
                .externalDocs(new ExternalDocumentation()
                        .description("SpringShop Wiki Documentation")
                        .url("https://springshop.wiki.github.org/docs"));
    }*/

    @Bean
    public OpenAPI openAPI() {
        return new OpenAPI()
                .components(new Components())
                .info(new Info()
                        .title("User Manager API")
                        .description("用户管理系统API.")
                        .version("1.0"));
    }

    @Bean
    public GroupedOpenApi frontApi() {
        return GroupedOpenApi.builder()
                .group("frontApi")
                .pathsToMatch(new String[]{"/users/**", "/roles/**"})
                .packagesToExclude("com.congge.controller")
                .build();
    }
}

4.3.4 自定义测试接口

注意接口类上的这个注解,@Tag,是UI界面上能够识别的关键;

//http://localhost:8087/swagger-ui/index.html?urls.primaryName=%E7%94%A8%E6%88%B7%E7%AE%A1%E7%90%86

@Tag(name = "用户管理", description = "用户管理FrontApi")
@RestController
@RequestMapping("/users")
public class UserController {

    /**
     * 查询用户详细信息
     *
     * @param id 用户ID
     * @return 用户信息
     */
    @GetMapping("/get")
    public UserInfo getUser(@RequestParam String id) {
        return new UserInfo();
    }

}

@Data
@Schema(description = "用户返回实体对象")
class UserInfo {
    @Schema(description = "用户名称")
    private String userName;
    @Schema(description = "用户密码")
    private String passWord;
}

4.3.5 访问UI界面

启动工程,访问界面地址:http://localhost:8087/swagger-ui/index.html,看到如下效果,具体在UI界面上进行接口调试的时候与上面两种是类似的;

五、写在结尾

本篇详细总结了springboot整合swagger的多种使用方式,希望能够为您的日常开发带去帮助,本篇到此结束,感谢观看!

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

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

相关文章

《设计模式》之命令模式

文章目录 1、定义2、动机3、类结构4、优缺点5、总结6、代码实现(C) 1、定义 将一个请求封装为一个对象&#xff0c;从而使你可用不同的请求对客户端进行参数化&#xff1b;对请求排队或记录请求日志&#xff0c;以及支持可撤销的操作。 2、动机 在软件构建过程中&#xff0c…

虚拟内存和物理内存:概念、原理和应用

目录 概述1. 概念2. 原理3. 设计寻位原理4. 应用场景结论 概述 当你使用计算机时&#xff0c;内存是一个非常重要的资源。它用于存储正在运行的程序和数据&#xff0c;确保系统的正常运行。在计算机系统中&#xff0c;存在着虚拟内存和物理内存的概念&#xff0c;它们共同协作…

Docker Gitlab Container Registry配置

文章目录 前言一、Registry是什么二、步骤配置gitlab.rb文件修改docker-compose.yaml文档验证推送镜像 总结 前言 找了很多资料包括官网1都没有发现比较清楚的配置registry的方法&#xff0c;自己摸索了半天发现其实通过简单设置就能够配置好Container Registry。 之所以在题…

【Docker】3.Docker Registry

文章目录 Docker RegistryDocker Registry CommandImage Command NginxNginx System installNginx Config Container CommandCreate My DegistryBusyBox腾讯云镜像仓库搭建 Docker Registry 镜像仓库负责存储、管理、分发镜像&#xff0c;并且提供了登录认证的能力&#xff0c…

LeetCode_二叉树_DFS_中等_129.求根节点到叶节点数字之和

目录 1.题目2.思路3.代码实现&#xff08;Java&#xff09; 1.题目 给你一个二叉树的根节点 root &#xff0c;树中每个节点都存放有一个 0 到 9 之间的数字。 每条从根节点到叶节点的路径都代表一个数字&#xff1a;例如&#xff0c;从根节点到叶节点的路径 1 -> 2 -> …

【计算机网络】IP 地址处理函数

目录 1.struct sockaddr_in的结构 2.一般我们写的结构 3.常见的“点分十进制” 到 ” uint32_t 的转化接口 3.1. inet_aton 和 inet_ntoa &#xff08;ipv4&#xff09; 3.2. inet_pton 和 inet_ntop (ipv4 和 ipv6&#xff09; 3.3. inet_addr 和 inet_network 3…

人工智能-深度学习-科研神器推荐

根据知乎问题 有没有什么可以节省大量时间的 Deep Learning 效率神器&#xff1f; 的回答&#xff0c;筛选整理出一些深度学习科研神器。包括参数优化、数据可视化、模型部署蒸馏剪枝等。收录到 人工智能-深度学习-科研神器推荐https://​www.webhub123.com/#/home/detail?p4O…

vue监听缓存数据(localStorage)

方法&#xff1a;可以重写localStorage的setItem方法&#xff0c;当调用setItem方法设置新值的时候&#xff0c;会new Event(‘setItemEvent’) 用window.dispatchEvent()这个方法来派发一个事件&#xff0c;让window去监听 以下demo实现的是 一个页面获取诗句 然后将获取的数据…

【P51 】JMeter 聚合报告(Aggregate Report)

文章目录 一、聚合报告&#xff08;Aggregate Report&#xff09;参数说明二、准备工作三、测试计划设计 一、聚合报告&#xff08;Aggregate Report&#xff09;参数说明 可以查看事务或者取样器在某个时间范围内执行的汇总结果 使用场景&#xff1a;用于评估测试结果 使用…

2023-06-07 stonedb-包含内连接外连接派生表in子查询和聚合-查询结果错误-分析问题的思路

摘要: 最近在处理stonedb的一个包含内连接包含内连接外连接派生表in子查询和聚合的查询出错的问题, 逻辑非常复杂, 包含的操作符非常多. 本文首先从顶层设计出发, 指出如何分析如此复杂的问题。 查询SQL: SELECTB.company_id,上划日 ud_type,2 sort_no,合计 fiscal_date,DAT…

输入java -version 命令行没反应的简单解决办法【亲测有效】

&#x1f4a7; 记录一下今天遇到的 b u g \color{#FF1493}{记录一下今天遇到的bug} 记录一下今天遇到的bug&#x1f4a7; &#x1f337; 仰望天空&#xff0c;妳我亦是行人.✨ &#x1f984; 个人主页——微风撞见云的博客&#x1f390; &#x1f433; 数据结构与算法…

qemu+buildroot+linux arm64操作系统虚拟化-宿主系统wsl2

文章目录 1.qemu2.buildroot配置编译 3.linux kernel下载交叉编译工具链 linux kernel 5.16配置内核config_kernel.shbuild_kernel.sh 4.启动虚拟机start_qemu.sh参数解释运行 环境&#xff1a; wls2、qemu8.2、buildroot、linuxkernel 1.qemu https://buildroot.org/download…

Python知识点:lambda 表达式

大家好&#xff0c;欢迎来到 Crossin的编程教室 &#xff01; Python 是一门简洁的语言&#xff0c;lambda 表达式则充分体现了 Python 这一特点。 lambda 表达可以被看做是一种匿名函数。它可以让你快速定义一个极度简单的单行函数。譬如这样一个实现三个数相加的函数&#xf…

学会使用perf性能分析工具(含移植到开发板)

文章目录 一、在ubuntu中使用apt包下载Perf二、使用源码安装Perf&#xff0c;并移植到arm-linux环境下三、使用perf四、Perf的功能介绍 系统&#xff1a;Ubuntu18.04系统 内核版本&#xff1a;5.4.0-150-generic&#xff08;通过uname -r查看&#xff09; 一、在ubuntu中使用ap…

Linux驱动系列-PWM驱动

转自&#xff1a;嵌入式系统研发 1.概述 本文主要讲述了Linux的PWM驱动框架、实现方法、驱动添加方法和调试方法。 示例Linux内核版本&#xff1a;6.2.8。 2.原理 PWM是Pulse-Width Modulation的简称&#xff0c;中文译作脉冲宽度调制。作为一种调制技术&#xff0c;PWM的…

SpringBoot实现异步调用的几种方式

一、使用 CompletableFuture 实现异步任务 CompletableFuture 是 Java 8 新增的一个异步编程工具&#xff0c;它可以方便地实现异步任务。使用 CompletableFuture 需要满足以下条件&#xff1a; 异步任务的返回值类型必须是 CompletableFuture 类型&#xff1b; 在异步任务中…

基于vasp计算材料红外与Raman光谱信息

使用方法一&#xff1a;获取材料raman活性信息 代码链接&#xff1a;VASP/Sibulk-VASP at master raman-sc/VASP GitHub 前置计算材料的振动频率和介电常数等&#xff0c;参考INCAR如下&#xff1a; SYSTEM Si_bulk ISTART 0 # From-scratch; job : 0-new 1-cont 2-same…

4-2 贪心算法的基本要素

博主简介&#xff1a;一个爱打游戏的计算机专业学生博主主页&#xff1a; 夏驰和徐策所属专栏&#xff1a;算法设计与分析 1.什么是贪心选择性质 贪心选择性质是一种在算法设计中经常使用的策略。它基于这样的思想&#xff1a;在每一步选择中&#xff0c;都选择当前看起来最优…

多篇论文入选ICASSP 2023,火山语音有效解决多类实践问题

近日由IEEE主办、被誉为世界范围内最大规模、也是最全面的信号处理及其应用方面的顶级学术会议ICASSP2023于希腊召开&#xff0c;该会议具有权威、广泛的学界以及工业界影响力&#xff0c;备受AI领域多方关注。会上火山语音多篇论文被接收并发表&#xff0c;内容涵盖众多前沿领…

superset db upgrade报错记录

superset db upgrade报错记录 报错1报错2报错3报错4报错5报错6成功了 报错1 (superset) [hyjhadoop102 ~]$ superset db upgradefrom markupsafe import soft_unicode ImportError: cannot import name soft_unicode from markupsafe (/opt/module/miniconda3/envs/superset/l…