Spring Boot 测试:单元、集成与契约测试全解析

一、Spring Boot 分层测试策略

Spring Boot 应用采用经典的分层架构,不同层级的功能模块对应不同的测试策略,以确保代码质量和系统稳定性。

Spring Boot 分层架构:

 Spring Boot分层架构    
 A[客户端] -->|HTTP 请求| B[Controller 层]   
 B -->|调用| C[Service 层]    
 C -->|调用| D[Repository 层]  
 D -->|操作| E[数据库]   
 E -->|调用| F[外部服务接口]

分层测试策略:

在这里插入图片描述

测试策略核心原则:

•单元测试 (UT)

隔离验证单模块逻辑(Controller、Service、Repository)。

价值:快速反馈,精准定位代码缺陷。

•集成测试 (IT)

垂直集成测试(应用内全链路)与水平集成测试(跨服务交互)

价值:保证生产环境行为一致性。

•契约测试 (CT)

保障跨服务接口一致性,与水平集成测试互补。

价值:防止接口“暗坑”,提升协作效率。

二、单元测试:逐层击破,精准验证

单元测试专注于验证单一模块的逻辑,通过模拟其依赖项,快速获取反馈。

2.1 Controller 层:HTTP接口的靶向验证

测试目标: REST API 接口的独立测试,隔离业务逻辑与外部依赖。

测试工具

•@WebMvcTest:轻量级切片测试,仅加载 Controller 层相关 Bean。

•MockMvc:模拟 HTTP 请求与响应,支持链式断言。

•@MockBean:Mock 依赖的 Service 层组件,隔离Service层依赖。

实战示例

@WebMvcTest(UserController.class) //只加载UserController进行测试。
public class UserControllerTest {

    @Autowired
    private MockMvc mockMvc;

    //模拟UserService,用于提供预定义的行为。
    @MockBean
    private UserService userService;

    @Test
    void getUserById_Returns200() throws Exception {
        // 模拟 Service 层返回
        when(userService.findById(1L)).thenReturn(new User(1L, "Test"));

        // 发起请求并断言
        mockMvc.perform(get("/users/1"))
               .andExpect(status().isOk())
               .andExpect(jsonPath("$.name").value("Test"));
    }
}

1.代码解析

•1L - 代表Long类型的 ID,符合User实体类的定义。

•/users/1 -为 HTTP 请求中的路径参数,Spring 会自动将其转换为Long类型。

•测试逻辑 -通过模拟UserService返回固定的数据,验证 Controller 层的输入输出行为。

2.注解解析

@WebMvcTest

•专注于Web 层的单元测试。只加载 Web 层相关的 Bean,如MockMvc。

•@WebMvcTest(UserController.class),表示只加载UserController进行测试。

@MockBean

•模拟服务层或其他依赖,避免与外部服务实际交互。

@Test

•标识一个单元测试方法。JUnit 会自动执行标记的方法,并报告结果。

MockMvc

•模拟 HTTP 请求并测试 Controller 行为及断言结果。

2.2 Service 层:业务逻辑深度验证

测试目标:验证业务规则的正确性、事务管理的行为符合预期。

测试工具

@MockBean + @SpringBootTest(轻量模式)

@MockBean模拟数据库操作,结合@SpringBootTest提供的 Spring 应用上下文,进行Service层单元测试。

实战示例

@SpringBootTest  // 启动一个完整的 Spring 应用上下文
public class UserServiceTest {

    // 自动注入 UserService 实例
    @Autowired private UserService userService;
    
    // 创建一个模拟的 UserRepository Bean,替代真实的数据库操作
    @MockBean
    private UserRepository userRepository;
    
    @Test
    void createUser_ValidInput_ReturnsUser() {
        // 1. 准备测试数据
        User user = new User("SpringBot");
        when(userRepository.save(user)).thenReturn(user);
        // 2. 调用业务方法
        User result = userService.createUser(user);
        // 3. 验证业务逻辑
        assertThat(result.getName()).isEqualTo("SpringBot");
        verify(userRepository).save(user); // 验证 Repository 方法被调用
    }
    @Test
    void createUser_NullName_ThrowsException() {
        // 验证业务规则:用户名为空时抛出异常
        User user = new User(null);
        assertThatThrownBy(() -> userService.createUser(user))
            .isInstanceOf(IllegalArgumentException.class)
            .hasMessage("用户名不能为空");
    }
}

代码解析

•@SpringBootTest

启动 Spring Boot类似真实的测试环境,加载整个应用上下文。通常用于集成测试。

与其他注解结合使用时,可用于单元测试。如结合@Autowired自动注入 Bean,或者@MockBean模拟服务进行单元测试。

•@Autowired

自动注入userService,用于测试业务逻辑。

•@MockBean

创建一个模拟的userRepository,替代真实的数据库操作。

2.3 Repository 层:数据操作基础校验

测试目标:验证JPA实体映射、基础查询逻辑。

工具:@DataJpaTest 默认使用内存数据库H2。

实战示例

@DataJpaTest  // 启动 JPA 相关的测试环境,通常用于测试 Repository 层

public class UserRepositoryTest {

    @Autowired private TestEntityManager entityManager;  // 用于与数据库进行交互,执行持久化操作

    @Autowired private UserRepository userRepository;  // 自动注入 UserRepository,用于测试数据访问方法

    @Test  // 标记为测试方法
    void findByEmail_ExistingEmail_ReturnsUser() {

        // 创建一个用户对象并持久化到数据库
        User user = new User("test@example.com");
        entityManager.persist(user);

        // 调用 UserRepository 方法,根据 email 查找用户
        User found = userRepository.findByEmail("test@example.com");

        // 断言返回的用户对象不为 null
        assertThat(found).isNotNull();

    }

}

关键点:

•TestEntityManager 手动管理测试数据。

•默认隔离真实数据库,确保快速执行。

单元测试的优势:

•快速执行,约 50 毫秒/测试。

•精准定位问题。

三、集成测试:全链路一致性保证

3.1 垂直集成测试(应用内全链路)

测试目标:验证应用内各层的完整调用链。

工具组合

•@SpringBootTest:启动 Spring Boot 应用测试环境,进行全链路集成测试。

•@Testcontainers:通过 Docker 启动真实数据库容器(如 PostgreSQL)。

•@AutoConfigureMockMvc:自动配置MockMvc,用于模拟 HTTP 请求。

•@Container:定义 Testcontainers 容器,启动真实数据库实例。

•OrderRepository:验证数据是否已保存至数据库。

代码示例

@SpringBootTest
@AutoConfigureMockMvc
@Testcontainers
public class OrderIntegrationTest {

    @Autowired
    private MockMvc mockMvc; // 模拟 HTTP 请求

    @Autowired
    private OrderRepository orderRepository;  // 注入 Repository 层以验证数据库

    @Container
    public static PostgreSQLContainer postgres = new PostgreSQLContainer("postgres:latest")
            .withDatabaseName("testdb")
            .withUsername("test")
            .withPassword("password");

    @Test
    void createOrder_ValidRequest_OrderIsSaved() throws Exception {
        // 发送请求创建订单
        mockMvc.perform(post("/orders")
               .contentType(MediaType.APPLICATION_JSON)
               .content("{ \"productId\": 1 }"))
               .andExpect(status().isCreated());

        // 验证数据库中是否有保存的订单
        Order order = orderRepository.findByProductId(1);
        assertThat(order).isNotNull();
        assertThat(order.getProductId()).isEqualTo(1);
    }
}

3.2 水平集成测试(跨服务交互)

测试目标:验证与外部服务的真实交互(如支付网关),确保跨服务的协议兼容性。

工具组合

•@SpringBootTest

•@Testcontainers:启动模拟的外部服务容器(如 WireMock)。

•WireMockServer:模拟外部服务的响应,进行服务间的交互测试。

•@BeforeAll / @AfterAll:在测试执行前后配置和清理模拟服务。

代码示例

@SpringBootTest
@Testcontainers
public class PaymentServiceIntegrationTest {

    @Autowired
    private PaymentService paymentService;

    @Container
    public static WireMockServer wireMockServer = new WireMockServer(options().port(8089));  // 设置外部服务模拟

    @BeforeAll
    static void setup() {
        wireMockServer.start();
        configureFor("localhost", 8089);
        stubFor(post(urlEqualTo("/payment"))
                .willReturn(aResponse()
                        .withStatus(200)
                        .withBody("{\"status\": \"success\"}")));
    }

    @AfterAll
    static void teardown() {
        wireMockServer.stop();
    }

    @Test
    void processPayment_ValidRequest_ReturnsSuccess() {
        // 模拟支付服务调用
        PaymentRequest paymentRequest = new PaymentRequest(1, 100);
        PaymentResponse response = paymentService.processPayment(paymentRequest);

        // 验证支付处理是否成功
        assertThat(response.getStatus()).isEqualTo("success");
    }
}

解析

•WireMockServer:模拟外部支付服务。

•PaymentService:调用外部支付服务并验证支付结果。

3.3 持久层的集成测试

测试目标:验证应用与真实数据库、中间件的交互逻辑。

工具组合

•Testcontainers:启动真实数据库(如MySQL、PostgreSQL)。

•@DynamicPropertySource:动态注入测试环境配置。

•@DataJpaTest:聚焦 JPA 层测试,自动配置 H2 或真实数据库。

实战示例

@Testcontainers  // 启动容器化的数据库实例(这里使用 PostgreSQL)
@DataJpaTest  // 启动 JPA 测试环境,只加载与 JPA 相关的配置。
@AutoConfigureTestDatabase(replace = NONE)  // 禁用 Spring Boot 默认的内存数据库配置,使用实际的 PostgreSQL 容器

public class UserRepositoryIntegrationTest {

    @Container
    static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15");  // 启动 PostgreSQL 容器,使用官方 15 版本

    @DynamicPropertySource  // 动态配置数据库连接属性
    static void configure(DynamicPropertyRegistry registry) {
        registry.add("spring.datasource.url", postgres::getJdbcUrl);  // 配置数据库连接 URL
        registry.add("spring.datasource.username", postgres::getUsername);  // 配置数据库用户名
        registry.add("spring.datasource.password", postgres::getPassword);  // 配置数据库密码
    }

    @Test 
    void saveUser_PersistsToRealDatabase() {

        // 创建用户并保存到数据库
        User user = new User("IntegrationTest");
        userRepository.save(user);

        // 断言数据库中保存的用户数量为 1
        assertThat(userRepository.findAll()).hasSize(1);
    }
}

1.注解解析

@DataJpaTest

•专注于 JPA 层(JPA repository 或数据访问层操作)的测试,自动配置一个嵌入式数据库并扫描@Entity类。

@AutoConfigureTestDatabase(replace = NONE)

•禁用默认的嵌入式数据库(如 H2),使用外部数据库(如 PostgreSQL容器)进行测试。

@Container

•标记一个静态的、全局共享的容器实例,为测试提供服务。

@DynamicPropertySource

•动态配置 Spring 环境的属性,常用于设置容器生成的数据库连接信息。

优势:真实数据库行为模拟,避免H2与生产数据库的差异问题。

四、契约测试:消费者驱动的接口保卫者

契约测试(Consumer-Driven Contract,CDC)用于确保服务提供者与消费者对接口的理解一致,防止因接口变更引发故障。

4.1 核心流程

participant Consumer as 消费者
participant PactBroker as Pact Broker
participant Provider as 提供者

Consumer->>PactBroker: 1. 定义并发布契约
PactBroker->>Provider: 2. 通知契约变更
Provider->>PactBroker: 3. 验证实现是否符合契约
PactBroker->>Consumer: 4. 反馈验证结果

4.2 技术组合

•Pact:定义消费者期望的接口契约

•@PactTestFor:绑定契约与测试用例

•Pact Broker:集中管理契约版本

4.3 实战示例

1.消费者端定义契约

// OrderService(消费者端)定义契约
@Pact(consumer = "OrderService", provider = "PaymentService")
public RequestResponsePact paymentSuccessPact(PactDslWithProvider builder) {
    return builder
        // 提供者状态:订单已创建,待支付(需在提供者端实现数据准备)
        .given("订单已创建,待支付") 
        // 消费者请求描述
        .uponReceiving("支付订单的请求")
        .method("POST")
        .path("/payments")
        .headers("Content-Type", "application/json") // 必须声明请求头
        .body(new PactDslJsonBody()
            .integerType("orderId", 1001)  // 订单ID为整数类型
            .decimalType("amount", 299.99) // 金额为小数类型
        )
        // 提供者预期响应
        .willRespondWith()
        .status(200)
        .headers(Map.of("Content-Type", "application/json")) // 响应头校验
        .body(new PactDslJsonBody()
            .stringType("status", "SUCCESS") // 状态必须为字符串且值=SUCCESS
            .stringType("transactionId", "TX123456") // 交易ID必须为字符串
        )
        .toPact(); // 生成Pact契约文件
}

2.消费者端基于契约测试

@Test
@PactTestFor(
    pactMethod = "paymentSuccessPact", 
    providerName = "PaymentService", // 指定提供者名称
    pactVersion = PactSpecVersion.V3 // 使用Pact协议V3
)
void testPayment_WhenValidRequest_ReturnsSuccess(MockServer mockServer) {
    // 1. 创建HTTP客户端,指向MockServer(模拟的PaymentService)
    WebClient client = WebClient.create(mockServer.getUrl());

    // 2. 构造请求并发送
    PaymentRequest request = new PaymentRequest(1001, 299.99);
    PaymentResponse response = client.post()
        .uri("/payments")
        .contentType(MediaType.APPLICATION_JSON)
        .bodyValue(request)
        .retrieve()
        .bodyToMono(PaymentResponse.class)
        .block(); // 同步等待响应

    // 3. 断言响应符合契约
    assertThat(response).isNotNull();
    assertThat(response.getStatus()).isEqualTo("SUCCESS");
    assertThat(response.getTransactionId()).isEqualTo("TX123456");
}

3.提供者端验证契约

目标:验证 PaymentService 的实现是否符合消费者定义的契约。

Step1. 提供者端代码实现

// PaymentService(提供者端)的Controller实现
@RestController
public class PaymentController {

    @PostMapping("/payments")
    public ResponseEntity<PaymentResponse> processPayment(
        @RequestBody PaymentRequest request
    ) {
        // 业务逻辑:处理支付请求
        PaymentResponse response = new PaymentResponse();
        response.setStatus("SUCCESS");
        response.setTransactionId("TX" + UUID.randomUUID().toString().substring(0, 6));
        return ResponseEntity.ok(response);
    }
}

Step2. 提供者端 Pact 验证配置(build.gradle)

// 添加Pact验证插件

plugins {
    id "au.com.dius.pact" version "4.6.8"
}

dependencies {
    // Pact提供者端依赖
    testImplementation 'au.com.dius.pact.provider:junit5:4.6.8'
}

// 配置Pact验证任务

pact {
    serviceProviders {
        PaymentService { // 提供者名称(需与契约中的provider一致)
            protocol = 'http'
            host = 'localhost'
            port = 8080 // 本地服务端口

            // 定义契约来源(本地文件或Pact Broker)
            hasPactWith('OrderService') {
                pactSource = file("path/to/OrderService-PaymentService.json")
            }
        }
    }
}

Step3: 提供者端状态准备(State Handler)

// 实现契约中的 given(“订单已创建,待支付”)

public class PaymentStateHandler {
    @BeforeRequest("订单已创建,待支付")
    public void setupOrderState(Map<String, Object> params) {
        // 模拟订单已创建的数据库操作
        Order order = new Order(1001, 299.99);
        orderRepository.save(order);
    }
}

Step4: 提供者端测试类

@Provider("PaymentService") // 声明提供者名称
@PactFolder("pacts") // 契约文件路径
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
public class PaymentServiceContractTest {
    @TestTemplate
    @ExtendWith(PactVerificationSpringProvider.class)
    void pactVerificationTestTemplate(PactVerificationContext context) {
        context.verifyInteraction();
    }
    @BeforeEach
    void before(PactVerificationContext context) {
        // 设置服务状态处理器
        context.setTarget(HttpTestTarget.fromUrl(new UrlParser().parse("http://localhost:8080")));
    }
}

Step5: 执行验证命令

# 在提供者端执行验证(确保服务已启动)
./gradlew pactVerify -Dpact.provider.version=1.0.0

4.4.契约测试总结

通过上述步骤,契约测试完整覆盖了消费者与提供者的协作流程:

1.消费者定义契约:明确接口预期行为。

2.消费者本地验证:通过MockServer模拟提供者。

3.提供者实现接口:按契约开发功能。

4.提供者验证契约:确保实现与契约一致。

契约测试优势

•解耦团队协作,契约即文档。

•自动检测接口变更引发的破坏性修改。

五、总结:构建测试体系

5.1 测试策略全景图

Spring Boot分层架构   
 A[客户端] -->|HTTP 请求| B[Controller 层]    
 B -->|调用| C[Service 层]    
 C -->|调用| D[Repository 层]  
 D -->|操作| E[数据库] 
 E -->|调用| F[外部服务接口]   
   
测试策略全景   
单元测试    
B1[Controller 单元测试] -->|@WebMvcTest + MockMvc| B    
C1[Service 单元测试] -->|@MockBean| C    
D1[Repository 单元测试] -->|@DataJpaTest| D

集成测试    
Int1[全链路调用] --> B --> C --> D --> |Testcontainers + 真实数据库| E    
Int2[水平集成测试] --> F


契约测试    
Contract1[消费者契约测试] -->|Pact 定义期望接口+本地验证| F   
Contract2[提供者契约测试] -->|Pact 验证实现| F    

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

(十 三)趣学设计模式 之 模版方法模式!

目录 一、 啥是模板方法模式&#xff1f;二、 为什么要用模板方法模式&#xff1f;三、 模板方法模式的实现方式四、 模板方法模式的优缺点五、 模板方法模式的应用场景六、 总结 &#x1f31f;我的其他文章也讲解的比较有趣&#x1f601;&#xff0c;如果喜欢博主的讲解方式&a…

汽车刹车系统设计

摘 要 本次设计内容为汽车刹车系统&#xff0c;其可靠性与驾驶人的生命息息相关&#xff0c;是汽车所有组成部分中最重要的一环。刹车系统是在车辆行驶过程中出现紧急情况时首先保护车辆与驾驶人员安全的反应系统&#xff0c;工作原理是依靠制动装置工作时产生的大量摩擦力来抵…

卷积神经网络梯度下降方向与参数更新方向的一致性论述

梯度下降是一种常用的优化算法&#xff0c;用于最小化损失函数&#xff0c;在机器学习和深度学习领域有着广泛的应用。分别对梯度下降、梯度方向以及参数更新采用负梯度方向的原因进行论述。 1.梯度下降 它的基本思想是通过迭代的方式来更新模型的参数&#xff0c;使得损失函数…

Starrocks入门(二)

1、背景&#xff1a;考虑到Starrocks入门这篇文章&#xff0c;安装的是3.0.1版本的SR&#xff0c;参考&#xff1a;Starrocks入门-CSDN博客 但是官网的文档&#xff0c;没有对应3.0.x版本的资料&#xff0c;却有3.2或者3.3或者3.4或者3.1或者2.5版本的资料&#xff0c;不要用较…

可以免费无限次下载PPT的网站

前言 最近发现了一个超实用的网站&#xff0c;想分享给大家。 在学习和工作的过程中&#xff0c;想必做PPT是一件让大家都很头疼的一件事。 想下载一些PPT模板减少做PPT的工作量&#xff0c;但网上大多精美的PPT都是需要付费才能下载使用。 即使免费也有次数限制&#xff0…

[Java基础] JVM常量池介绍(BeanUtils.copyProperties(source, target)中的属性值引用的是同一个对象吗)

文章目录 1. JVM内存模型2. 常量池中有什么类型&#xff1f;3. 常量池中真正存储的内容是什么4. 判断一个字符串(引用)是否在常量池中5. BeanUtils.copyProperties(source, target)中的属性值引用的是同一个对象吗&#xff1f;6. 获取堆内存使用情况、非堆内存使用情况 1. JVM内…

DeepSeek模型昇腾部署优秀实践

2024年12月26日&#xff0c;DeepSeek-V3横空出世&#xff0c;以其卓越性能备受瞩目。该模型发布即支持昇腾&#xff0c;用户可在昇腾硬件和MindIE推理引擎上实现高效推理&#xff0c;但在实际操作中&#xff0c;部署流程与常见问题困扰着不少开发者。本文将为你详细阐述昇腾 De…

python编写liunx服务器登陆自动巡检脚本

前言&#xff1a; 用户需要一份用Python编写的Linux系统巡检脚本&#xff0c;检查内存、磁盘、CPU使用率&#xff0c;还有网络连通性。 首先&#xff0c;我得确定用户的使用场景。可能用户是系统管理员&#xff0c;需要定期监控服务器状态&#xff0c;确保系统正常运行。 或者…

鸿蒙 ArkUI 实现敲木鱼小游戏

敲木鱼是一款具有禅意的趣味小游戏&#xff0c;本文将通过鸿蒙 ArkUI 框架的实现代码&#xff0c;逐步解析其核心技术点&#xff0c;包括动画驱动、状态管理、音效震动反馈等。 一、架构设计与工程搭建 1.1 项目结构解析 完整项目包含以下核心模块&#xff1a; ├── entry…

ShenNiusModularity项目源码学习(14:ShenNius.Infrastructure项目分析)

ShenNius.Infrastructure项目用于定义ShenNius.Admin.Mvc项目和ShenNius.Admin.API项目共用的特性类、数据操作接口实现类、上下文类、通讯类&#xff0c;主要文件的用途如下&#xff1a;   Attributes文件夹保存特性类或过滤器类定义&#xff0c;主要包括&#xff1a;   …

Mysql表字段字符集未设置导致乱码问题

项目场景&#xff1a; 在使用mysql的text类型作为字段类型【未设置编码】&#xff0c;且表结构【设置了编码集】的条件下&#xff0c;查询表这个字段会出现乱码的情况。 问题描述 今日测试小伙伴给题主提出了一个bug&#xff0c;数据库当中的text文本字段在存储json的情况下&…

staruml绘制时序图和用例图

文章目录 1.文章介绍2.绘制用例图3.绘制时序图 1.文章介绍 之前&#xff0c;我们初步介绍了这个staruml软件的安装和如何使用这个软件对于uml类图进行绘制&#xff0c;当时我们是绘制了这个user类&#xff0c;实现了相关的接口&#xff0c;表示他们之间的关系&#xff0c;在今…

火狐浏览器多开指南:独立窗口独立IP教程

无论是跨境电商从业者需要管理多个店铺账号&#xff0c;还是海外社交媒体营销人员要运营多个社交平台账号&#xff0c;亦或是从事多账号广告投放的人员&#xff0c;都面临着一个共同的挑战 —— 如何高效管理多个账号&#xff0c;并确保每个账号的独立性。 在这种情况下&#…

DeepSeek赋能大模型内容安全,网易易盾AIGC内容风控解决方案三大升级

在近两年由AI引发的生产力革命的背后&#xff0c;一场关乎数字世界秩序的攻防战正在上演&#xff1a;AI生成的深度伪造视频导致企业品牌声誉损失日均超千万&#xff0c;批量生成的侵权内容使版权纠纷量与日俱增&#xff0c;黑灰产利用AI技术持续发起欺诈攻击。 与此同时&#…

【论文精读】YOLO-World:实时开放词汇目标检测

论文地址&#xff1a; YOLO-World: Real-Time Open-Vocabulary Object Detection 源代码&#xff1a;YOLO-World 摘要 YOLO系列检测器因其高效性和实用性而被广泛认可。然而&#xff0c;它们依赖于预定义和训练过的物体类别&#xff0c;这限制了其在开放场景中的适用性。为了…

开放标准(RFC 7519):JSON Web Token (JWT)

开放标准&#xff1a;JSON Web Token 前言基本使用整合Shiro登录自定义JWT认证过滤器配置Config自定义凭证匹配规则接口验证权限控制禁用session缓存的使用登录退出单用户登录Token刷新双Token方案单Token方案 前言 JSON Web Token &#xff08;JWT&#xff09; 是一种开放标准…

mysql架构查询执行流程(图解+描述)

目录 mysql架构查询执行流程 图解 描述 mysql架构查询执行流程 图解 描述 用户连接到数据库后&#xff0c;由连接器处理 连接器负责跟客户端建立连接、获取权限、维持和管理连接 客户端发送一条查询给服务器 服务器先检查查询缓存&#xff0c;如果命中缓存&#xff0c;则立…

k8s使用containerd作为容器运行时配置Harbor私有仓库与阿里云私有仓库以及镜像加速器,k8s基于containerd如何配置harbor私有仓库

至于containerd大家还需要在去学习以下使用的命令。 版本介绍 k8s&#xff1a;v1.28.2containerd&#xff1a;1.6.33 1.配置containerd镜像加速器 [rootmaster ~]# vim /etc/containerd/config.toml ---编辑containerd配置文件找到以下位置新添加 [plugins."io.contain…

【MySql】EXPLAIN执行计划全解析:15个字段深度解读与调优指南

文章目录 一、执行计划核心字段总览二、关键字段深度拆解1. type&#xff08;访问类型&#xff09;——查询性能的晴雨表典型场景分析&#xff1a; 2. key_len&#xff08;索引使用长度&#xff09;——索引利用率的检测仪计算示例&#xff1a; 3. Extra&#xff08;附加信息&a…

python-leetcode-最长有效括号

32. 最长有效括号 - 力扣&#xff08;LeetCode&#xff09; class Solution:def longestValidParentheses(self, s: str) -> int:stack [-1] # 存储索引&#xff0c;初始值 -1 代表“未匹配起点”max_length 0for i, char in enumerate(s):if char (:stack.append(i)els…