Spring模块详解Ⅲ(Spring Expression Language (SPEL)和Spring JDBC)

news2025/1/11 2:16:54

目录

  • Spring Expression Language(SpEL)
    • Spring Context 模块详解
    • 1. 什么是 Spring Context?
    • 2. ApplicationContext 的主要实现
    • 3. 国际化支持
      • 国际化消息文件
      • 使用 `MessageSource`
        • XML 配置:
        • Java 配置:
      • 使用国际化消息:
    • 4. 事件处理机制
      • 核心接口与类:
      • 自定义事件:
      • 自定义监听器:
      • 发布事件:
    • 5. 资源访问
      • 获取资源:
    • 6. 生命周期管理
      • 生命周期回调:
      • 生命周期回调示例:
    • 7. Environment 抽象
      • 访问环境属性:
    • 8. ApplicationContext 的扩展
      • WebApplicationContext 示例:
    • 总结
  • Spring JDBC
    • Spring JDBC 模块详解
    • 1. Spring JDBC 的核心组件
    • 2. JdbcTemplate 的使用
      • 2.1 JdbcTemplate 的配置
        • 通过 Java 配置:
      • 2.2 查询操作
        • 查询单一值:
        • 查询单行数据并映射为对象:
        • 查询多行数据并映射为对象列表:
      • 2.3 更新操作
        • 插入数据:
        • 更新数据:
        • 删除数据:
      • 2.4 批量操作
        • 批量插入数据:
    • 3. NamedParameterJdbcTemplate 的使用
      • 示例:
    • 4. SimpleJdbcInsert 和 SimpleJdbcCall
      • 4.1 SimpleJdbcInsert
        • 示例:
      • 4.2 SimpleJdbcCall
        • 示例:
    • 5. RowMapper 和 ResultSetExtractor
      • RowMapper 示例:
    • 6. 事务管理
      • 使用注解配置事务:
    • 总结

Spring Expression Language(SpEL)

在这里插入图片描述

Spring Context 模块详解

Spring Context 模块是 Spring 框架的一个重要模块,它建立在 Core 和 Beans 模块的基础之上,提供了更高级的特性,如国际化(I18N)、事件传播、资源管理、依赖注入(DI)、生命周期管理以及对 Java EE 特性的支持。它扩展了 BeanFactory,为应用程序提供了丰富的上下文环境。

1. 什么是 Spring Context?

ApplicationContext 是 Spring Context 模块的核心接口,它是 Spring IoC 容器的高级接口,扩展了基础的 BeanFactory 功能,不仅支持 Bean 的创建和管理,还提供了企业级的特性,例如:

  • 国际化(国际化消息)
  • 事件传播(监听和发布事件)
  • 资源访问(文件、URL、classpath 等)
  • 自动装配(基于注解和自动检测)

通过 ApplicationContext,Spring 应用程序能够管理 Bean 的生命周期、依赖关系、配置和运行时行为。

2. ApplicationContext 的主要实现

Spring 提供了多种 ApplicationContext 的实现,适用于不同的应用场景:

  • ClassPathXmlApplicationContext:从类路径下的 XML 配置文件中加载上下文。
  • FileSystemXmlApplicationContext:从文件系统中的 XML 配置文件中加载上下文。
  • AnnotationConfigApplicationContext:基于注解的配置上下文,通常用于基于 Java 配置的应用程序。
  • WebApplicationContext:用于 Web 应用的上下文,实现了 ApplicationContext,并集成了 Servlet 环境。
    在这里插入图片描述

3. 国际化支持

ApplicationContext 提供了对国际化(I18N)的支持,允许开发者根据用户的区域设置信息提供不同语言的消息。Spring 通过 MessageSource 接口实现了对国际化消息的管理,可以在配置文件中或通过 Java 类来定义国际化消息。

国际化消息文件

国际化消息通常存储在 .properties 文件中,不同语言的消息文件名称会有所区别,例如:

  • messages.properties:默认语言
  • messages_en.properties:英文
  • messages_fr.properties:法语

使用 MessageSource

配置 MessageSource 来加载国际化消息:

XML 配置:
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
    <property name="basename" value="messages" />
</bean>
Java 配置:
@Configuration
public class AppConfig {
    @Bean
    public ResourceBundleMessageSource messageSource() {
        ResourceBundleMessageSource source = new ResourceBundleMessageSource();
        source.setBasename("messages");
        return source;
    }
}

使用国际化消息:

@Autowired
private MessageSource messageSource;

public void printMessage(Locale locale) {
    String message = messageSource.getMessage("greeting", null, locale);
    System.out.println(message);
}

通过 Locale 参数,开发者可以获取基于不同语言环境的消息。

4. 事件处理机制

Spring 的事件机制使得应用程序中的组件之间可以通过发布和监听事件进行松散耦合的通信。Spring 提供了简单且强大的事件处理机制,基于 Observer Design Pattern(观察者模式)。

核心接口与类:

  • ApplicationEvent:所有事件类的父类,开发者可以自定义事件,继承自该类。
  • ApplicationListener:事件监听器接口,开发者可以实现该接口来处理事件。
  • ApplicationEventPublisher:事件发布接口,Spring IoC 容器实现了该接口,开发者可以通过它发布事件。

自定义事件:

public class CustomEvent extends ApplicationEvent {
    public CustomEvent(Object source) {
        super(source);
    }
}

自定义监听器:

@Component
public class CustomEventListener implements ApplicationListener<CustomEvent> {
    @Override
    public void onApplicationEvent(CustomEvent event) {
        System.out.println("Received custom event: " + event.getSource());
    }
}

发布事件:

@Component
public class EventPublisher {
    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    public void publishEvent() {
        CustomEvent customEvent = new CustomEvent(this);
        applicationEventPublisher.publishEvent(customEvent);
    }
}

在这个机制中,监听器通过实现 ApplicationListener 接口来处理特定的事件,发布器通过 ApplicationEventPublisher 接口发布事件,Spring IoC 容器负责监听器和事件的管理。
在这里插入图片描述

5. 资源访问

Spring Context 模块提供了统一的资源访问接口 Resource,可以用来访问各种形式的资源文件,如文件、URL、classpath 等。

获取资源:

Resource resource = applicationContext.getResource("classpath:data.txt");
InputStream inputStream = resource.getInputStream();

不同的资源前缀表示不同的资源类型:

  • classpath::类路径下的资源
  • file::文件系统中的资源
  • http::通过 HTTP 访问的资源

6. 生命周期管理

Spring 提供了对 Bean 生命周期的全面管理,ApplicationContext 扩展了 BeanFactory 的功能,并提供了更加细粒度的生命周期控制。Bean 的生命周期包括初始化、依赖注入、初始化回调、销毁等阶段。

生命周期回调:

  • InitializingBeanDisposableBean 接口:这些接口允许在 Bean 初始化和销毁时执行自定义逻辑。
  • @PostConstruct@PreDestroy 注解:用于定义 Bean 初始化和销毁的回调方法。
  • init-methoddestroy-method:在 XML 或 Java 配置中定义 Bean 的初始化和销毁方法。

生命周期回调示例:

@Component
public class MyBean implements InitializingBean, DisposableBean {
    @Override
    public void afterPropertiesSet() {
        System.out.println("Bean 初始化");
    }

    @Override
    public void destroy() {
        System.out.println("Bean 销毁");
    }
}

在这里插入图片描述

7. Environment 抽象

Spring Environment 抽象用于管理与应用程序运行环境相关的配置。它提供了配置文件、系统属性和环境变量等信息的统一访问方式。Environment 接口还支持对配置文件的处理,例如 devtestprod 环境的动态切换。

访问环境属性:

@Component
public class MyBean {
    @Autowired
    private Environment env;

    public void printProperty() {
        String dbUrl = env.getProperty("database.url");
        System.out.println("Database URL: " + dbUrl);
    }
}

8. ApplicationContext 的扩展

Spring 提供了 ApplicationContext 的扩展,使其能够支持多种功能,如 Web 应用中的 WebApplicationContext,它是一个专用于 Web 环境的 ApplicationContext,与 Servlet 环境集成紧密,能够管理 Web 应用的生命周期、请求作用域 Bean、会话作用域 Bean 等。

WebApplicationContext 示例:

public class MyWebAppInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext servletContext) {
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.register(AppConfig.class);
        servletContext.addListener(new ContextLoaderListener(context));
    }
}

在这里插入图片描述

总结

Spring Context 模块扩展了基础的 Bean 管理功能,提供了更为全面的应用上下文管理。通过 ApplicationContext,开发者可以实现国际化、事件传播、资源访问、环境配置、生命周期管理等高级功能。这些特性为企业级应用程序开发提供了强大的支持,使应用程序更加灵活、可扩展和易于维护。

Spring Context 是 Spring 框架的中枢模块之一,它整合了大量企业级功能,并且可以通过注解、XML 和 Java 配置灵活定义和管理上下文,满足不同类型应用的需求。

Spring JDBC

Spring JDBC 模块详解

在这里插入图片描述

Spring JDBC 模块简化了对关系型数据库的操作,是对 Java 标准 JDBC API 的抽象和封装。它帮助开发者免于处理繁琐的 JDBC 连接管理、资源释放、SQL 异常处理等问题。Spring JDBC 模块的目标是让开发者能够专注于数据库逻辑和业务逻辑,而不是底层的 JDBC 代码细节。

1. Spring JDBC 的核心组件

Spring JDBC 提供了一系列核心组件,用于简化数据库访问。最重要的组件包括:

  • JdbcTemplate:Spring JDBC 的核心类,用于执行 SQL 查询、更新以及调用存储过程等操作。它封装了基本的数据库操作,简化了数据库连接管理、异常处理等任务。
  • NamedParameterJdbcTemplate:支持使用命名参数的模板类,解决了复杂 SQL 中大量占位符的问题,使 SQL 更具可读性。
  • SimpleJdbcInsert 和 SimpleJdbcCall:提供插入和存储过程调用的简化 API。
  • RowMapper:将数据库中的行数据映射为 Java 对象。
  • DataSource:JDBC 连接池的数据源接口,用于获取数据库连接。

2. JdbcTemplate 的使用

JdbcTemplate 是 Spring JDBC 模块的核心类,用于执行数据库操作。它提供了一系列简化的 API 方法来处理常见的 JDBC 操作,如查询、插入、更新和删除等。

2.1 JdbcTemplate 的配置

为了使用 JdbcTemplate,首先需要配置 DataSource,它负责管理数据库连接。Spring 提供了多种方式来配置 DataSource,可以通过 Java 配置类、XML 或者注解方式实现。

通过 Java 配置:
@Configuration
public class JdbcConfig {

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/mydb");
        dataSource.setUsername("root");
        dataSource.setPassword("password");
        return dataSource;
    }

    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
}

在这个配置中,我们创建了一个 DataSource Bean,并将它注入到 JdbcTemplate 中。

在这里插入图片描述

2.2 查询操作

JdbcTemplate 提供了多种查询方法,比如 queryForObjectquery 等。常见的查询操作可以分为以下几种:

查询单一值:
String sql = "SELECT COUNT(*) FROM employees";
int count = jdbcTemplate.queryForObject(sql, Integer.class);
System.out.println("Total employees: " + count);
查询单行数据并映射为对象:
String sql = "SELECT * FROM employees WHERE id = ?";
Employee employee = jdbcTemplate.queryForObject(sql, new Object[]{1}, new BeanPropertyRowMapper<>(Employee.class));
System.out.println(employee);

在这个例子中,我们查询了一行数据,并使用 BeanPropertyRowMapper 将结果映射为 Employee 对象。

查询多行数据并映射为对象列表:
String sql = "SELECT * FROM employees";
List<Employee> employees = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Employee.class));
for (Employee employee : employees) {
    System.out.println(employee);
}

这里我们查询了多行数据,并将每一行映射为 Employee 对象,最终得到一个 List<Employee>

2.3 更新操作

JdbcTemplate 同样提供了一系列方法来执行数据库的更新操作,如插入、更新和删除等。

插入数据:
String sql = "INSERT INTO employees (name, department, salary) VALUES (?, ?, ?)";
int result = jdbcTemplate.update(sql, "John Doe", "HR", 55000);
System.out.println("Rows affected: " + result);
更新数据:
String sql = "UPDATE employees SET salary = ? WHERE id = ?";
int result = jdbcTemplate.update(sql, 60000, 1);
System.out.println("Rows affected: " + result);
删除数据:
String sql = "DELETE FROM employees WHERE id = ?";
int result = jdbcTemplate.update(sql, 1);
System.out.println("Rows affected: " + result);

2.4 批量操作

对于需要批量执行的 SQL 语句,JdbcTemplate 提供了批处理功能,能够在一次操作中执行多个 SQL 语句。

批量插入数据:
String sql = "INSERT INTO employees (name, department, salary) VALUES (?, ?, ?)";
List<Object[]> batchArgs = Arrays.asList(
    new Object[]{"Alice", "Sales", 50000},
    new Object[]{"Bob", "IT", 60000},
    new Object[]{"Charlie", "HR", 55000}
);
int[] results = jdbcTemplate.batchUpdate(sql, batchArgs);
System.out.println(Arrays.toString(results));

3. NamedParameterJdbcTemplate 的使用

NamedParameterJdbcTemplateJdbcTemplate 的增强版本,允许使用命名参数代替传统的占位符(?)。这种方式在处理复杂 SQL 时尤其有用,可以使代码更具可读性。

示例:

String sql = "SELECT * FROM employees WHERE name = :name AND department = :department";
Map<String, Object> params = new HashMap<>();
params.put("name", "Alice");
params.put("department", "Sales");

List<Employee> employees = namedParameterJdbcTemplate.query(sql, params, new BeanPropertyRowMapper<>(Employee.class));
System.out.println(employees);

在这个例子中,命名参数使得 SQL 更加清晰,并避免了传统占位符方式的参数顺序错误问题。
在这里插入图片描述

4. SimpleJdbcInsert 和 SimpleJdbcCall

SimpleJdbcInsertSimpleJdbcCall 是 Spring 提供的用于简化数据库插入操作和调用存储过程的类。这些类封装了底层的复杂性,使开发者可以以更简洁的方式进行操作。

4.1 SimpleJdbcInsert

SimpleJdbcInsert 提供了一种简单的方式来插入数据,它能够自动生成 INSERT 语句,不需要显式编写 SQL。

示例:
SimpleJdbcInsert insert = new SimpleJdbcInsert(jdbcTemplate)
    .withTableName("employees")
    .usingGeneratedKeyColumns("id");

Map<String, Object> parameters = new HashMap<>();
parameters.put("name", "John Doe");
parameters.put("department", "IT");
parameters.put("salary", 70000);

Number id = insert.executeAndReturnKey(new MapSqlParameterSource(parameters));
System.out.println("Inserted employee ID: " + id);

4.2 SimpleJdbcCall

SimpleJdbcCall 用于简化调用存储过程的操作,尤其适合那些复杂的存储过程调用场景。

示例:
SimpleJdbcCall jdbcCall = new SimpleJdbcCall(jdbcTemplate)
    .withProcedureName("get_employee_count");

Map<String, Object> out = jdbcCall.execute();
System.out.println("Employee count: " + out.get("count"));

在这里插入图片描述

5. RowMapper 和 ResultSetExtractor

RowMapperResultSetExtractor 是 Spring JDBC 中用于将数据库结果集映射为 Java 对象的接口。

  • RowMapper:用于将每一行结果映射为一个 Java 对象。
  • ResultSetExtractor:用于自定义复杂结果集的提取逻辑,适用于复杂查询场景。

RowMapper 示例:

public class EmployeeRowMapper implements RowMapper<Employee> {
    @Override
    public Employee mapRow(ResultSet rs, int rowNum) throws SQLException {
        Employee employee = new Employee();
        employee.setId(rs.getInt("id"));
        employee.setName(rs.getString("name"));
        employee.setDepartment(rs.getString("department"));
        employee.setSalary(rs.getDouble("salary"));
        return employee;
    }
}

JdbcTemplate 查询中使用:

String sql = "SELECT * FROM employees";
List<Employee> employees = jdbcTemplate.query(sql, new EmployeeRowMapper());

6. 事务管理

Spring JDBC 支持声明式事务管理,允许开发者通过简单的配置或注解来控制事务的边界,而不需要手动管理事务的开启、提交和回滚。

使用注解配置事务:

@Service
@Transactional
public class EmployeeService {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    public void updateEmployee(Employee employee) {
        String sql = "UPDATE employees SET salary = ? WHERE id = ?";
        jdbcTemplate.update(sql, employee.getSalary(), employee.getId());
    }
}

通过 @Transactional 注解,Spring 自动管理事务的开启、提交和回滚。

在这里插入图片描述

总结

Spring JDBC 模块通过对标准 JDBC API 的封装和抽象,简化了数据库操作,减少了冗余代码,提升了开发效率。通过核心的 JdbcTemplateNamedParameterJdbcTemplateSimpleJdbcInsertSimpleJdbcCall 等类,开发

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

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

相关文章

SwapPrompt(论文解读): Test-Time Prompt Adaptation for Vision-Language Models

2023(Neural IPS) 摘要 测试自适应 &#xff08;TTA&#xff09; 是无监督域自适应&#xff08;UDA&#xff09;中一种特殊且实用的设置&#xff0c;它允许源域中的预训练模型去适应另一个目标域中的未标记测试数据。为了避免计算密集型的骨干网络微调过程&#xff0c;因此利…

【技巧】-DNSlog外带文件

❤️博客主页&#xff1a; iknow181 &#x1f525;系列专栏&#xff1a; 网络安全、 Python、JavaSE、JavaWeb、CCNP &#x1f389;欢迎大家点赞&#x1f44d;收藏⭐评论✍ 1.什么是DNSlog 我们都知道DNS就是将域名解析为ip&#xff0c;用户在浏览器上输入一个域名A.com&#x…

实现Nginx四层负载均衡

Nginx在1.9.0版本开始支持tcp模式的负载均衡&#xff0c;在1.9.13版本开始支持udp协议的负载&#xff0c;udp主要用于 DNS的域名解析&#xff0c;其配置方式和指令和http 代理类似&#xff0c;其基于ngx_stream_proxy_module模块实现tcp 负载&#xff0c;另外基于模块ngx_strea…

vue2版本空目录下创建新项目的方法2024

vue2版本空目录下创建新项目的方法2024 node -v npm -v vue -V 安装vue-cli 2.9版本的命令 npm install vue-cli -g 卸载vue2.x方法&#xff1a; npm uninstall vue-cli -g 设置 NPM 镜像 npm config set registry https://registry.npmmirror.com vue -V 报错时需设置环…

多进程和多线程基础概念LINUX

进程和程序的区别 程序是静态的&#xff0c;它是保存在磁盘上的指令的有序集合&#xff0c;没有任何执行的概念进程是一个动态的概念&#xff0c;它是程序执行的过程&#xff0c;包括了动态创建、调度和销毁的整个过程 并行&#xff1a;在 cpu 多核的支持下&#xff0c;实现物…

Git 的基本使用

1.创建 Git 本地仓库 仓库是进⾏版本控制的⼀个⽂件⽬录。我们要想对⽂件进⾏版本控制&#xff0c;就必须先创建⼀个仓库出来&#xff0c;例如下面代码创建了gitcode_linux的文件夹&#xff0c;之后再对其进行初始化。创建⼀个 Git 本地仓库对应的命令为 git init &#xff0c…

视频项目开发,EasyCVR视频融合平台为何成为关键驱动力

智慧类视频项目是基于多个系统融合&#xff0c;旨在实现更广泛联动功能&#xff0c;以满足智能化应用需求为基石的信息化项目。当前&#xff0c;智慧社区、智慧园区、智慧工厂乃至智慧城市等应用场景的需求日益增长。这些智慧项目的整合进程中&#xff0c;视频融合能力扮演着不…

ASP.NET Core 入门教程一 创建最小 API

构建最小 API&#xff0c;以创建具有最小依赖项的 HTTP API。 它们非常适合需要在 ASP.NET Core 中仅包括最少文件、功能和依赖项的微服务和应用。 本教程介绍使用 ASP.NET Core 生成最小 API 的基础知识。 启动 Visual Studio 2022 并选择“创建新项目”。 在“创建新项目”…

RabbitMQ 最新版 安装,配置,java接入使用(详细教程)

一 RabbitMQ下载 RabbitMQ 官网最新版下载&#xff1a; RabbitMQ: One broker to queue them all | RabbitMQ RabbitMQ依赖erlang-26.2.5.2-1.el7.x86_64.rpm下载&#xff1a; https://github.com/rabbitmq/erlang-rpm/releases/download/v26.2.5.2/erlang-26.2.5.2-1.el7.…

Information Processing Technician

信息处理技术员试题 🔥SeptemberZone 1.信息是一种() A.资源 B.物质 C.能量 D.载体 2.以下关于信息的表达中,不正确的选项是() A.一切数据都能产生信息 B.信息的产生、处理和传递依靠于物质和能量 C.同一信息在不同的时间可能具有不同的价值 D.信息的屡次使用不会使信息…

MD编辑器学习笔记

MD编辑器学习笔记 目录标题文本样式列表图片链接代码片数学公式表格部分总结 目录 目录是使用“[TOC](目录&#xff09;”&#xff0c;记住别忘了加上&#xff08;&#xff09;标题 使用#来确定标题&#xff0c;几个#就是几级标题。记住#后面要加上空格文本样式 tips: 在写正…

什么是制造业项目管理软件?适合制造企业的项目管理软件具备哪些特征

当前&#xff0c;我国的制造业呈现出稳步增长与风险并存的现象。经济构建以国内大循环为主体&#xff0c;国产替代的浪潮正在席卷国内制造业&#xff0c;越来越多的制造领域企业开始启动数字化变革来支撑企业的迅猛发展&#xff0c;进一步优化项目管理流程&#xff0c;促进研发…

Docker的概述及如何启动docker的镜像、远程管理宿主机的docker进程

一、概述&#xff1a; 1、Docker 是什么&#xff1f; Docker 是⼀个开源的应⽤容器引擎&#xff0c;可以实现虚拟化&#xff0c;完全采用“沙盒”机制&#xff0c;容器之间不会存在任何接口。 2、Docker 和虚拟机的区别&#xff1a; 1&#xff09;启动速度&#xff1a;Dock…

使用 Visual Studio 编辑器作为 DailyNotes 的 markdown 编辑器

DailyNotes 是我使用过的最优秀的日常笔记管理工具&#xff0c;为它配置一个好的 markdown 编辑器&#xff0c;可以大幅提升效率。 除了使用 Typora 作为 markdown 编辑器&#xff0c;Visual Studio Code 也是一个非常不错的选择&#xff0c;令人惊喜的是&#xff0c;它也支持…

React学习笔记(二)——react基础

目录 1. 受控表单绑定 2. React中获取DOM 3. 案例&#xff1a;B站评论 — 发表评论 3.1 B站评论案例 —— 核心功能实现 3.2 B站评论案例 — id处理和时间处理 3.3 B站评论案例 — 清空内容并重新聚焦 4. 组件通信 4.1 理解组件通信 4.2 父传子-基础实现 4.3 父传子-…

基于Spark计算网络图中节点之间的Jaccard相似性

基于Spark计算网络图中节点之间的Jaccard相似性 Jaccard 相似度是一种较为常用的衡量两个集合相似性的指标&#xff0c;用于计算两个集合的交集与并集的比率。具体来说&#xff0c;它的计算公式为&#xff1a; 在网络图中同样经常使用Jaccard来计算节点之间的相似性&#xff…

【标准知识】航天产品设计文件编号

按照QJ 1714-2011《航天产品设计文件管理制度》&#xff0c;梳理一下设计文件的编号要求。 01 设计文件 按照QJ 1714的规定&#xff0c;设计文件是由设计部门编制的&#xff0c;用以规定产品的组成、型式、结构尺寸、技术要求、原理以及制造、调试、试验、验收、使用、维护、…

Robot Operating System——自定义订阅/发布的消息结构

大纲 初始化环境生成自定义消息的工程创建包自定义消息package.xml完整文件 CMakeLists.txt完整文件 编译注册 使用自定义消息的工程创建包代码CMakeLists.txt编译运行 工程地址参考资料 在之前的案例中我们订阅/发布之间传递的消息都是ROS2的标准类型。本文我们将讨论如何自定…

【IoTDB 线上小课 06】列式写入=时序数据写入性能“利器”?

【IoTDB 视频小课】更新来啦&#xff01;今天已经是第六期了~ 关于 IoTDB&#xff0c;关于物联网&#xff0c;关于时序数据库&#xff0c;关于开源... 一个问题重点&#xff0c;3-5 分钟&#xff0c;我们讲给你听&#xff1a; 列式写入到底是&#xff1f; 上一期我们详细了解了…

【STM32】写Keil程序的注意事项

看正点原子的资料使用Keil写STM32程序的时候&#xff0c;总是在不断学习&#xff0c;不断探索。后续又学到啥再更新 目录 1 Keil设置 1.1 字体设置 1.2 快捷键设置 1.3 快速前往前一操作位置/后一操作位置 2 宏定义 2.1 宏定义函数时为什么使用do{…}w…