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

[spring] Spring Boot REST API - 项目实现

Spring Boot REST API - 项目实现

书接上文 Spring Boot REST API - CRUD 操作,一些和数据库相关联的注解在 [spring] spring jpa - hibernate CRUD

主要的 layer 如下:

rest controller
service
DAO
db

项目配置

项目开始前的准备

spring 配置

Spring 依旧是从 https://start.spring.io/ 上下载的,具体配置如下:

在这里插入图片描述

properties 文件更新如下:

spring.datasource.url=jdbc:mysql://localhost:3306/employee_directory
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect

DB 配置

用的是 mysql,具体跑的脚本如下:

CREATE DATABASE  IF NOT EXISTS `employee_directory`;
USE `employee_directory`;--
-- Table structure for table `employee`
--DROP TABLE IF EXISTS `employee`;CREATE TABLE `employee` (`id` int NOT NULL AUTO_INCREMENT,`first_name` varchar(45) DEFAULT NULL,`last_name` varchar(45) DEFAULT NULL,`email` varchar(45) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;--
-- Data for table `employee`
--INSERT INTO `employee` VALUES(1,'Leslie','Andrews','leslie@google.com'),(2,'Emma','Baumgarten','emma@google.com'),(3,'Avani','Gupta','avani@google.com'),(4,'Yuri','Petrov','yuri@google.com'),(5,'Juan','Vega','juan@google.com');
使用 docker 运行 mysql

最近卸载掉了一些服务然后移到了 docker 上跑景象,发现方便了不少,下面贴一下用 docker 运行 mysql 的指令

# 下载最新的 mysql 镜像docker pull mysql:latest
# 运行镜像启动容器docker run --name mysql-container -e MYSQL_ROOT_PASSWORD=yourpassword -p 3306:3306 -d mysql:latest# 查看正在运行的 docker containerdocker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED      STATUS      PORTS                                         NAMES
ec2f40d48498   mysql     "docker-entrypoint.s…"   3 days ago   Up 3 days   8080/tcp, 0.0.0.0:3306->3306/tcp, 33060/tcp   nice_kirch# 可以查看 3306 是否被使用
# 正常来说上面的 PORTS 没问题就行了
# 我这里跑出来其实有一大堆的结果,因为 spring 跑起来了,也在和 3306 进行沟通,所以 spring 的 process 也会在这个列表中
# 如果刚刚启动了 docker,应该只有一条 docker 的 process 在使用 3306lsof -i :3306COMMAND     PID  USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
com.docke  1642 _____  144u  IPv6 0xf1d60cef5e02672d      0t0  TCP localhost:mysql->localhost:55086 (ESTABLISHED)
com.docke  1642 _____  642u  IPv6 0xf1d60cef66beb72d      0t0  TCP *:mysql (LISTEN)# 复制 sql 文件到 container 里docker cp <file_name> <container_name>:<path_name>

完成后使用 mysql 运行 sql 文件即可

CRUD 实现

这里就先用比较传统的实现

entity

@Data
@NoArgsConstructor
@RequiredArgsConstructor
@Entity
@Table(name = "employee")
public class Employee {// define fields@Id@GeneratedValue(strategy = GenerationType.IDENTITY)@Column(name = "id")private int id;@NonNull// must be the table name@Column(name = "first_name")private String firstName;@NonNull@Column(name = "last_name")private String lastName;@NonNull@Column(name = "email")private String email;
}

使用 lombok 省略一些实现,关于其他的注解,都是来自 Hibernate 的部分

dao & dao impl

这里就是比较传统的 DAO+DAOImpl 的实现,依旧是 Hibernate 的东西:

DAO interface:

public interface EmployeeDAO {List<Employee> findAll();
}

DAOImpl 实现:

@Repository
public class EmployeeDAOImpl implements EmployeeDAO {// define field for entityManagerprivate EntityManager entityManager;// setup constructor injection@Autowiredpublic EmployeeDAOImpl(EntityManager entityManager) {this.entityManager = entityManager;}@Overridepublic List<Employee> findAll() {// create a queryTypedQuery<Employee> query = this.entityManager.createQuery("from Employee", Employee.class);// execute query and get result list// and return resultreturn query.getResultList();}
}

rest controller 实现

这里依旧结合了一下 rest api 部分和 hibernate 的实现,后期会进行重构:

@RestController
@RequestMapping("/api")
public class EmployeeRestController {private final EmployeeDAO employeeDAO;public EmployeeRestController(EmployeeDAO employeeDAO) {this.employeeDAO = employeeDAO;}@GetMapping("/employees")public List<Employee> findAll() {return employeeDAO.findAll();}
}

实现效果如下:

在这里插入图片描述

service 层

上面的实现是直接通过 controller 和 DAO 层进行沟通,但是忽略了 service 层,这里把 service 层的实现补上

service 层本身是 façade 设计模式,其主要实现的功能就是让 DAO 层专注于实现数据的获取,controller 层专注于 HTTP 的处理,而 service 层则对 business logic 进行处理。由此可以延展出的优点/特性为:

  • 对功能的实现进行抽象,将低耦合性

  • 实现交易(transaction)管理

  • 集中处理 business logic

  • 复用性与灵活性

  • 提高可维护性与可拓展性

Service - Retrieve

具体实现如下:

  1. 首先声明一个 service 的 interface

    public interface EmployeeService {List<Employee> findAll();
    }
    
  2. 实现 interface

    @Service
    public class EmployeeServiceImpl implements EmployeeService{private final EmployeeDAO employeeDAO;public EmployeeServiceImpl(EmployeeDAO employeeDAO) {this.employeeDAO = employeeDAO;}@Overridepublic List<Employee> findAll() {return this.employeeDAO.findAll();}
    }
    

    可以看到,这个实现和 DAO 很像

  3. 将 controller 中调用的 DAO 替换为 service

    @RestController
    @RequestMapping("/api")
    public class EmployeeRestController {private final EmployeeService employeeService;public EmployeeRestController(EmployeeService employeeService) {this.employeeService = employeeService;}@GetMapping("/employees")public List<Employee> findAll() {return employeeService.findAll();}
    }
    
Service - 剩余 CRUD

这里实现一个根据 id 获取 employee 的功能,主要也是更新 DAO, DAOImpl,Service,ServiceImpl 和 Controller 这个套路,这里就放在一起了。

DAO 更新
public interface EmployeeDAO {List<Employee> findAll();Employee findById(int employeeId);Employee save(Employee employee);void deleteById(int employeeId);
}
DaoImpl 更新
@Repository
public class EmployeeDAOImpl implements EmployeeDAO {// define field for entityManagerprivate EntityManager entityManager;// setup constructor injection@Autowiredpublic EmployeeDAOImpl(EntityManager entityManager) {this.entityManager = entityManager;}@Overridepublic List<Employee> findAll() {// create a queryTypedQuery<Employee> query = this.entityManager.createQuery("from Employee", Employee.class);// execute query and get result list// and return resultreturn query.getResultList();}@Overridepublic Employee findById(int employeeId) {return this.entityManager.find(Employee.class, employeeId);}// No @Transactional here, it'll be handled at service layer@Overridepublic Employee save(Employee employee) {// if id == 0, then insert/save// else, updatereturn this.entityManager.merge(employee);}@Overridepublic void deleteById(int employeeId) {Employee employee = this.findById(employeeId);this.entityManager.remove(employee);}
}

这里几个点需要注意一下:

  1. merge 是根据 id 进行的操作,如果 id == 0,那么实现添加功能,不然就是修改
  2. service 层会接管 transaction,所以 DAO 层不需要添加 @Transactional 注解
service 更新

这里和 DAO 一样,添加新的方法即可——我是直接从 DAO 那里 cv 过来的

public interface EmployeeService {List<Employee> findAll();Employee findById(int employeeId);Employee save(Employee employee);void deleteById(int employeeId);
}
service impl 实现
@Service
public class EmployeeServiceImpl implements EmployeeService{private final EmployeeDAO employeeDAO;public EmployeeServiceImpl(EmployeeDAO employeeDAO) {this.employeeDAO = employeeDAO;}@Overridepublic List<Employee> findAll() {return this.employeeDAO.findAll();}@Overridepublic Employee findById(int employeeId) {return this.employeeDAO.findById(employeeId);}@Override@Transactionalpublic Employee save(Employee employee) {return this.employeeDAO.save(employee);}@Override@Transactionalpublic void deleteById(int employeeId) {this.employeeDAO.deleteById(employeeId);}
}

这里需要注意的就是:service 层中添加了 @Transactional 注解

相当于 business logic 在 service 中进行处理——不过这里的业务比较简单就是了

controller 实现
@RestController
@RequestMapping("/api")
public class EmployeeRestController {private final EmployeeService employeeService;public EmployeeRestController(EmployeeService employeeService) {this.employeeService = employeeService;}@GetMapping("/employees")public List<Employee> findAll() {return employeeService.findAll();}@GetMapping("/employees/{employeeId}")public Employee findById(@PathVariable int employeeId) {Employee employeeFound = this.employeeService.findById(employeeId);if (employeeFound == null) {throw new RuntimeException("Employee id not found - " + employeeId);}return employeeFound;}@PostMapping("/employees")public Employee save(@RequestBody Employee newEmployee) {newEmployee.setId(0);return this.employeeService.save(newEmployee);}@PutMapping("/employees")public Employee updateEmployee(@RequestBody Employee updateEmployee) {return this.employeeService.save(updateEmployee);}@DeleteMapping("/employees/{employeeId}")public String deleteEmployee(@PathVariable int employeeId) {Employee employeeFound = this.employeeService.findById(employeeId);if (employeeFound == null) {throw new RuntimeException("Employee id not found - " + employeeId);}this.employeeService.deleteById(employeeId);return "Deleted employee id - " + employeeId;}
}

效果如下:

实现功能效果展示
findById在这里插入图片描述
save在这里插入图片描述在这里插入图片描述
updage在这里插入图片描述在这里插入图片描述
deleteById在这里插入图片描述在这里插入图片描述在这里插入图片描述

目前项目结构如下:

在这里插入图片描述

优化

其实可以看到代码实现还是有很多的 boilerplate code,如 DAO/DAOImpl 和 Service/ServiceImpl,这 4 个类里的代码其实高度重合。为了解决这个问题,Spring 也实现了两个库,它们可以提供一些常规的 CRUD 功能的实现,减少 boilerplate code

更新 POM

		<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-rest</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency>

主要是增加这两个依赖

二者都是可拓展,如果想要实现更加个性化的功能,也可以通过实现 @Query 去进行拓展

Spring Data JPA

Sping Data JPA 可以通过实现 JpaRepository 去提供基础 CRUD 操作的支持

实现很简单:

package com.example.demo.dao;import com.example.demo.entity.Employee;
import org.springframework.data.jpa.repository.JpaRepository;public interface EmployeeRepository extends JpaRepository<Employee, Integer> {
}

不需要写任何代码,就可以把 DAO 和 DAOImpl 删了,接下来就是修改所有使用 DAO 的地方,将其修改为调用 repository:

@Service
public class EmployeeServiceImpl implements EmployeeService {private final EmployeeRepository employeeRepository;public EmployeeServiceImpl(EmployeeRepository employeeDAO) {this.employeeRepository = employeeDAO;}@Overridepublic List<Employee> findAll() {return this.employeeRepository.findAll();}@Overridepublic Employee findById(int employeeId) {Optional<Employee> result = this.employeeRepository.findById(employeeId);if (result.isEmpty()) {throw new RuntimeException("Did not find employee id - " + employeeId);}return result.get();}@Override@Transactionalpublic Employee save(Employee employee) {return this.employeeRepository.save(employee);}@Override@Transactionalpublic void deleteById(int employeeId) {this.employeeRepository.deleteById(employeeId);}
}

需要注意的是这里对 findById 的具体实现有些不一样,这里是因为 employeeRepository.findById 的返回值是 Optional<Employee>,因此需要对其进行一个空值的检查。

直接返回也不是不行,不过 Intellij 会报警告:

在这里插入图片描述

不影响正常使用,不过看着有点烦

Spring Data REST

DAO 可以用 JPA 代替,Service 也可以被 REST 所取代。这里其实不需要做什么事情,只要确定 pom 里有 spring-boot-starter-data-rest,直接删除掉 controller 和 service 即可

这时候的调用结果如下:

实现功能效果展示
patch,之前没有实现 patch,所以这里就尝试调用一下在这里插入图片描述
retrieve 注意这里结构改了在这里插入图片描述 在这里插入图片描述
query,这也是 rest 自带的一些支持功能在这里插入图片描述

配置

我这里修改的 properties 文件如下:

# Spring Data Rest properties
spring.data.rest.base-path=/api
spring.data.rest.default-page-size=50

base-path 加回对 RequestMapping 的支持,然后修改了一下默认的 pagination size

另一个比较常见需要修改的可能是 resource 的名字,data-rest 是会按照 resource+s 这种方式去自动添加路径,但是英语的复数形态不一定遵从这个规则,比如 person 的复数是 people,mouse 的复数是 mice 等,要修改路径则需要在 Repo 上使用 @RepositoryRestResource 的方式去修改,如:

@RepositoryRestResource(path = "members")
public interface EmployeeRepository extends JpaRepository<Employee, Integer> {
}

这样就无法通过 employees 的路径去访问,而是需要使用 members:

在这里插入图片描述

在这里插入图片描述

相关文章:

[spring] Spring Boot REST API - 项目实现

Spring Boot REST API - 项目实现 书接上文 Spring Boot REST API - CRUD 操作&#xff0c;一些和数据库相关联的注解在 [spring] spring jpa - hibernate CRUD 主要的 layer 如下&#xff1a; #mermaid-svg-QE1PR1gyrkz4XIT0 {font-family:"trebuchet ms",verdana…...

ELK之Filebeat实用配置及批量部署(部署200+可用)

跟我之前Zabbix-agent批量部署脚本Linux and Windows&#xff08;部署300可用&#xff09;文章的套路一样&#xff0c;在使用该脚本前&#xff0c;请先准备好安装包及配置好安装包的资源下载点&#xff0c;由于我这边是纯内网&#xff0c;所以我就找了一个NAS做了共享目录&…...

用odin实现的资源复制编辑器

用odin实现了一个资源复制编辑器&#xff0c;使用要安装odin&#xff0c;功能是把要复制的资源路径一个个添加设置&#xff0c;点copy能把列表里的资源全部复制&#xff0c;支持目录复制到目录&#xff0c;文件复制到目录&#xff0c;文件复制替换。提升效率&#xff0c;让自己…...

linux监控文件操作行为

linux监控文件操作行为 使用 auditd 系统 auditd 是Linux系统的一个安全和审计系统&#xff0c;它能够跟踪系统上发生的安全相关事件。要使用 auditd 来监控文件&#xff0c;你需要首先确保 auditd 已经安装并且运行在你的系统上。 然后&#xff0c;你可以使用 auditctl 命令…...

单链表接口函数的实现(增删查改)

一、单链表的实现形式以及接口函数的声明 #include<stdio.h> #include<stdlib.h> #include<assert.h> typedef int DataType ;typedef struct SListNode {DataType data;struct SListNode* next; }SLTNODE; void SLTPrint(SLTNODE* phead);//打印链表 SLTNO…...

超低功耗Sub-1G收发芯片DP32RF002 M0内核(G)FSK/OOK 无线收发机的32位SoC芯片

产品概述 DP32RF002是深圳市动能世纪科技有限公司研制的基于ARMCortex-MO内核的超低功耗 高性能的、单片集成(G)FSK/OOK 无线收发机的32位SoC芯片。工作于200 ~960MHz范围内&#xff0c;支持灵活可设的数据包格式&#xff0c;支持自动应答和自动重发功能&#xff0c;支持跳频…...

uniapp_微信小程序_NaN

一、定义 isNaN() 函数用于检查一个值是否为 NaN。它接受一个参数&#xff0c;该参数可以是任何 JavaScript 数据类型&#xff0c;包括数字、字符串、对象等。如果参数是 NaN&#xff0c;或者不能被转换为数字&#xff0c;则 isNaN() 返回 true&#xff1b;否则返回 false。 …...

1043: 利用栈完成后缀表达式的计算

解法&#xff1a; #include<iostream> #include<stack> using namespace std; int main() {char a;stack<int> sk;while (cin >> a && a ! #) {if (a > 0 && a < 9) {sk.push(a - 0);}else {int num2 sk.top();sk.pop();int n…...

初学ELK - elk部署

一、简介 ELK是3个开源软件组合&#xff0c;分别是 Elasticsearch &#xff0c;Logstash&#xff0c;Kibana Elasticsearch &#xff1a;是个开源分布式搜索引擎&#xff0c;提供搜集、分析、存储数据三大功能。它的特点有&#xff1a;分布式&#xff0c;零配置&#xff0c;自…...

[Java EE] 计算机工作原理与操作系统简明概要

1. 计算机工作原理 1.1 生活中常见的计算机 计算机分为通用计算机和专用计算机,计算机并不单单指的是电脑,还有我们平时使用的手机,ipad,智能手表等终端设备都是计算机.还有我们用户不常见的计算机,比如服务器. 还有许多嵌入式设备(针对特定场景定制的"专用计算机"…...

【尚硅谷】Git与GitLab的企业实战 学习笔记

目录 第1章 Git概述 1. 何为版本控制 2. 为什么需要版本控制 3. 版本控制工具 4. Git简史 5. Git工作机制 6. Git和代码托管中心 第2章 Git安装 第3章 Git常用命令 1. 设置用户签名 1.1 基本语法 1.2 案例实操 2. 初始化本地库 2.1 基本语法 2.2 案例实操 3. 查…...

如何在MobaXterm上使用rz命令

1、首先输入命令和想下载的文件&#xff0c;如下图&#xff1a; 2、按住ctrl鼠标右键&#xff0c;选择如下选项&#xff1a; 上传命令是rz&#xff0c;选择Receive...... 下载命令是sz&#xff0c;选择Send...... 3、我这里是要把Linux上的文件下载到我的本地window磁盘&…...

【计算机考研】408网课汇总+资源分享

408王道的视频就比较通俗易懂 王道的教材非常契合408的大纲&#xff0c;是专门为408大纲而编写的&#xff0c;而教材是方方面面都讲解的透彻。 建议王道为主&#xff0c;网络搜索为辅&#xff01; 王道中讲解不清楚&#xff0c;看不懂的知识点&#xff0c;可以尝试在网络上进…...

如何在OceanBase v4.2 中快速生成随机数据

在使用传统数据库如 MySQL 和 Oracle 时&#xff0c;由于缺乏多样化的随机数据生成方案&#xff0c;或者实现成本过高&#xff0c;构造随机数据的开发成本受到了影响。OceanBase在老版本中虽然有相应的解决方案&#xff0c;但语法复杂和性能较差等问题仍然存在。 现在&#xf…...

nvm node.js的安装

说明&#xff1a;部分但不全面的记录 因为过程中没有截图&#xff0c;仅用于自己的学习与总结 过程中借鉴的优秀博客 可以参考 1,npm install 或者npm init vuelatest报错 2&#xff0c;了解后 发现是nvm使用的版本较低&#xff0c;于是涉及nvm卸载 重新下载最新版本的nvm 2…...

【Docker】安装Redis、Nginx

1、安装redis mkdir -p /docker/redis mkdir -p /docker/redis/data touch /docker/redis/redis.conf touch /docker/redis/redis.bash编辑配置文件 vim /docker/redis/redis.conf # Redis配置文件# Redis默认不是以守护进程的方式运行&#xff0c;可以通过该配置项修改&…...

RK3568 UBUNTU修改网卡名称

​​​​​​RK3568 UBUNTU系统有两个网卡&#xff0c;ETH0和ETH1&#xff0c;于设备机壳丝印ETH1、ETH2无法对应&#xff0c;于是百度了一下相关的修改办法&#xff0c;有修改设备树的等等&#xff0c;挑了一个最简单&#xff0c;验证通过 #第1步&#xff0c;将原网卡关闭ip …...

【华为OD机试C++】统计字符

《最新华为OD机试题目带答案解析》:最新华为OD机试题目带答案解析,语言包括C、C++、Python、Java、JavaScript等。订阅专栏,获取专栏内所有文章阅读权限,持续同步更新! 文章目录 描述输入描述输出描述示例代码描述 输入一行字符,分别统计出包含英文字母、空格、数字和其它…...

百货商场用户画像描绘and价值分析(下)

目录 内容概述数据说明技术点主要内容4 会员用户画像和特征字段创造4.1 构建会员用户基本特征标签4.2 会员用户词云分析 5 会员用户细分和营销方案制定5.1 会员用户的聚类分析及可视化5.2 对会员用户进行精细划分并分析不同群体带来的价值差异 内容概述 本项目内容主要是基于P…...

spring-cloud微服务gateway

核心部分&#xff1a;routes(路由)&#xff0c; predicates(断言)&#xff0c;filters(过滤器) id&#xff1a;可以理解为是这组配置的一个id值&#xff0c;请保证他的唯一的&#xff0c;可以设置为和服务名一致 uri&#xff1a;可以理解为是通过条件匹配之后需要路由到&…...

业务系统对接大模型的基础方案:架构设计与关键步骤

业务系统对接大模型&#xff1a;架构设计与关键步骤 在当今数字化转型的浪潮中&#xff0c;大语言模型&#xff08;LLM&#xff09;已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中&#xff0c;不仅可以优化用户体验&#xff0c;还能为业务决策提供…...

label-studio的使用教程(导入本地路径)

文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...

ubuntu搭建nfs服务centos挂载访问

在Ubuntu上设置NFS服务器 在Ubuntu上&#xff0c;你可以使用apt包管理器来安装NFS服务器。打开终端并运行&#xff1a; sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享&#xff0c;例如/shared&#xff1a; sudo mkdir /shared sud…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

C++中string流知识详解和示例

一、概览与类体系 C 提供三种基于内存字符串的流&#xff0c;定义在 <sstream> 中&#xff1a; std::istringstream&#xff1a;输入流&#xff0c;从已有字符串中读取并解析。std::ostringstream&#xff1a;输出流&#xff0c;向内部缓冲区写入内容&#xff0c;最终取…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序

一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...

C++八股 —— 单例模式

文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全&#xff08;Thread Safety&#xff09; 线程安全是指在多线程环境下&#xff0c;某个函数、类或代码片段能够被多个线程同时调用时&#xff0c;仍能保证数据的一致性和逻辑的正确性&#xf…...

Java多线程实现之Thread类深度解析

Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...

【C++特殊工具与技术】优化内存分配(一):C++中的内存分配

目录 一、C 内存的基本概念​ 1.1 内存的物理与逻辑结构​ 1.2 C 程序的内存区域划分​ 二、栈内存分配​ 2.1 栈内存的特点​ 2.2 栈内存分配示例​ 三、堆内存分配​ 3.1 new和delete操作符​ 4.2 内存泄漏与悬空指针问题​ 4.3 new和delete的重载​ 四、智能指针…...

论文阅读:LLM4Drive: A Survey of Large Language Models for Autonomous Driving

地址&#xff1a;LLM4Drive: A Survey of Large Language Models for Autonomous Driving 摘要翻译 自动驾驶技术作为推动交通和城市出行变革的催化剂&#xff0c;正从基于规则的系统向数据驱动策略转变。传统的模块化系统受限于级联模块间的累积误差和缺乏灵活性的预设规则。…...