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

《Spring Boot 测试框架指南:@SpringBootTest与Mockito的最佳实践》

大家好呀!👋 今天我要和大家聊聊Spring Boot测试的那些事儿。作为一名Java开发者,写代码很重要,但写测试同样重要!💯 想象一下,你建了一座漂亮的房子🏠,但如果没有质量检查,你敢住进去吗?测试就是我们的"质量检查员"!今天重点介绍两个超级明星:@SpringBootTest和Mockito,保证让你学得明明白白!😊

📚 第一章:为什么要写测试?测试有多重要?

1.1 测试的重要性

先讲个小故事📖:小明写了一个计算器程序,能算加减乘除。他自信满满地交给老师,结果老师输入"5÷0",程序直接崩溃了💥!如果有测试,这种问题早就能发现啦!

测试的好处多多:

  • 🛡️ 防错保护:提前发现bug,避免上线后出问题
  • 🔄 安全重构:改代码时不担心破坏原有功能
  • 📝 文档作用:测试用例本身就是最好的使用示例
  • 持续集成:自动化测试是CI/CD的基础

1.2 Spring Boot测试生态

Spring Boot提供了一整套测试工具:

  • 🧪 @SpringBootTest:完整应用上下文测试
  • 🎭 Mockito:模拟对象和行为
  • 🏗️ TestEntityManager:数据库测试
  • 🌐 WebTestClient:WebFlux测试
  • 🖥️ MockMvc:Web MVC测试

今天我们先重点聊聊@SpringBootTest和Mockito这对黄金搭档!✨

🚀 第二章:@SpringBootTest - 你的应用完整测试工具

2.1 什么是@SpringBootTest?

@SpringBootTest就像是给你的Spring Boot应用做全身检查👨⚕️。它会启动几乎整个应用上下文,包括所有的bean、配置、数据库连接等等。

@SpringBootTest
class MyApplicationTests {@Autowiredprivate MyService myService; // 可以自动注入真实的bean@Testvoid contextLoads() {assertThat(myService).isNotNull();}
}

2.2 @SpringBootTest的几种模式

@SpringBootTest有三种启动模式,就像汽车的档位🚗:

  1. MOCK(默认):模拟Servlet环境,不启动真实服务器

    @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
    
  2. RANDOM_PORT:启动真实服务器,随机端口

    @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
    
  3. DEFINED_PORT:使用application.properties中定义的端口

    @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
    
  4. NONE:不提供任何Servlet环境

    @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
    

2.3 实际应用示例

假设我们有个用户服务:

@Service
public class UserService {@Autowiredprivate UserRepository userRepository;public User getUserById(Long id) {return userRepository.findById(id).orElseThrow(() -> new UserNotFoundException("User not found"));}
}

测试这个服务:

@SpringBootTest
class UserServiceTest {@Autowiredprivate UserService userService;@Autowiredprivate UserRepository userRepository;@Testvoid shouldGetUserById() {// 准备测试数据User testUser = new User(1L, "张三");userRepository.save(testUser);// 执行测试User result = userService.getUserById(1L);// 验证结果assertThat(result.getName()).isEqualTo("张三");}@Testvoid shouldThrowExceptionWhenUserNotFound() {assertThatThrownBy(() -> userService.getUserById(999L)).isInstanceOf(UserNotFoundException.class).hasMessageContaining("User not found");}
}

2.4 最佳实践

  1. 合理选择web环境:根据测试需求选择MOCK、RANDOM_PORT或NONE
  2. 使用@TestConfiguration:覆盖特定bean而不是全部配置
  3. 注意测试顺序:使用@DirtiesContext确保测试独立性
  4. 控制测试范围:不要过度使用@SpringBootTest,轻量级测试更高效

🎭 第三章:Mockito - 测试中的"替身演员"

3.1 什么是Mockito?

Mockito就像是电影里的替身演员🎬,它可以:

  • 创建虚拟对象(模拟对象)
  • 定义这些对象的行为
  • 验证它们是否被正确调用

为什么需要Mockito?因为单元测试应该独立!我们不希望测试UserService时,真的去调用数据库或第三方API。

3.2 Mockito核心功能

3.2.1 创建Mock对象
// 创建一个模拟的UserRepository
UserRepository mockRepo = Mockito.mock(UserRepository.class);

或者使用注解更简洁:

@Mock
private UserRepository userRepository;@BeforeEach
void setup() {MockitoAnnotations.openMocks(this); // 初始化@Mock注解
}
3.2.2 定义Mock行为
// 当调用findById(1L)时,返回预设的用户
Mockito.when(userRepository.findById(1L)).thenReturn(Optional.of(new User(1L, "张三")));// 当调用findById(999L)时,返回空
Mockito.when(userRepository.findById(999L)).thenReturn(Optional.empty());
3.2.3 验证交互
// 验证findById(1L)被调用了一次
Mockito.verify(userRepository, Mockito.times(1)).findById(1L);// 验证deleteById从未被调用
Mockito.verify(userRepository, Mockito.never()).deleteById(Mockito.anyLong());

3.3 Mockito与@SpringBootTest结合

使用@MockBean替换Spring上下文中的真实bean:

@SpringBootTest
class UserServiceMockTest {@Autowiredprivate UserService userService; // 真实服务@MockBeanprivate UserRepository userRepository; // 模拟仓库@Testvoid shouldGetUserByIdWithMock() {// 设置模拟行为Mockito.when(userRepository.findById(1L)).thenReturn(Optional.of(new User(1L, "张三")));// 调用真实服务方法User result = userService.getUserById(1L);// 验证assertThat(result.getName()).isEqualTo("张三");Mockito.verify(userRepository).findById(1L);}
}

3.4 Mockito高级技巧

3.4.1 参数匹配器
// 任何Long类型的ID
Mockito.when(userRepository.findById(Mockito.anyLong())).thenReturn(Optional.of(new User(1L, "默认用户")));// 特定条件的参数
Mockito.when(userRepository.findByName(Mockito.argThat(name -> name.length() > 5))).thenReturn(Optional.of(new User(1L, "长名字用户")));
3.4.2 抛出异常
Mockito.when(userRepository.save(Mockito.any())).thenThrow(new RuntimeException("数据库错误"));
3.4.3 连续调用不同结果
Mockito.when(userRepository.count()).thenReturn(10L)  // 第一次调用返回10.thenReturn(20L)  // 第二次返回20.thenThrow(new RuntimeException("太多调用")); // 第三次抛出异常
3.4.4 验证调用顺序
InOrder inOrder = Mockito.inOrder(userRepository);// 验证先调用findById,再调用save
inOrder.verify(userRepository).findById(1L);
inOrder.verify(userRepository).save(Mockito.any(User.class));

3.5 Mockito最佳实践

  1. 不要过度Mock:只Mock必要的依赖
  2. 验证适度:不要过度验证内部实现
  3. 保持简单:每个测试只关注一个行为
  4. 使用@Spy谨慎:@Spy是部分Mock,可能导致测试不稳定

🔧 第四章:测试中的常见问题与解决方案

4.1 测试速度慢怎么办?

@SpringBootTest启动整个应用,确实会比较慢🐢。解决方案:

  • 使用**@DataJpaTest**、@WebMvcTest等切片测试
  • 合理使用**@MockBean**减少真实bean加载
  • 共享测试上下文:@SpringBootTest + @DirtiesContext

4.2 数据库测试问题

测试时操作数据库📊要注意:

  • 使用嵌入式数据库(H2)加速测试
  • 每个测试后清理数据:
    @Transactional
    @Rollback  // 默认就是true
    @Test
    void testWithDatabase() { ... }
    
  • 或者手动清理:
    @AfterEach
    void tearDown() {userRepository.deleteAll();
    }
    

4.3 第三方服务依赖

对于外部API调用🌐:

  • 使用Mockito模拟
  • 使用WireMock模拟HTTP服务
  • 考虑契约测试(Pact)

4.4 测试Spring MVC

测试Controller层🖥️:

@WebMvcTest(UserController.class)
class UserControllerTest {@Autowiredprivate MockMvc mockMvc;@MockBeanprivate UserService userService;@Testvoid shouldReturnUser() throws Exception {Mockito.when(userService.getUserById(1L)).thenReturn(new User(1L, "张三"));mockMvc.perform(MockMvcRequestBuilders.get("/users/1")).andExpect(MockMvcResultMatchers.status().isOk()).andExpect(MockMvcResultMatchers.jsonPath("$.name").value("张三"));}
}

🏆 第五章:测试金字塔与策略

5.1 测试金字塔

健康的测试套件应该像金字塔🏛️:

  1. 单元测试(70%):测试单个类,快速执行
  2. 集成测试(20%):测试组件间交互
  3. 端到端测试(10%):测试完整应用流程

5.2 如何选择测试工具

测试类型适用场景推荐工具
纯业务逻辑Service层核心逻辑JUnit + Mockito
数据库交互Repository层@DataJpaTest + TestEntityManager
Web层Controller@WebMvcTest + MockMvc
完整流程应用启动到API调用@SpringBootTest + TestRestTemplate
客户端交互前端调用API@SpringBootTest + WebTestClient

5.3 测试命名规范

好的测试名应该像说明书📝:

  • 方法名说明测试场景和预期
  • 常用模式:[方法名]_[状态]_[预期]

例如:

@Test
void getUserById_withInvalidId_shouldThrowException() { ... }@Test
void saveUser_withValidUser_shouldReturnSavedUser() { ... }

🛠️ 第六章:实战演练 - 完整测试示例

让我们通过一个完整的用户管理系统示例来实践:

6.1 领域模型

@Entity
public class User {@Id @GeneratedValueprivate Long id;private String name;private String email;// getters/setters
}public interface UserRepository extends JpaRepository {Optional findByEmail(String email);
}

6.2 服务层

@Service
@Transactional
public class UserService {@Autowiredprivate UserRepository userRepository;public User registerUser(String name, String email) {if (userRepository.findByEmail(email).isPresent()) {throw new EmailAlreadyExistsException("Email already registered");}User user = new User();user.setName(name);user.setEmail(email);return userRepository.save(user);}public User getUserByEmail(String email) {return userRepository.findByEmail(email).orElseThrow(() -> new UserNotFoundException("User not found"));}
}

6.3 完整的测试套件

6.3.1 单元测试(Service层)
class UserServiceUnitTest {private UserService userService;@Mockprivate UserRepository userRepository;@BeforeEachvoid setUp() {userService = new UserService(userRepository);}@Testvoid registerUser_withNewEmail_shouldSaveUser() {// 准备String name = "张三";String email = "zhangsan@example.com";// 模拟findByEmail返回空Mockito.when(userRepository.findByEmail(email)).thenReturn(Optional.empty());// 模拟save返回用户User savedUser = new User(1L, name, email);Mockito.when(userRepository.save(Mockito.any(User.class))).thenReturn(savedUser);// 执行User result = userService.registerUser(name, email);// 验证assertThat(result.getId()).isNotNull();assertThat(result.getEmail()).isEqualTo(email);// 验证交互Mockito.verify(userRepository).findByEmail(email);Mockito.verify(userRepository).save(Mockito.any(User.class));}@Testvoid registerUser_withExistingEmail_shouldThrowException() {String email = "exists@example.com";// 模拟已存在用户Mockito.when(userRepository.findByEmail(email)).thenReturn(Optional.of(new User()));// 执行并验证异常assertThatThrownBy(() -> userService.registerUser("任何名字", email)).isInstanceOf(EmailAlreadyExistsException.class).hasMessageContaining("Email already registered");}
}
6.3.2 集成测试(Repository层)
@DataJpaTest
class UserRepositoryIntegrationTest {@Autowiredprivate TestEntityManager entityManager;@Autowiredprivate UserRepository userRepository;@Testvoid findByEmail_whenUserExists_shouldReturnUser() {// 保存测试用户User user = new User(null, "李四", "lisi@example.com");entityManager.persist(user);entityManager.flush();// 查询Optional found = userRepository.findByEmail(user.getEmail());// 验证assertThat(found).isPresent();assertThat(found.get().getName()).isEqualTo("李四");}@Testvoid findByEmail_whenUserNotExists_shouldReturnEmpty() {Optional found = userRepository.findByEmail("nonexistent@example.com");assertThat(found).isEmpty();}
}
6.3.3 完整集成测试
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class UserSystemIntegrationTest {@LocalServerPortprivate int port;@Autowiredprivate TestRestTemplate restTemplate;@Autowiredprivate UserRepository userRepository;@AfterEachvoid tearDown() {userRepository.deleteAll();}@Testvoid fullUserRegistrationFlow_shouldWork() {// 准备注册请求Map request = new HashMap<>();request.put("name", "王五");request.put("email", "wangwu@example.com");// 调用注册APIResponseEntity response = restTemplate.postForEntity("http://localhost:" + port + "/api/users",request,User.class);// 验证响应assertThat(response.getStatusCode()).isEqualTo(HttpStatus.CREATED);assertThat(response.getBody().getId()).isNotNull();assertThat(response.getBody().getEmail()).isEqualTo("wangwu@example.com");// 验证数据库Optional dbUser = userRepository.findByEmail("wangwu@example.com");assertThat(dbUser).isPresent();// 调用查询APIResponseEntity getResponse = restTemplate.getForEntity("http://localhost:" + port + "/api/users?email=wangwu@example.com",User.class);assertThat(getResponse.getStatusCode()).isEqualTo(HttpStatus.OK);assertThat(getResponse.getBody().getName()).isEqualTo("王五");}
}

🎯 第七章:测试覆盖率与质量门禁

7.1 测试覆盖率

测试覆盖率是衡量测试完整性的重要指标📊:

  • 行覆盖率:执行了多少百分比代码行
  • 分支覆盖率:是否覆盖了所有if-else分支
  • 变异测试:更高级的覆盖率分析

推荐阅读文章

  • 由 Spring 静态注入引发的一个线上T0级别事故(真的以后得避坑)

  • 如何理解 HTTP 是无状态的,以及它与 Cookie 和 Session 之间的联系

  • HTTP、HTTPS、Cookie 和 Session 之间的关系

  • 什么是 Cookie?简单介绍与使用方法

  • 什么是 Session?如何应用?

  • 使用 Spring 框架构建 MVC 应用程序:初学者教程

  • 有缺陷的 Java 代码:Java 开发人员最常犯的 10 大错误

  • 如何理解应用 Java 多线程与并发编程?

  • 把握Java泛型的艺术:协变、逆变与不可变性一网打尽

  • Java Spring 中常用的 @PostConstruct 注解使用总结

  • 如何理解线程安全这个概念?

  • 理解 Java 桥接方法

  • Spring 整合嵌入式 Tomcat 容器

  • Tomcat 如何加载 SpringMVC 组件

  • “在什么情况下类需要实现 Serializable,什么情况下又不需要(一)?”

  • “避免序列化灾难:掌握实现 Serializable 的真相!(二)”

  • 如何自定义一个自己的 Spring Boot Starter 组件(从入门到实践)

  • 解密 Redis:如何通过 IO 多路复用征服高并发挑战!

  • 线程 vs 虚拟线程:深入理解及区别

  • 深度解读 JDK 8、JDK 11、JDK 17 和 JDK 21 的区别

  • 10大程序员提升代码优雅度的必杀技,瞬间让你成为团队宠儿!

  • “打破重复代码的魔咒:使用 Function 接口在 Java 8 中实现优雅重构!”

  • Java 中消除 If-else 技巧总结

  • 线程池的核心参数配置(仅供参考)

  • 【人工智能】聊聊Transformer,深度学习的一股清流(13)

  • Java 枚举的几个常用技巧,你可以试着用用

  • 由 Spring 静态注入引发的一个线上T0级别事故(真的以后得避坑)

  • 如何理解 HTTP 是无状态的,以及它与 Cookie 和 Session 之间的联系

  • HTTP、HTTPS、Cookie 和 Session 之间的关系

  • 使用 Spring 框架构建 MVC 应用程序:初学者教程

  • 有缺陷的 Java 代码:Java 开发人员最常犯的 10 大错误

  • Java Spring 中常用的 @PostConstruct 注解使用总结

  • 线程 vs 虚拟线程:深入理解及区别

  • 深度解读 JDK 8、JDK 11、JDK 17 和 JDK 21 的区别

  • 10大程序员提升代码优雅度的必杀技,瞬间让你成为团队宠儿!

  • 探索 Lombok 的 @Builder 和 @SuperBuilder:避坑指南(一)

  • 为什么用了 @Builder 反而报错?深入理解 Lombok 的“暗坑”与解决方案(二)

相关文章:

《Spring Boot 测试框架指南:@SpringBootTest与Mockito的最佳实践》

大家好呀&#xff01;&#x1f44b; 今天我要和大家聊聊Spring Boot测试的那些事儿。作为一名Java开发者&#xff0c;写代码很重要&#xff0c;但写测试同样重要&#xff01;&#x1f4af; 想象一下&#xff0c;你建了一座漂亮的房子&#x1f3e0;&#xff0c;但如果没有质量检…...

《数据结构初阶》【时间复杂度 + 空间复杂度】

《数据结构初阶》【时间复杂度 空间复杂度】 前言&#xff1a;-----------------------------------------1. 什么是数据结构&#xff1f;2. 什么是算法&#xff1f; -----------------------------------------算法的时间复杂度和空间复杂度1. 为什么要引入时间复杂度和空间复…...

【深度学习—李宏毅教程笔记】Self-attention

目录 一、Self-attention 的引入 1、多样化的输入形式 2、典型的下游任务下游任务 3、传统“全连接 窗口”方法的局限 4、Self‑Attention 的引入 二、Self-attention 的架构 1、Self-attention层的框图表示 2、Self-attention 层的矩阵运算过程 三、Multi-head Self…...

PHP腾讯云人脸核身获取Access Token

参考腾讯云官方文档&#xff1a; 人脸核身 获取 Access Token_腾讯云 public function getAccessToken(){$data [appId > , //WBappid,https://cloud.tencent.com/document/product/1007/49634secret > ,grant_type > client_credential, //授权类型version > 1…...

pytorch基本操作2

torch.clamp 主要用于对张量中的元素进行截断&#xff08;clamping&#xff09;&#xff0c;将其限制在一个指定的区间范围内。 函数定义 torch.clamp(input, minNone, maxNone) → Tensor 参数说明 input 类型&#xff1a;Tensor 需要进行截断操作的输入张…...

Linux服务器配置Anaconda环境、Pytorch库(图文并茂的教程)

引言&#xff1a;为了方便后续新进组的 师弟/师妹 使用课题组的服务器&#xff0c;特此编文&#xff08;ps&#xff1a;我导从教至今四年&#xff0c;还未招师妹&#xff09; ✅ NLP 研 2 选手的学习笔记 笔者简介&#xff1a;Wang Linyong&#xff0c;NPU&#xff0c;2023级&a…...

idea 许可证过期

今天打开IDEA写代码突然提示&#xff1a;Your idea evaluation has expired. Your session will be limited to 30 minutes 评估已过期&#xff0c;您的会话将限制为 30 分钟。也就是说可以使用&#xff0c;但30min就会自动关闭 1 下载 ide-eval-resetter-2.1.6.zip https…...

Git常用命令分类汇总

Git常用命令分类汇总 一、基础操作 初始化仓库git init添加文件到暂存区git add file_name # 添加单个文件 git add . # 添加所有修改提交更改git commit -m "提交描述"查看仓库状态git status二、分支管理 创建/切换分支git branch branch_name …...

归并排序:数据排序的高效之道

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;…...

分布式训练(记录)

为什么要分布式训练&#xff1f; 单机训练有物理上限&#xff1a; 显存不够&#xff08;大模型根本放不下&#xff09; 单机计算慢&#xff08;数据量一多就耗时太长&#xff09; 多卡并行性不高 分布式训练的常见方式 Data Parallel&#xff08;数据并行&#xff09; 每个G…...

vue3中使用拖拽组件vuedragable@next

vue3中使用拖拽组件vuedragablenext 官网传送门 下载 npm install vuedraggablenext基本使用 <script setup> import draggable from vuedraggable import { ref } from vue const list ref([{ id:1,name:第一个 },{ id:2,name:第二个 },{ id:3,name:第三个 }, ]) <…...

Oracle、MySQL、PostgreSQL三大数据库对比分析

Oracle、MySQL、PostgreSQL 三大数据库的对比分析&#xff0c;结合 Java SpringBoot 项目开发 的实际场景&#xff0c;重点说明分库分表、主从复制的实现难度及案例。 一、数据库核心对比 1. 核心区别与适用场景 维度OracleMySQLPostgreSQL定位企业级商业数据库轻量级开源数据…...

java八股之并发编程

1.java线程和操作系统线程之间的区别&#xff1f; 现在java线程本质上是操作系统线程&#xff0c;java中采用的是一对一的线程模型&#xff08;一个用户线程对应一个内核进程&#xff09; 2.什么是进程和线程&#xff1f; 1.进程是操作系统一次执行&#xff0c;资源分配和调度的…...

Qt 入门 5 之其他窗口部件

Qt 入门 5 之其他窗口部件 本文介绍的窗口部件直接或间接继承自 QWidget 类详细介绍其他部件的功能与使用方法 1. QFrame 类 QFrame类是带有边框的部件的基类。它的子类包括最常用的标签部件QLabel另外还有 QLCDNumber、QSplitter,QStackedWidget,QToolBox 和 QAbstractScrol…...

Linux系统之----冯诺依曼结构

1.简要描述 冯诺依曼体系结构是现代计算机的基本设计思想&#xff0c;其核心理念是将计算机的硬件和软件统一为一个整体&#xff0c;通过存储程序的方式实现计算。冯诺依曼体系结构的核心思想是通过存储程序实现自动计算&#xff0c;其五大部件协同工作&#xff0c;奠定了现代…...

C++11新特性

目录 引入 C11新特性 统一的初始化列表 一切皆可{}初始化 std::initializer_list 统一的声明 auto decltype nullptr 范围for STL新增容器 STL新增容器接口 左值引用和右值引用 左值和右值 左值引用和右值引用 右值引用的优势(移动语义) 右值引用的使用场景 …...

492Q 型气缸盖双端面铣削组合铣床总体设计

一、引言 492Q 型气缸盖是发动机的重要组成部分&#xff0c;其双端面的加工精度对发动机的性能和可靠性有着重要影响。设计一款适用于 492Q 型气缸盖双端面铣削的组合铣床&#xff0c;能够提高加工效率和质量&#xff0c;满足发动机生产的需求。 二、总体设计要求 加工精度&…...

《软件设计师》复习笔记(4.2)——关系代数、函数依赖、范式

目录 一、关系代数 基本运算 笛卡尔积&#xff08;&#xff09; 投影&#xff08;π&#xff09; 选择&#xff08;σ&#xff09; 自然连接&#xff08;⋈&#xff09; 真题示例&#xff1a; 二、函数依赖 基本概念 Armstrong公理系统 键与约束 三、范式&#xff…...

IO流(二)

一、字符流 使用字节流可以读取文件中的字节数据。但是如果文件中有中文使用字节流来读取&#xff0c;就有可能读到半个汉字的情况&#xff0c;这样会导致乱码。虽然使用读取全部字节的方法不会出现乱码&#xff0c;但是如果文件过大又不太合适。 所以Java专门为我们提供了另…...

#Linux动态大小裁剪以及包大小变大排查思路

1 动态库裁剪 库分为动态库和静态库&#xff0c;动态库是在程序运行时才加载&#xff0c;静态库是在编译时就加载到程序中。动态库的大小通常比静态库小&#xff0c;因为动态库只包含了程序需要的函数和数据&#xff0c;而静态库则包含了所有的函数和数据。静态库可以理解为引入…...

天梯赛数据结构合集

1.集合操作&#xff1a;PTA | 程序设计类实验辅助教学平台 主要是注意set的取交集操作&#xff0c;AC代码&#xff1a; #include<bits/stdc.h> using namespace std; int n,m,k; set<int> a[60]; int main(){cin>>n;for(int i1;i<n;i){cin>>m;for…...

pdfjs库使用记录1

import React, { useEffect, useState, useRef } from react; import * as pdfjsLib from pdfjs-dist; // 设置 worker 路径 pdfjsLib.GlobalWorkerOptions.workerSrc /pdf.worker.min.js; const PDFViewer ({ url }) > { const [pdf, setPdf] useState(null); const […...

LIMS引领综合质检中心数字化变革,赋能质量强国战略

在质量强国战略的深入推进下&#xff0c;我国综合质检机构迎来了前所未有的发展机遇&#xff0c;同时也面临着诸多严峻挑战。随着检测领域从传统的食品药品监督向环境监测、新材料检测等新兴领域不断拓展&#xff0c;跨领域协同管理的复杂度呈指数级增长。作为提升产品质量的关…...

MySQL+Redis实战教程:从Docker安装部署到自动化备份与数据恢复20250418

MySQLRedis实战教程&#xff1a;从Docker安装部署到自动化备份与数据恢复 一、前言 在企业应用中&#xff0c;对MySQL和Redis运维的要求越来越高&#xff1a; 不能仅是启动就算部署运行稳定、隔离、访问控制、备份恢复、安全可靠&#xff0c;才是 企业级的基本功能 本文将手…...

嵌入式音视频开发指南:从MPP框架到QT实战全解析

嵌入式音视频开发指南:从MPP框架到QT实战全解析 一、音视频技术全景概述 1.1 技术演进里程碑 2003-2010年:标清时代(H.264/AVC + RTMP)2011-2018年:高清时代(H.265/HEVC + WebRTC)2019-至今:智能时代(AV1 + AI编解码 + 低延迟传输)1.2 现代音视频技术栈 #mermaid-s…...

如何使用Python进行自动化的系统管理?

Python已经成为系统管理员最流行的编程语言之一&#xff0c;因为它简单、灵活&#xff0c;并且广泛支持各种系统管理任务。无论您是自动执行重复性任务&#xff0c;管理文件和目录&#xff0c;还是处理用户权限&#xff0c;Python都提供了一组强大的工具来简化您的工作流程。 …...

拆机装机,通电主板亮灯风扇不转无法开机解决办法

电源开机线 重启线 usb耳机模块 灯线 看来电源没问题 参考https://zhidao.baidu.com/question/83939532/answer/2321171868.html 买了个新主板过几天到看看会不会好...

IntelliSense 已完成初始化,但在尝试加载文档时出错

系列文章目录 文章目录 系列文章目录前言一、原因二、使用步骤 前言 IntelliSense 已完成初始化&#xff0c;但在尝试加载文档时出错 File path: E:\QtExercise\DigitalPlatform\DigitalPlatform\main\propertyWin.ui Frame GUID:96fe523d-6182-49f5-8992-3bea5f7e6ff6 Frame …...

SuperMap iClient3D for WebGL 如何加载WMTS服务

在 SuperMap iClient3D for WebGL 中加载WMTS服务时&#xff0c;参数配置很关键&#xff01;下面我们详细介绍如何正确填写参数&#xff0c;确保影像服务完美加载。 一、数据制作 对于上述视频中的地图制作&#xff0c;此处不做讲述&#xff0c;如有需要可访问&#xff1a;Onl…...

[密码学实战]基于Python的国密算法与通用密码学工具箱

引言 在当今数字化浪潮中&#xff0c;信息安全已成为个人隐私保护与商业机密守护的核心议题。作为一位在密码学领域深耕多年的技术实践者&#xff0c;我深谙密码学工具在构建数字安全防线中的关键作用。正是基于这份认知与责任&#xff0c;我倾力打造了一款全方位、高性能的密…...

[密码学实战]详解gmssl库与第三方工具兼容性问题及解决方案

[密码学实战]详解gmssl库与第三方工具兼容性问题及解决方案 引言 国密算法&#xff08;SM2/SM3/SM4&#xff09;在金融、政务等领域广泛应用&#xff0c;但开发者在集成gmssl库实现SM2签名时&#xff0c;常遇到与第三方工具&#xff08;如OpenSSL、国密网关&#xff09;验证不…...

LIB-ZC, 一个跨平台(Linux)平台通用C/C++扩展库, stream 流操作

LIB-ZC, 一个跨平台(Linux)平台通用C/C扩展库, stream 流操作 lib-zc 封装了流操作命名空间 zcc基础类 stream(基类), iostream(io流封装) class stream 介绍 连接相关 // 都是虚函数, 为 iostream 等做准备virtual inline bool connect(const char *destination) { return …...

从零开始解剖Spring Boot启动流程:一个Java小白的奇幻冒险之旅

大家好呀&#xff01;今天我们要一起探索一个神奇的话题——Spring Boot的启动流程。我知道很多小伙伴一听到"启动流程"四个字就开始头疼&#xff0c;别担心&#xff01;我会用最通俗易懂的方式&#xff0c;带你从main()方法开始&#xff0c;一步步揭开Spring Boot的…...

概率多假设跟踪(PMHT):多目标跟踪中的概率软关联与高效跟踪算法解析

一、PMHT 的起源与核心定位 &#xff08;一&#xff09;背景 在多目标跟踪中&#xff0c;传统算法面临以下瓶颈&#xff1a; JPDA&#xff1a;单帧局部最优关联&#xff0c;无法处理跨帧长时间断联&#xff0c;且假设目标数固定&#xff08;如雷达跟踪中预设目标数范围&…...

4.信号和槽|存在意义|信号和槽的连接方式|信号和槽断开|lambda表达式|信号和槽优缺点(C++)

信号和槽存在意义 所谓的信号槽&#xff0c;终究要解决的问题&#xff0c;就是响应用户的操作 信号槽&#xff0c;其实在GUI开发的各种框架中&#xff0c;是一个比较有特色的存在 其他的GUI开发框架&#xff0c;搞的方式都要更简洁一些&#xff5e;~ 网页开发 (js dom api) 网…...

电脑 BIOS 操作指南(Computer BIOS Operation Guide)

电脑 BIOS 操作指南 电脑的BIOS界面&#xff08;应为“BIOS”&#xff09;是一个固件界面&#xff0c;允许用户配置电脑的硬件设置。 进入BIOS后&#xff0c;你可以进行多种设置&#xff0c;具体包括&#xff1a; 1.启动配置 启动顺序&#xff1a;设置从哪个设备启动&#x…...

Scrapeless Scraping Browser: A high-concurrency automation solution for AI

介绍&#xff1a;升级无缝抓取浏览器的并发能力 作为 Scrapeless 的开发者和创始团队&#xff0c;我们对人工智能自动化的未来充满真诚的热情。我们的使命是创建一个真正为 AI 设计的自动化浏览器。在过去的几年中&#xff0c;从 Browserless.io 到众多云服务供应商推出的“浏…...

Java项目—— 拼图小游戏(进阶版)

项目需求 在拼图小游戏基础版的基础上&#xff0c;完成下列要求&#xff1a; 一、实现更换拼图图片功能 1&#xff0c;给美女&#xff0c;动物&#xff0c;运动菜单按钮添加单击事件&#xff08;动作监听&#xff09; 2&#xff0c;当我们点击了美女之后&#xff0c;就会从13…...

解析:深度优先搜索、广度优先搜索和回溯搜索

一、深度优先搜索&#xff08;DFS&#xff09; 1. 原理 思想&#xff1a;从起始节点出发&#xff0c;顺着一条路径不断深入&#xff0c;直到到达目标或无路可走&#xff0c;然后回溯到最近的分支点&#xff0c;继续探索其他分支。 应用场景&#xff1a;路径查找、连通性检测、…...

探索大语言模型(LLM):循环神经网络的深度解析与实战(RNN、LSTM 与 GRU)

一、循环神经网络&#xff08;RNN&#xff09; 1.1 基本原理 循环神经网络之所以得名&#xff0c;是因为它在处理序列数据时&#xff0c;隐藏层的节点之间存在循环连接。这意味着网络能够记住之前时间步的信息&#xff0c;并利用这些信息来处理当前的输入。 想象一下&#xf…...

从零开始开发 MCP Server

作者&#xff1a;张星宇 在大型语言模型&#xff08;LLM&#xff09;生态快速演进的今天&#xff0c;Model Context Protocol&#xff08;MCP&#xff09;作为连接 AI 能力与真实世界的标准化协议&#xff0c;正逐步成为智能体开发的事实标准。该协议通过定义 Resources&#…...

Oracle日志系统之重做日志和归档日志

Oracle日志系统之重做日志和归档日志 重做日志归档日志 本文讨论Oracle日志系统中对数据恢复非常重要的两个日志&#xff1a;重做日志和归档日志。 重做日志 重做日志&#xff0c;英文名Redo Log&#xff0c;顾名思义&#xff0c;是用来数据重做的&#xff0c;主要使用场景是事…...

嵌入式开发--STM32G4系列硬件CRC支持MODBUS和CRC32

需求 在项目中&#xff0c;需要用到MODBUS CRC16校验&#xff0c;也要用到CRC32的校验&#xff0c;出于效率的考虑&#xff0c;准备用硬件CRC。 CRC 16的参数模型有很多种&#xff0c;我这里用的是MODBUS&#xff0c;对于不同的参数模型&#xff0c;会有不同的参数设置和初值&a…...

基于尚硅谷FreeRTOS视频笔记——4—多任务处理

目录 多任务处理 任务调度 任务的调度策略 优先级不同 优先级相同 多任务处理 通俗来讲就是 能够在同一时间 同时 进行多个任务的处理&#xff0c;这就时多任务处理。 但是&#xff0c;单核处理器一次只能处理一个任务&#xff0c;就是说在while中&#xff0c;任务们只能…...

中小型及初创企业如何实现数字化转型?

在当今动态的商业环境中&#xff0c;财务团队开始肩负起推动企业数字化转型的重任&#xff0c;即从传统的财务规划系统稳步迈向基于商业智能平台和以创新技术为驱动的解决方案领域。这些举措有望提高运营和分析效率&#xff0c;同时依托数据驱动的决策机制&#xff0c;帮助企业…...

java输出、输入语句

先创建一个用于测试的java 编写程序 #java.util使java标准库的一个包&#xff0c;这里拉取Scanner类 import java.util.Scanner;public class VariableTest {public static void main(String[] args) {#创建一个 Scanner 对象Scanner scanner new Scanner(System.in);System.…...

Python基础知识语法归纳总结(数据类型-1)

Python基础知识&语法归纳总结&#xff08;数据类型&#xff09; 一、Python基本数据类型 尤其注意&#xff0c;Python中的变量不需要特定的去声明&#xff0c;每个变量在使用前都必须对其进行赋值&#xff0c;它没有类型&#xff0c;我们所说的“类型”是变量所指的内存中对…...

Spring数据访问全解析:ORM整合与JDBC高效实践

目录 一、Spring ORM集成深度剖析 &#x1f31f; ORM模块架构设计 核心集成特性&#xff1a; 整合MyBatis示例配置&#xff1a; 二、Spring JDBC高效实践指南 &#x1f31f; 传统JDBC vs Spring JDBC对比 &#x1f31f; JdbcTemplate核心操作示例 批量操作优化&#xf…...

哪种电脑更稳定?Mac?Windows?还是云电脑? 实测解密

随着科技的发展进步&#xff0c;电脑已成为当下各类群体的必备产品之一&#xff0c;它的妙用有很多&#xff0c;无论是学生党、打工人还是已经退休的人群或都离不开它的存在。然而&#xff0c;电脑虽好却也差异很大、不同品牌、不同系统、不同配置、不同价位的统统都会有区别。…...

【AI模型学习】关于写论文——论文的审美

文章目录 一、“补丁法”&#xff08;Patching&#xff09;1.1 介绍1.2 方法论1.3 实例 二、判断工作的价值2.1 介绍2.2 详细思路2.3 科研性vs工程性 三、novelty以及误区3.1 介绍3.2 举例 看了李沐老师的读论文系列后&#xff0c;总结三个老师提到的有关课题研究和论文写作的三…...