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

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 {@Autowiredprivate MockMvc mockMvc;//模拟UserService,用于提供预定义的行为。@MockBeanprivate UserService userService;@Testvoid 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,替代真实的数据库操作@MockBeanprivate UserRepository userRepository;@Testvoid 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 方法被调用}@Testvoid 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");// 断言返回的用户对象不为 nullassertThat(found).isNotNull();}}

关键点:

•TestEntityManager 手动管理测试数据。

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

单元测试的优势:

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

•精准定位问题。

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

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

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

工具组合

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

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

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

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

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

代码示例

@SpringBootTest
@AutoConfigureMockMvc
@Testcontainers
public class OrderIntegrationTest {@Autowiredprivate MockMvc mockMvc; // 模拟 HTTP 请求@Autowiredprivate OrderRepository orderRepository;  // 注入 Repository 层以验证数据库@Containerpublic static PostgreSQLContainer postgres = new PostgreSQLContainer("postgres:latest").withDatabaseName("testdb").withUsername("test").withPassword("password");@Testvoid 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 {@Autowiredprivate PaymentService paymentService;@Containerpublic static WireMockServer wireMockServer = new WireMockServer(options().port(8089));  // 设置外部服务模拟@BeforeAllstatic void setup() {wireMockServer.start();configureFor("localhost", 8089);stubFor(post(urlEqualTo("/payment")).willReturn(aResponse().withStatus(200).withBody("{\"status\": \"success\"}")));}@AfterAllstatic void teardown() {wireMockServer.stop();}@Testvoid 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 {@Containerstatic PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15");  // 启动 PostgreSQL 容器,使用官方 15 版本@DynamicPropertySource  // 动态配置数据库连接属性static void configure(DynamicPropertyRegistry registry) {registry.add("spring.datasource.url", postgres::getJdbcUrl);  // 配置数据库连接 URLregistry.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);// 断言数据库中保存的用户数量为 1assertThat(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();}@BeforeEachvoid 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    

相关文章:

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

一、Spring Boot 分层测试策略 Spring Boot 应用采用经典的分层架构&#xff0c;不同层级的功能模块对应不同的测试策略&#xff0c;以确保代码质量和系统稳定性。 Spring Boot 分层架构&#xff1a; Spring Boot分层架构 A[客户端] -->|HTTP 请求| B[Controller 层] …...

Oracle 数据库基础入门(四):分组与联表查询的深度探索(上)

在 Oracle 数据库的学习进程中&#xff0c;分组查询与联表查询是进阶阶段的重要知识点&#xff0c;它们如同数据库操作的魔法棒&#xff0c;能够从复杂的数据中挖掘出有价值的信息。对于 Java 全栈开发者而言&#xff0c;掌握这些技能不仅有助于高效地处理数据库数据&#xff0…...

机器学习的起点:线性回归Linear Regression

机器学习的起点&#xff1a;线性回归Linear Regression 作为机器学习的起点&#xff0c;线性回归是理解算法逻辑的绝佳入口。我们从定义、评估方法、应用场景到局限性&#xff0c;用生活化的案例和数学直觉为你构建知识框架。 回归算法 一、线性回归的定义与核心原理 定义&a…...

2024贵州大学计算机考研复试上机真题

历年贵州大学计算机考研复试上机真题 2024贵州大学计算机考研复试上机真题 2023贵州大学计算机考研复试上机真题 贵州大学计算机考研复试上机真题 在线 oj 测评&#xff1a;https://app2098.acapp.acwing.com.cn/problem/list/ 字符串翻转 题目描述 给定一个字符串&#xf…...

17、什么是智能指针,C++有哪几种智能指针【高频】

智能指针其实不是指针&#xff0c;而是一个&#xff08;模板&#xff09;类&#xff0c;用来存储指向某块资源的指针&#xff0c;并自动释放这块资源&#xff0c;从而解决内存泄漏问题。主要有以下四种&#xff1a; auto_ptr 它的思想就是当当一个指针对象赋值给另一个指针对…...

PyCharm接入本地部署DeepSeek 实现AI编程!【支持windows与linux】

今天尝试在pycharm上接入了本地部署的deepseek&#xff0c;实现了AI编程&#xff0c;体验还是很棒的。下面详细叙述整个安装过程。 本次搭建的框架组合是 DeepSeek-r1:1.5b/7b Pycharm专业版或者社区版 Proxy AI&#xff08;CodeGPT&#xff09; 首先了解不同版本的deepsee…...

深入解析SQL Server高级SQL技巧

SQL Server 是一种功能强大的关系型数据库管理系统&#xff0c;广泛应用于各种数据驱动的应用程序中。在开发过程中&#xff0c;掌握一些高级SQL技巧&#xff0c;不仅能提高查询性能&#xff0c;还能优化开发效率。这篇文章将全面深入地探讨SQL Server中的一些高级技巧&#xf…...

PyCharm怎么集成DeepSeek

PyCharm怎么集成DeepSeek 在PyCharm中集成DeepSeek等大语言模型(LLM)可以借助一些插件或通过代码调用API的方式实现,以下为你详细介绍两种方法: 方法一:使用JetBrains AI插件(若支持DeepSeek) JetBrains推出了AI插件来集成大语言模型,不过截至2024年7月,官方插件主要…...

Hive之正则表达式RLIKE详解及示例

目录 一、RLIKE 语法及核心特性 1. 基本语法 2. 核心特性 二、常见业务场景及示例 场景1&#xff1a;过滤包含特定模式的日志&#xff08;如错误日志&#xff09; 场景2&#xff1a;验证字段格式&#xff08;如邮箱、手机号&#xff09; 场景3&#xff1a;提取复杂文本中…...

fluent-ffmpeg 依赖详解

fluent-ffmpeg 是一个用于在 Node.js 环境中与 FFmpeg 进行交互的强大库&#xff0c;它提供了流畅的 API 来执行各种音视频处理任务&#xff0c;如转码、剪辑、合并等。 一、安装 npm install fluent-ffmpeg二、基本使用 要使用 fluent-ffmpeg&#xff0c;首先需要确保系统中…...

【定昌Linux系统】部署了java程序,设置开启启动

将代码上传到相应的目录&#xff0c;并且配置了一个.sh的启动脚本文件 文件内容&#xff1a; #!/bin/bash# 指定JAR文件的路径&#xff08;如果JAR文件在当前目录&#xff0c;可以直接使用文件名&#xff09; JAR_FILE"/usr/local/java/xs_luruan_client/lib/xs_luruan_…...

Java零基础入门笔记:(7)异常

前言 本笔记是学习狂神的java教程&#xff0c;建议配合视频&#xff0c;学习体验更佳。 【狂神说Java】Java零基础学习视频通俗易懂_哔哩哔哩_bilibili 第1-2章&#xff1a;Java零基础入门笔记&#xff1a;(1-2)入门&#xff08;简介、基础知识&#xff09;-CSDN博客 第3章…...

【字符串】最长公共前缀 最长回文子串

文章目录 14. 最长公共前缀解题思路&#xff1a;模拟5. 最长回文子串解题思路一&#xff1a;动态规划解题思路二&#xff1a;中心扩散法 14. 最长公共前缀 14. 最长公共前缀 ​ 编写一个函数来查找字符串数组中的最长公共前缀。 ​ 如果不存在公共前缀&#xff0c;返回空字符…...

【软路由】ImmortalWrt 编译指南:从入门到精通

对于喜欢折腾路由器&#xff0c;追求极致性能和定制化的玩家来说&#xff0c;OpenWrt 无疑是一个理想的选择。而在众多 OpenWrt 衍生版本中&#xff0c;ImmortalWrt 以其更活跃的社区、更激进的特性更新和对新硬件的支持而备受关注。 本文将带你深入了解 ImmortalWrt&#xff0…...

react 中,使用antd layout布局中的sider 做sider的展开和收起功能

一 话不多说&#xff0c;先展示效果&#xff1a; 展开时&#xff1a; 收起时&#xff1a; 二、实现代码如下 react 文件 import React, {useState} from react; import {Layout} from antd; import styles from "./index.module.less"; // 这个是样式文件&#…...

easyExcel使用案例有代码

easyExcel 入门,完成web的excel文件创建和导出 easyExcel官网 EasyExcel 的主要特点如下&#xff1a; 1、高性能&#xff1a;EasyExcel 采用了异步导入导出的方式&#xff0c;并且底层使用 NIO 技术实现&#xff0c;使得其在导入导出大数据量时的性能非常高效。 2、易于使…...

CPU、SOC、MPU、MCU--详细分析四者的区别

一、CPU 与SOC的区别 1.CPU 对于电脑&#xff0c;我们经常提到&#xff0c;处理器&#xff0c;内存&#xff0c;显卡&#xff0c;硬盘四大部分可以组成一个基本的电脑。其中的处理器——Central Processing Unit&#xff08;中央处理器&#xff09;。CPU是一台计算机的运算核…...

机器学习:监督学习、无监督学习和强化学习

机器学习&#xff08;Machine Learning, ML&#xff09;是人工智能&#xff08;AI&#xff09;的一个分支&#xff0c;它使计算机能够从数据中学习&#xff0c;并在没有明确编程的情况下执行任务。机器学习的核心思想是使用算法分析数据&#xff0c;识别模式&#xff0c;并做出…...

SpringBoot项目注入 traceId 来追踪整个请求的日志链路

SpringBoot项目注入 traceId 来追踪整个请求的日志链路&#xff0c;有了 traceId&#xff0c; 我们在排查问题的时候&#xff0c;可以迅速根据 traceId 查找到相关请求的日志&#xff0c;特别是在生产环境的时候&#xff0c;用户可能只提供一个错误截图&#xff0c;我们作为开发…...

苹果廉价机型 iPhone 16e 影像系统深度解析

【人像拍摄差异】 尽管iPhone 16e支持后期焦点调整功能&#xff0c;但用户无法像iPhone 16系列那样通过点击屏幕实时切换拍摄主体。前置摄像头同样缺失人像深度控制功能&#xff0c;不过TrueTone原彩闪光灯系统在前后摄均有保留。 很多人都高估了 iPhone 的安全性&#xff0c;查…...

视觉图像坐标转换

1. 透镜成像 相机的镜头系统将三维场景中的光线聚焦到一个平面&#xff08;即传感器&#xff09;。这个过程可以用小孔成像模型来近似描述&#xff0c;尽管实际相机使用复杂的透镜系统来减少畸变和提高成像质量。 小孔成像模型&#xff1a; 假设有一个理想的小孔&#xff0c;…...

汽车电子电控软件开发中因复杂度提升导致的架构恶化问题

针对汽车电子电控软件开发中因复杂度提升导致的架构恶化问题&#xff0c;建议从以下方向进行架构优化和开发流程升级&#xff0c;以提升灵活性、可维护性和扩展性&#xff1a; 一、架构设计与模块化优化 分层架构与模块解耦 采用AUTOSAR标准的分层架构&#xff08;应用层、运行…...

2024年第十五届蓝桥杯大赛软件赛省赛Python大学A组真题解析《更新中》

文章目录 试题A: 拼正方形(本题总分:5 分)解析答案试题B: 召唤数学精灵(本题总分:5 分)解析答案试题C: 数字诗意解析答案试题D:回文数组试题A: 拼正方形(本题总分:5 分) 【问题描述】 小蓝正在玩拼图游戏,他有7385137888721 个2 2 的方块和10470245 个1 1 的方块,他需…...

脚本无法获取响应主体(原因:CORS Missing Allow Credentials)

背景&#xff1a; 前端的端口号8080&#xff0c;后端8000。需在前端向后端传一个参数&#xff0c;让后端访问数据库去检测此参数是否出现过。涉及跨域请求&#xff0c;一直有这个bug是404文件找不到。 在修改过程当中不小心删除了一段代码&#xff0c;出现了这个bug&#xff0…...

leetcode第39题组合总和

原题出于leetcode第39题https://leetcode.cn/problems/combination-sum/description/题目如下&#xff1a; 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target &#xff0c;找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 &#xff0c;并以…...

在 macOS 系统上安装 kubectl

在 macOS 系统上安装 kubectl 官网&#xff1a;https://kubernetes.io/zh-cn/docs/tasks/tools/install-kubectl-macos/ 用 Homebrew 在 macOS 系统上安装 如果你是 macOS 系统&#xff0c;且用的是 Homebrew 包管理工具&#xff0c; 则可以用 Homebrew 安装 kubectl。 运行…...

SQLark 数据迁移|断点续迁已上线(Oracle-达梦)

数据迁移是 SQLark 最受企业和个人用户欢迎的功能之一&#xff0c;截止目前已帮助政府、金融、能源、通信等 50 家单位完成从 Oracle、MySQL 到达梦的全量迁移&#xff0c;自动化迁移成功率达 96% 以上。 在 Oracle 到达梦数据库迁移过程中&#xff0c;SQLark V3.3 新增 断点续…...

Element Plus中el-tree点击的节点字体变色加粗

el-tree标签设置 <el-tree class"tree":data"treeData":default-expand-all"true":highlight-current"true"node-click"onTreeNodeClick"><!-- 自定义节点内容&#xff0c;点击的节点字体变色加粗 --><!-- 动…...

vmware安装firepower ftd和fmc

在vmware虚拟机中安装cisco firepower下一代防火墙firepower threat defence&#xff08;ftd&#xff09;和管理中心firepower management center&#xff08;fmc&#xff09;。 由于没有cisco官网下载账号&#xff0c;无法下载其中镜像。使用eveng模拟器中的ftd和fmc虚拟镜像…...

计算机毕业设计SpringBoot+Vue.js医院资源管理系统(源码+文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…...