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

[Spring] Spring事务与事务的传播

🌸个人主页:https://blog.csdn.net/2301_80050796?spm=1000.2115.3001.5343
🏵️热门专栏:
🧊 Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm=1001.2014.3001.5482
🍕 Collection与数据结构 (92平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm=1001.2014.3001.5482
🧀线程与网络(96平均质量分) https://blog.csdn.net/2301_80050796/category_12643370.html?spm=1001.2014.3001.5482
🍭MySql数据库(93平均质量分)https://blog.csdn.net/2301_80050796/category_12629890.html?spm=1001.2014.3001.5482
🍬算法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12676091.html?spm=1001.2014.3001.5482
🍃 Spring(97平均质量分)https://blog.csdn.net/2301_80050796/category_12724152.html?spm=1001.2014.3001.5482
感谢点赞与关注~~~
在这里插入图片描述

目录

  • 1. 回忆数据库中的事务
  • 2. Spring中事务的实现
    • 2.1 Spring编程式事务
    • 2.2 Spring声明式事务@Transactional
    • 2.3 @Transactional的作用
  • 3. @Transactional详解
    • 3.1 rollbackFor
    • 3.2 事务隔离级别
      • 3.2.1 回顾MySQL中的事务隔离级别
      • 3.3.2 Spring事务隔离级别
    • 3.3 Spring事务传播机制
      • 3.3.1 概念
      • 3.3.2 事务的传播机制分类
      • 3.3.3 Spring事务传播机制代码演示

1. 回忆数据库中的事务

https://lilesily12385.blog.csdn.net/article/details/137935719

2. Spring中事务的实现

Spring中的事务操作分为两类:

  1. 编程式事务(手动写代码操作事务)
  2. 声明式事务(使用注解完成)

现有一需求: 用户注册,注册时候在日志表中插入一条操作记录
数据准备:

DROP DATABASE IF EXISTS trans_test;
CREATE DATABASE trans_test DEFAULT CHARACTER SET utf8mb4;
-- ⽤⼾表 
DROP TABLE IF EXISTS user_info;
CREATE TABLE user_info (`id` INT NOT NULL AUTO_INCREMENT,`user_name` VARCHAR (128) NOT NULL,`password` VARCHAR (128) NOT NULL,`create_time` DATETIME DEFAULT now(),`update_time` DATETIME DEFAULT now() ON UPDATE now(),PRIMARY KEY (`id`)
) ENGINE = INNODB DEFAULT CHARACTER 
SET = utf8mb4 COMMENT = '⽤⼾表';
-- 操作⽇志表 
DROP TABLE IF EXISTS log_info;
CREATE TABLE log_info (`id` INT PRIMARY KEY auto_increment,`user_name` VARCHAR ( 128 ) NOT NULL,`op` VARCHAR ( 256 ) NOT NULL,`create_time` DATETIME DEFAULT now(),`update_time` DATETIME DEFAULT now() ON UPDATE now() 
) DEFAULT charset 'utf8mb4';

代码准备:
1. 创建项目,配置文件引入日志打印,驼峰转换,数据库配置等.

spring:datasource:url: jdbc:mysql://127.0.0.1:3306/trans_test?
characterEncoding=utf8&useSSL=falseusername: rootpassword: rootdriver-class-name: com.mysql.cj.jdbc.Driver
mybatis:configuration: # 配置打印 MyBatis⽇志 log-impl: org.apache.ibatis.logging.stdout.StdOutImplmap-underscore-to-camel-case: true #配置驼峰⾃动转换 

创建实体类:

import lombok.Data;
import java.util.Date;
@Data
public class UserInfo {private Integer id;private String userName;private String password;private Date createTime;private Date updateTime;
}
mport lombok.Data;
import java.util.Date;
@Data
public class LogInfo {private Integer id;private String userName;private String op;private Date createTime;private Date updateTime;
}

Mapper:

import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserInfoMapper {@Insert("insert into user_info(`user_name`,`password`)values(#{name},#{password})")Integer insert(String name,String password);
}
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface LogInfoMapper {@Insert("insert into log_info(`user_name`,`op`)values(#{name},#{op})")Integer insertLog(String name,String op);
}

Service:

@Slf4j
@Service
public class UserService {@Autowiredprivate UserInfoMapper userInfoMapper;public void registryUser(String name,String password){//插⼊⽤⼾信息 userInfoMapper.insert(name,password);}
}
 @Slf4j@Servicepublic class LogService {@Autowiredprivate LogInfoMapper logInfoMapper;public void insertLog(String name,String op){//记录⽤⼾操作 logInfoMapper.insertLog(name,"⽤⼾注册");}}

2.1 Spring编程式事务

Spring手动操作事务主要分为三步,与Sql事务的操作类似:
- 开启事务
- 提交事务
- 或者回滚事务

@RestController
@RequestMapping("/user")
public class TransactionController {@Autowiredprivate UserService userService;@Autowiredprivate DataSourceTransactionManager dataSourceTransactionManager;@Autowiredprivate TransactionDefinition transactionDefinition;@RequestMapping("/registry")public String login(String userName,String password){//开启事务TransactionStatus transaction = dataSourceTransactionManager.getTransaction(transactionDefinition);//用户注册userService.registryUser(userName,password);//提交事务dataSourceTransactionManager.commit(transaction);//回滚事务
//        dataSourceTransactionManager.rollback(transaction);return "注册成功";}
}

SpringBoot内置了两个对象:

  1. DataSourceTransactionManager,数据源事务管理器,一般用于事务的开启回滚和提交.
  2. TransactionDefinition是事务的属性,一般用于传给事务管理器的getTransaction方法,用于事务的获取与开启.
  • 观察事务提交
dataSourceTransactionManager.commit(transaction);

在这里插入图片描述
在这里插入图片描述
我们观察到数据库,数据被插入成功.

  • 观察事务回滚
dataSourceTransactionManager.rollback(transaction);

在这里插入图片描述
在这里插入图片描述
我们看到虽然返回的结果是注册成功,但是数据库中并没有多出任何数据.
下面我们来学习一种简单而快捷的方法,使用注解声明.

2.2 Spring声明式事务@Transactional

一共有两部操作:

  1. 添加依赖
<dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId>
</dependency>
  1. 在事务的方法上添加@Transactional注解就可以实现了.无需手动开启和提交事务,在事务全部执行完成之后会自动提交,在中途发生异常的手会自动回滚.
@RestController
@RequestMapping("/user2")
public class TransactionController2 {@Autowiredprivate UserService userService;@RequestMapping("/registry2")@Transactionalpublic String registry2(String userName,String password){userService.registryUser(userName,password);return "注册成功";}
}

运行程序后,数据插入成功.
修改程序,使之出现异常:

@RestController
@RequestMapping("/user2")
public class TransactionController2 {@Autowiredprivate UserService userService;@RequestMapping("/registry2")@Transactionalpublic String registry2(String userName,String password){userService.registryUser(userName,password);int i = 10/0;return "注册成功";}
}

运行之后,虽然返回了注册成功,但是数据库并没有更新结果.

我们一般写事务的时候会在业务逻辑层来控制事务,因为在业务逻层中,一个业务功能可能会包含多个数据库访问操作,这样就可以把多个访问数据库的操作 合并在同一个事务中.

2.3 @Transactional的作用

@Transactional可以用来修饰方法或者是类.
修饰方法的时候,只对public修饰的方法生效,修饰其他方法也不会报错,但是也不会生效.
修饰类的时候,对类中的所有public方法生效.
在程序出现异常的时候,如果异常没有被捕获,这时候事务就会被回滚,但是如果异常被捕获,就会被认为是正常执行,依然会提交事务.
修改上述代码:

@RestController
@RequestMapping("/user2")
public class TransactionController2 {@Autowiredprivate UserService userService;@RequestMapping("/registry2")@Transactionalpublic String registry2(String userName,String password){userService.registryUser(userName,password);try {int i = 10/0;}catch (ArithmeticException e) {e.printStackTrace();}return "注册成功";}
}

运行程序之后,虽然出错了,由于异常得到了捕获,事务便得到了提交.
以下两种情况,事务依然会回滚:

  1. 重新抛出异常
try {int i = 10/0;
}catch (ArithmeticException e) {throw e;
}
  1. 手动回滚事务
    使用TransactionAspectSupport.currentTransactionStatus()得到当前事务,并使用setRollbackOnly回滚.
try {int i = 10/0;
}catch (ArithmeticException e) {TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}

3. @Transactional详解

我们主要学习@Transactional注解的三个属性:
1. rollbackFor:异常回滚属性,指定能够触发事务回滚的异常类型.可以指定多个异常类型.
2. Isolation:事务的隔离级别,默认是Isolation.DEFAULT.
3. propagation:事务的传播机制.默认值为propagation.REQUIRED

3.1 rollbackFor

异常回滚的时候,@Transactional默认在遇到Error或者运行时异常时才会回滚.
在这里插入图片描述
接下来我们来使用代码验证:

@Transactional
@RequestMapping("/registry3")
public String registry3(String userName,String password) throws IOException {userService.registryUser(userName,password);if (true){throw new IOException();}return "注册成功";
}

向服务器提交数据:
在这里插入图片描述
在这里插入图片描述
我们看到,虽然抛出了异常,但是数据库的数据仍然被修改了.
如果我们要想指定回滚异常的类型,我们需要通过@Transactional的rollbackFor属性来完成,给属性传入异常的类对象来实现对回滚异常的指定,

@RequestMapping("/registry3")
@Transactional(rollbackFor = Exception.class)
public String registry3(String userName,String password) throws IOException {userService.registryUser(userName,password);if (true){throw new IOException();}return "注册成功";
}

运行程序:
在这里插入图片描述在这里插入图片描述
我们看到,事务并没有进行提交,被回滚了,数据库的数据并没有更行.

3.2 事务隔离级别

3.2.1 回顾MySQL中的事务隔离级别

https://lilesily12385.blog.csdn.net/article/details/137935719

3.3.2 Spring事务隔离级别

Spring中事务的隔离级别有5种:

  1. Isolation.DEFAULT: 以连接数据库的隔离级别为准.
  2. Isolation.READ_UNCOMMITTED:读未提交
  3. Isolating.READ_COMMITTED:读提交.
  4. Isolation.REPEATABLE_READ:可重复读.
  5. Isolation.SERIALIZABLE:串行化.
public enum Isolation {DEFAULT(-1),READ_UNCOMMITTED(1),READ_COMMITTED(2),REPEATABLE_READ(4),SERIALIZABLE(8);private final int value;private Isolation(int value) {this.value = value;}public int value() {return this.value;}
}

Spring中的隔离级别可以通过@Transactional中的Isolation属性进行设置.

@RequestMapping("/registry3")
@Transactional(isolation = Isolation.DEFAULT)
public String registry3(String userName,String password) throws IOException {userService.registryUser(userName,password);return "注册成功";
}

3.3 Spring事务传播机制

3.3.1 概念

事务的传播机制就是:多个事务方法存在调用关系的时候,事务是如何在这些方法之间进行传播的.事务的传播机制就解决的是一个事务在多个节点上(方法)中的传递.
在这里插入图片描述

比如有两个方法A和B,他们都被@Transactional修饰,方法A调用了方法B.A方法运行的时候,会开启一个新的事物,当A调用B的时候,B方法本身也有事务,此时B方法运行的时候,是假如A事务,还是创建一个新的事务呢?下面我们就来介绍一下事务的传播机制.

3.3.2 事务的传播机制分类

@Transactional注解支持事务的传播机制的设置,我们可以通过propagation属性来设置传播行为.

  1. Propagation.REQUIRED:加入事务,默认的事务传播级别.如果当前存在事务,则加入该事务,如果当前没有事务,则创建一个新的事务.(加入事务,就是共用一个事务,一个事务发生异常,全部回滚.)
  2. Propagation.SUPPORTS:如果当前存在事务,则加入该事务.如果当前没有事务,则以非事务的方式继续运行.
  3. Propagation.MANDATORY:强制性,如果当前存在事务,则加入该事务,如果当前没有事务,则抛出异常.
  4. Propagation.REQUIERS_NEW:新建事务,创建一个新事务如果当前存在事务,则把当前事务挂起.(发生异常,不影响其他事务)也就是不管外部方法是否开启事务,Propagation.REQUIERS_NEW修饰的内部方法都会新开启自己的事务,且开启的事务相互独立,互不干涉.
  5. Propagation.NOT_SUPPORTED: 以非事务的方式运行,如果当前存在事务则把当前事务挂起.
  6. Propagation.NEVER: 不支持当前事务,以非事务的方式运行,如果存在事务,则抛出异常.
  7. Propagation.NESTED: 嵌套事务,如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行,如果当前没有事务,则该取值等价于Propagation.REQUIRED.
    1,4对应,2,5对应,3,6对应.
public enum Propagation {REQUIRED(0),SUPPORTS(1),MANDATORY(2),REQUIRES_NEW(3),NOT_SUPPORTED(4),NEVER(5),NESTED(6);private final int value;private Propagation(int value) {this.value = value;}public int value() {return this.value;}
}

举例说明:一对新人结婚,需要房子

  1. Propagation.REQUIRES: 如果你有房子,就住你的房子(加入事务),如果你没有房子,我们就一起买房子(创建一个新事务).
  2. Propagation.SUPPORTS: 如果你有房子,我们就住你的房子(加入事务),如果没有房子,我们就租房子(以非事务的方式运行).
  3. Propagation.MANDATORY: 要求必须有房子(加入事务),如果没有房子,就不结婚(抛出异常)
  4. Propagation.REQUIERS_NEW: 必须买新房,不管你有没有房子,必须两个人一起买房(创建一个新事务),即使有房也不住(当前事务挂起).
  5. Propagation.NOT_SUPPORTED: 不管你有没有房子,我都不住(挂起当前事务),必须租房(以非事务的方式运行).
  6. Propagation.NEVER:不能有房子(当前存在事务),有房子就不结婚(抛出异常).
  7. Propagation.NESTED :如果你没房,就⼀起买房.如果你有房,我们就以房子为根据地,做点下生意.(如果如果当前存在事务,则创建⼀个事务作为当前事务的嵌套事务来运行.如果当前没有事务,则该取值等价于PROPAGATION_REQUIRED )

3.3.3 Spring事务传播机制代码演示

重点关注两个: REQUIRED,REQUIERS_NEW.

  • REQUIRED(加入事务)
    用户注册,插入一条数据,并记录操作日志.
@RequestMapping("/r4")
@Transactional
public String registry4(String userName,String password){userService.registryUser(userName,password);logService.insertLog(userName,"用户注册");return "注册成功";
}
@Service
public class UserService {@Autowiredpublic UserInfoMapper userInfoMapper;@Transactional(propagation = Propagation.REQUIRED)public void registryUser(String name,String password) {userInfoMapper.insert(name, password);}
}
@Service
public class LogService {@Autowiredprivate LogInfoMapper logInfoMapper;@Transactional(propagation = Propagation.REQUIRED)public void insertLog(String name,String op){int i = 10/0;//记录⽤⼾操作logInfoMapper.insertLog(name,"⽤户注册");}
}

我们在执行之后,发现数据库中并没有插入任何数据,这就是因为insertLog方法发生了异常,事务发生回滚,当事务回滚之后,registry4方法也发生了回滚,导致了registryUser也发生了回滚,导致数据库中没有插入数据.

  • REQUIRES_NEW(新建事务)
    将上面的UserService和LogService的事务传播机制改为Propagation.REQUIRES_NEW.
@RequestMapping("/r4")
@Transactional
public String registry4(String userName,String password){userService.registryUser(userName,password);logService.insertLog(userName,"用户注册");return "注册成功";
}
@Service
public class LogService {@Autowiredprivate LogInfoMapper logInfoMapper;@Transactional(propagation = Propagation.REQUIRES_NEW)public void insertLog(String name,String op){int i = 10/0;//记录⽤⼾操作logInfoMapper.insertLog(name,"⽤户注册");}
}
@Service
public class UserService {@Autowiredpublic UserInfoMapper userInfoMapper;@Transactional(propagation = Propagation.REQUIRES_NEW)public void registryUser(String name,String password) {userInfoMapper.insert(name, password);}
}

在执行之后,我们会发现,日志表中并没有插入新的数据,但是用户表中插入了新的数据,这是由于UserService,LogServiceregistry4属于不同的事务,LogService出现异常回滚之后不会影响registry4UserService的执行.

  • NEVER(不支持当前事务)
    REQUIRED代码的UserService中的对应方法的事务传播机制修改为Propagation.NEVER.并去掉制造的异常.
@Transactional(propagation = Propagation.NEVER)
public void insertLog(String name,String op){//记录⽤⼾操作logInfoMapper.insertLog(name,"用户注册");
}

运行之后,程序抛出异常,日志表和用户表均没有数据插入.

  • NESTED(嵌套事务)
    将上述REQUIREDUserService中的对应方法的事务传播机制修改为Propagation.NESTED.
@Transactional(propagation = Propagation.NESTED)
public void insertLog(String name,String op){int i = 10/0;//记录用户操作logInfoMapper.insertLog(name,"用户注册");
}
@Transactional(propagation = Propagation.NESTED)`在这里插入代码片`
public void registryUser(String name,String password) {userInfoMapper.insert(name, password);
}

运行程序之后,两张表中都没有插入任何数据,如果我们对出现异常的方法进行手动回滚:

@Transactional(propagation = Propagation.NESTED)
public void insertLog(String name,String op){try {int i = 10/0;}catch (Exception e){TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();}//记录用户操作logInfoMapper.insertLog(name,"用户注册");
}

在这里插入图片描述
我们看到,用户表插入成功了,但是日志表的数据被回滚了.
在这里插入图片描述
在这里插入图片描述

区分REQUIRED和NESTED
REQUIRED:当其中一个事务出现异常的时候,所有事务都会回滚,如果try-catch语句中对事物进行手动回滚,则子事务和父事务全部会被回滚.
NESTED : 当子事务出现异常的时候,子事务对应的父事务也会回滚,但是如果在有异常的子事务中进行try-catch,catch中对事务进行手动回滚,则只有出现异常的事务被回滚,但是另一个没有出现异常的子事务没有被回滚,与REQUIRED最大的区别就是,NESTED可以做到部分回滚,但是REQUIRED只能做到全部回滚.

相关文章:

[Spring] Spring事务与事务的传播

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏: &#x1f9ca; Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 &#x1f355; Collection与…...

Java 网络编程练习

InternetExercise1 package InternetExercise20240815;public class InternetExercise1 {public static void main(String[] args) {// 网络编程// 在网络通信协议下&#xff0c;不同计算机上面运行的程序&#xff0c;可以实现不同计算机上的数据传输// 网络编程三要素// 1.IP…...

中国科技统计年鉴,数据覆盖1991-2022年多年份

基本信息. 数据名称: 中国科技统计年鉴 数据格式: excel 数据时间: 1991-2022年 数据几何类型: xlsx 数据坐标系: WGS84 数据来源&#xff1a;国家统计局 数据预览&#xff1a; 数据可视化....

大模型的训练过程

大模型的训练是一个复杂的过程&#xff0c;涉及多个步骤和技术。下面我将概述大模型训练的主要流程&#xff0c;包括预训练、微调等关键阶段&#xff0c;并解释一些常见的技术和策略。 1. 数据准备 数据收集&#xff1a;收集大量多样化的数据&#xff0c;包括文本、图像、音频…...

4款ai在线改写工具,帮你轻松一键智能改写文章

在当今数字化内容创作的浪潮中&#xff0c;ai技术的应用为我们带来了极大的便利&#xff0c;尤其是在文章改写方面。以下将为大家详细分享四款出色的ai在线改写工具&#xff0c;从而帮助大家提升创作效率和质量。 ai在线改写工具一&#xff1a;智媒ai伪原创工具 它是一款备受好…...

Maven Mirror - 仓库镜像的介绍和配置

Maven Mirror&#xff08;Maven镜像&#xff09;是Maven构建工具中用于优化依赖下载速度和提高构建效率的一种机制。 在使用 Maven 构建应用程序时&#xff0c;Maven 默认会从 Maven 官方的中央仓库中下载依赖包。但是&#xff0c;在该仓库受到网络限制或访问速度过慢等问题时&…...

DevEcoStudio对Gitee进行变基与合并

当尝试将本地分支的更改推送到远程仓库&#xff0c;但是远程仓库中的该分支已经有了您本地分支中没有的提交时&#xff0c;会出现这个提示。 具体来说&#xff0c;这个提示意味着&#xff1a; 推送被拒绝&#xff1a;不能直接将更改推送到远程仓库&#xff0c;因为远程仓库中…...

2024 NVIDIA Summer Camp Day1:构建RAG多模态AI Agent

下载材料和课件等 课程相关资料下载链接: https://pan.baidu.com/s/15Y-gmsfeYCgKF-M3TJZVgg?pwdfafe 提取码: fafe 1.课件 链接&#xff1a;https://pan.baidu.com/s/15JTy9CqnesXSlPiwwrUmjA?pwd1111 提取码&#xff1a;1111 2.phi3量化大模型 链接&#xff1a;http…...

微服务之间的通信?

微服务之间的通信是微服务架构中的关键部分&#xff0c;它决定了服务之间如何进行数据交换和协同工作。微服务架构通过将大型应用拆分成多个小型、独立的服务&#xff0c;每个服务专注于完成特定的业务功能&#xff0c;从而提高了系统的可伸缩性、可维护性和可靠性。以下是微服…...

Elasticsearch 聚合概览及示例

Elasticsearch 是一个强大的搜索引擎&#xff0c;除了提供搜索功能外&#xff0c;它还内置了丰富的聚合功能&#xff0c;允许用户对数据进行统计、分析和运算。聚合可以帮助我们理解数据的分布和统计特性&#xff0c;是数据探索和报告的重要工具。本文将介绍 Elasticsearch 中的…...

【抓包】- Fiddler抓包教程,使用Fiddle抓取B站视频;ffmpeg的使用方法

一、预准备&#xff1a;过滤器设置 打开fiddler后&#xff0c;清空内容&#xff0c;然后播放视频。 找到与B站视频资源相关的回应&#xff0c;而后在“原始&#xff08;raw&#xff09;”标签中查看它的host信息。 发现B站视频资源的服务器DNS地址为【*bilivideo.cn】、【*bi…...

Linux网络配置和维护命令(三)

文章目录 网络接口配置-network-scripts文件远程复制文件-scp定义主机名与IP地址的关系-hosts文件登录远程主机-sshIP/主机名配置DNS域名解析服务器-resolv.conf文件 本篇讲解&#xff1a;网络接口配置-network-scripts文件、远程复制文件-scp、定义主机、名与IP地址的关系-hos…...

代码随想录算法训练营第二天 |209.长度最小子数组; 59.螺旋矩阵|| ; 前缀和

今日任务 209.长度最小子数组; 59.螺旋矩阵|| 58.区间和 44.开发商购买土地 209.长度最小的子数组 题目建议&#xff1a; 本题关键在于理解滑动窗口&#xff0c;这个滑动窗口看文字讲解 还挺难理解的&#xff0c;建议大家先看视频讲解。 拓展题目可以先不做。 题目链接&#xf…...

Go语言基础--数据类型(整型、字符型)

转义字符 常用的转义字符有如下: 1)\t : 表示一个制表符&#xff0c;通常使用它可以排版。 2)\n&#xff1a;换行符 3)\\&#xff1a;一个\ 4) \"&#xff1a;一个" 5)\r&#xff1a;一个回车 数据类型概述 在 Go 编程语言中&#xff0c;数据类型用于声明函数和变量…...

SpringBoot配置--Profile

目录 使用profile 的原因&#xff1f; proflie 的配置方式 多profile文件方式 profile 激活方式 1 配置文件 2 命令行参数 小结 使用profile 的原因&#xff1f; 用来完成不同环境下&#xff0c;配置动态切换功能的&#xff08;具体什么意思呢&#xff1f;假设你在A电脑…...

在Go中理解栈和先进先出原则

Go是一种功能强大的编程语言&#xff0c;提供了丰富的数据结构和算法。堆栈是计算机科学中的基本数据结构之一。在本博文中&#xff0c;我们将探讨如何在 Go 中实现和使用堆栈&#xff0c;以及堆栈如何遵循先进先出 (FIFO) 原则。 首先&#xff0c;让我们来看看堆栈是什么以及它…...

Ted靶机渗透测试

一、靶机下载地址 Ted: 1 ~ VulnHub 二、信息收集 1、主机发现 # 使用命令 nmap 192.168.145.0/24 -sn | grep -B 2 "00:0C:29:E2:36:FA" 2、端口扫描 # 使用命令 nmap 192.168.145.214 -p- -sV 3、指纹识别 # 使用命令 whatweb "http://192.168.145.214&…...

【chart.js】折线图给点添加点击事件

var mychart new Chart( ctx,{ type:line", … options:{ hover:{ // 此处最重要&#xff0c;决定是否能选中绑定的点 mode:“nearest” } &#xff0c; onClick:function(event,elements){ // 此为 被点击 的点 firstelement elements[0] // 这个点 属于第几个数据集合…...

旧手机NAS方案

这里写目录标题 1、参考2、alpine-term-v16.0-release.apk下载安装3、电脑端ssh连接3、安装docker3.1 网络配置3.2 配置APK源 1、参考 【Docker与Termux】闲置旧安卓手机上的NAS无缝部署方案 https://blog.csdn.net/AnRanGeSi/article/details/138717589 【Alpine Term】Andr…...

Secure CRT 9.x版本高亮着色配置文件

Secure CRT的网络配置文件高亮显示&#xff0c;还在完善&#xff0c;逐渐适配不同厂商 设备名字自动蓝色高亮显示设备接口名高亮显示IPv4地址、IPv6地址、MAC地址高亮显示掩码、反掩码高亮显示设备SN号高亮显示接口状态、设备状态等高亮显示各路由协议高亮显示 【下载地址】效果…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

什么是库存周转?如何用进销存系统提高库存周转率?

你可能听说过这样一句话&#xff1a; “利润不是赚出来的&#xff0c;是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业&#xff0c;很多企业看着销售不错&#xff0c;账上却没钱、利润也不见了&#xff0c;一翻库存才发现&#xff1a; 一堆卖不动的旧货…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...

Java 加密常用的各种算法及其选择

在数字化时代&#xff0c;数据安全至关重要&#xff0c;Java 作为广泛应用的编程语言&#xff0c;提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景&#xff0c;有助于开发者在不同的业务需求中做出正确的选择。​ 一、对称加密算法…...

Unit 1 深度强化学习简介

Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库&#xff0c;例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体&#xff0c;比如 SnowballFight、Huggy the Do…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建

华为云FlexusDeepSeek征文&#xff5c;DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色&#xff0c;华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型&#xff0c;能助力我们轻松驾驭 DeepSeek-V3/R1&#xff0c;本文中将分享如何…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)

本文把滑坡位移序列拆开、筛优质因子&#xff0c;再用 CNN-BiLSTM-Attention 来动态预测每个子序列&#xff0c;最后重构出总位移&#xff0c;预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵&#xff08;S…...

智能AI电话机器人系统的识别能力现状与发展水平

一、引言 随着人工智能技术的飞速发展&#xff0c;AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术&#xff0c;在客户服务、营销推广、信息查询等领域发挥着越来越重要…...

【Go语言基础【13】】函数、闭包、方法

文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数&#xff08;函数作为参数、返回值&#xff09; 三、匿名函数与闭包1. 匿名函数&#xff08;Lambda函…...

使用LangGraph和LangSmith构建多智能体人工智能系统

现在&#xff0c;通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战&#xff0c;比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...