Spring 学习笔记之 @Transactional 异常不回滚汇总
使用springboot时,只要引入spring-jdbc/jpa相关的依赖后,在想要启用事务的方法上加上@Transactional注解就能开启事务,碰到异常就能自动回滚。大大的提高了编码的便捷性性,同时也不侵入代码,保持了代码的简洁性。
默认情况下,Spring时使用的Spring AOP (mode=Mode.Proxy, proxyTargetClass=false)方式启动数据库事务拦截。只有了解清楚了具体背景,才能清除知道事务为什么在碰到异常时没有能够正确回滚。下面是一些常用场景分析:
场景1、未正确配置TransactionManager
使用springboot开发时,引入以下依赖后通常会自动启用TransactionManager。
-
spring-boot-starter-jdbc
是 Spring Boot 提供的用于简化 JDBC(Java Database Connectivity)开发的启动器,引入该依赖后,Spring Boot 会自动配置DataSourceTransactionManager
。 -
spring-boot-starter-data-jpa
是 Spring Boot 提供的用于简化 JPA(Java Persistence API)开发的启动器,它集成了 Hibernate 等 JPA 实现框架,方便开发者进行数据库操作。引入该依赖后,Spring Boot 会自动配置JpaTransactionManager
。
通过下面代码中的printTransactionManager(TransactionManager transactionManager) 方法可以检查是否配置正常。
@SpringBootApplication
public class MybatisApplication {public static void main(String[] args) {org.springframework.boot.SpringApplication.run(MybatisApplication.class, args);}@BeanObject printTransactionManager(TransactionManager transactionManager) {System.out.println("transactionManager: " + transactionManager);return null;}
}
transactionManager: org.springframework.jdbc.support.JdbcTransactionManager@590765c4
通过打印语句,可以看到spring中的TransactionManager是否正确配置。
场景2、@Transaction注解不在public方法上
默认情况下,事务是在proxy模式下(即Spring AOP负责拦截事务),proxyTargetClass=false ,有接口的时候使用JDK动态代理实现。没有接口时使用CGLIB进行代理。
JDK代理接口时,都是public方法。
CGLIB代理时,在public方法上能生效。在Spring 6.0 以后,除public方法外,可以代理protected, package-visable修饰的方法。
当@Transactional注解位于private/final修饰的方法上时,事务碰到异常不能正常回滚。
详情参考文档:
Method visibility and
@Transactional
in proxy modeThe
@Transactional
annotation is typically used on methods withpublic
visibility. As of 6.0,protected
or package-visible methods can also be made transactional for class-based proxies by default. Note that transactional methods in interface-based proxies must always bepublic
and defined in the proxied interface. For both kinds of proxies, only external method calls coming in through the proxy are intercepted.
Using @Transactional :: Spring Framework
示例代码:
@Service
public class UserService {@Autowiredprivate UserRepository userRepository;@Transactionalprivate void createUser(User user) {// 插入用户数据userRepository.save(user);// 可能会抛出异常if (user.getName().equals("error")) {throw new RuntimeException("创建用户失败");}}
}
因为方法的可见性,private修饰的方法不能被代理拦截
场景3、调用内部方法
@Transactional
注解使用 AOP 实现事务管理,而 AOP 是基于代理模式的。当在同一个类内部一个没有事务注解的方法调用有 @Transactional
注解的方法时,事务注解会失效,因为这种调用没有经过代理对象。
示例代码如下:
// 定义 UserService 类,处理用户相关业务逻辑
@Service
class UserService {@Autowiredprivate UserRepository userRepository;// 无事务注解的方法,内部调用有事务注解的方法public void outerMethod() {try {innerMethod();} catch (Exception e) {System.out.println("Exception caught: " + e.getMessage());}}// 有事务注解的方法@Transactionalpublic void innerMethod() {User user = new User("John");userRepository.save(user);// 模拟抛出异常throw new RuntimeException("Simulated exception");}
}
示例代码中,虽然Spring AOP代理了innerMethod方法,但是原始事务不是通过代理的innerMethod进入,而是通过原始类的outerMethod进入,这样就调用的是原始类的innerMethod方法,导致不能进入代理类的innerMethod方法,事务拦截不能生效。
场景4、方法内部Catch了异常
在 Spring 中使用 @Transactional
注解时,如果在方法内部捕获了异常且没有重新抛出,会导致事务无法正常回滚,从而使 @Transactional
注解失效。
@Transactional
注解的事务管理是基于 AOP 实现的,它会在目标方法抛出异常时进行事务回滚。默认情况下,@Transactional
注解只对未被捕获的 RuntimeException
及其子类异常进行回滚操作。如果在方法内部捕获了异常,Spring 就无法感知到异常的抛出,从而不会触发事务回滚逻辑,导致事务继续提交,@Transactional
注解的功能失效。
示例代码
// 定义 UserService 类,处理用户相关业务逻辑
@Service
class UserService {@Autowiredprivate UserRepository userRepository;@Transactionalpublic void createUser() {User user = new User("John");userRepository.save(user);try {// 模拟抛出异常throw new RuntimeException("Simulated exception");} catch (Exception e) {// 捕获异常但未重新抛出System.out.println("Exception caught: " + e.getMessage());}}
}
createUser()
方法:使用 @Transactional
注解标记,在方法内部保存用户信息后抛出一个 RuntimeException
异常,并在 catch
块中捕获该异常,但没有重新抛出。
解决办法:重新抛出异常
在 catch
块中重新抛出异常,让 Spring 能够感知到异常的发生,从而触发事务回滚逻辑。
@Transactional
public void createUser() {User user = new User("John");userRepository.save(user);try {throw new RuntimeException("Simulated exception");} catch (Exception e) {System.out.println("Exception caught: " + e.getMessage());// 重新抛出异常throw e;}
}
场景5、 rollbackFor/rollbackForClassName属性未正确配置
-
默认回滚规则:
@Transactional
注解默认只对RuntimeException
及其子类和Error
进行回滚。若抛出的是受检查异常(如IOException
、SQLException
),默认不会触发回滚。
@Service
class UserService {@Autowiredprivate UserRepository userRepository;@Transactionalpublic void createUser() throws IOException {User user = new User("John");userRepository.save(user);// 抛出受检查异常throw new IOException("Simulated IOException");}
}
IOException是一个CheckedException的子类,不在默认的回滚体系内,所以不能自动回滚。需要使用rollbackFor属性显式指定才能生效。
- rollbackFor=BaseException.class, 针对BaseException和它的子类回滚。若抛出的异常不在继承体系内,则不能自动回滚。
@Service public class OrderService {@Autowiredprivate OrderRepository orderRepository;@Transactional(rollbackFor = BaseException.class)public void createOrder(Order order) throws Exception {orderRepository.createOrder(order);// will rollback// throw new SubException("出现未知错误");// will not rollbackthrow new OtherException("出现未知错误");} }class BaseException extends Exception {public BaseException(String message) {super(message);} }class SubException extends BaseException {public SubException(String message) {super(message);} }class OtherException extends Exception {public OtherException(String message) {super(message);} }
rollbackForClassName=exceptionPattern, exceptionPattern可以包含异常名字全部或者部分字符。注意这里不是正则表达式,而是基于String.contains(exceptionPattern)来判断的。
匹配规则的源码如下:
private int getDepth(Class<?> exceptionType, int depth) {if (this.exceptionType != null) {if (this.exceptionType.equals(exceptionType)) {// Found it!return depth;}}else if (exceptionType.getName().contains(this.exceptionPattern)) {// Found it!return depth;}// If we've gone as far as we can go and haven't found it...if (exceptionType == Throwable.class) {return -1;}return getDepth(exceptionType.getSuperclass(), depth + 1);}
不能匹配的示例代码如下:
@Slf4j
@Service
public class OrderService {@Autowiredprivate OrderRepository orderRepository;@Transactional(rollbackForClassName = "Base*Exception")public void createOrder(Order order) throws Exception {orderRepository.createOrder(order);// will not rollbackthrow new Base1Exception("出现未知错误");}
}
因为exception.typeName="Base1Exception" contains("Base*Exception") 结果未false,所以不匹配,导致不能回滚。
正确的用法如下:
@Service
public class OrderService {@Autowiredprivate OrderRepository orderRepository;@Transactional(rollbackForClassName = "Base")public void createOrder(Order order) throws Exception {orderRepository.createOrder(order);// will rollbackthrow new Base1Exception("出现未知错误");}
}
以上是我过去经常碰到的@Transactional碰到异常不能正常回滚的案例总结,若有遗漏欢迎下方留言。
参考文档:
Declarative Transaction Management :: Spring Framework
相关文章:
Spring 学习笔记之 @Transactional 异常不回滚汇总
使用springboot时,只要引入spring-jdbc/jpa相关的依赖后,在想要启用事务的方法上加上Transactional注解就能开启事务,碰到异常就能自动回滚。大大的提高了编码的便捷性性,同时也不侵入代码,保持了代码的简洁性。 默认情…...
Java 自定义TCP协议:【特点编码字符串<=>字节<=>特点编码16进制】16进制字符串和编码的转换 (各种编码通过字节向16进制的互转)| XOR计算
文章目录 引言I 各种编码通过字节向16进制的互转。字符串<=>字节<=>16进制 | Java验证微信小程序 JavaScript字符串转gb2312 字符编码,以16进制字符串传输。(接收蓝牙设备的信息,发送北斗终端消息)II xor校验码Java实现验证C# 实现引言 为了避免中文在传输过程…...
大模型的使用
以下是不同类型大模型及其适用场景: 对话模型 - 代表模型:GPT-3.5/4、Claude、LaMDA、ChatGLM等。 - 适用场景:客服机器人为用户解答常见问题,提供实时支持;个人助理帮助用户完成各种任务,如查询信息、设置…...
OSPF的不规则区域和特殊区域
目录 一、OSPF不规则区域类型 1、非骨干区域无法和骨干区域保持连通 2、骨干区域被分割 解决方案 1、使用虚连接 2、使用多进程双向重发布(路由引入) 二、特殊区域 1、STUB区域(末梢区域) 2、totally stub区域(…...
C++学习:六个月从基础到就业——STL:分配器与设计原理
C学习:六个月从基础到就业——STL:分配器与设计原理 本文是我C学习之旅系列的第三十篇技术文章,也是第二阶段"C进阶特性"的第九篇,主要介绍C STL中的分配器设计原理与实现。查看完整系列目录了解更多内容。 引言 在之前…...
QQMusic项目功能总结
QQMusic项目功能总结 一、核心功能分类 (一)界面交互功能 功能模块实现方式使用类(自定义/Qt库)核心类说明窗口布局Head区(图标、搜索框、控制按钮) Body区(左侧功能栏右侧页面区)…...
人形机器人:MCP与人形机器人的联系
MCP(Model Context Protocol)与人形机器人的结合,正在重构智能体与物理世界的交互范式。这种联系不仅体现在技术架构的深度融合,更体现在对机器人认知能力、协作模式和应用场景的全方位赋能。以下从技术整合、场景落地和未来趋势三…...
matplotlib画图工具使用(1) 画折线统计图python代码
Python 画折线统计图(line chart)最常用的是 matplotlib。 最基本的折线图代码如下: import matplotlib.pyplot as plt# 假设这是你的数据 x [1, 2, 3, 4, 5] y [2, 3, 5, 7, 11]# 创建折线图 plt.plot(x, y, markero) # markero 是在点…...
神经网络与深度学习第四章-前馈神经网络
前馈神经网络 在本章中,我们主要关注采用误差反向传播来进行学习的神经网络。 4.1 神经元 神经元是构成神经网络的基本单元。主要是模拟生物神经元的结构和特性,接收一组输入信号并产生输出。 现代神经元中的激活函数通常要求是连续可导的函数。 净输…...
TC3xx学习笔记-UCB BMHD使用详解(一)
文章目录 前言UCB BMHDPINDISHWCFGLSENA0-3LBISTENACHSWENABMHDIDSTADCRCBMHDCRCBMHD_NPW0-7 总结 前言 AURIX Tc系列Mcu启动过程,必须要了解BMHD,本文详细介绍BMHD的定义及使用过程 UCB BMHD UCB表示User Configuration Block,UCB是Dflash,存储的地址…...
C语言 函数递归
目录 1.什么是递归 2.递归的限制条件 3.递归的举例 1.递归与迭代 1.递归是什么 递归是学习C语言函数绕不开的一个话题,那什么是递归呢? 递归其实是一种解决问题的方法,在C语言中,递归就是函数自己调用自己。 写一个史上最简单的C语言…...
4月25日日记(补)
最近实在是忙的不行了,做不到一天一更,但是实际上只需要每天拿出十分钟就可以写一篇不错的随笔或者说日记,我还是有点倦怠了。 昨天是4月25,我的生日,但是依旧是很忙碌的一天。零点准时拆了朋友们送的礼物,…...
【股票系统】使用docker本地构建ai-hedge-fund项目,模拟大师炒股进行分析。人工智能的对冲基金的开源项目
股票系统: https://github.com/virattt/ai-hedge-fund 镜像地址: https://gitcode.com/gh_mirrors/ai/ai-hedge-fund 项目地址: https://gitee.com/pythonstock/docker-run-ai-hedge-fund 这是一个基于人工智能的对冲基金的原理验证项目。本项目旨在探讨利用人工智能进行…...
Ollama平替!LM Studio本地大模型调用实战
本文已收录在Github,关注我,紧跟本系列专栏文章,咱们下篇再续! 🚀 魔都架构师 | 全网30W技术追随者🔧 大厂分布式系统/数据中台实战专家🏆 主导交易系统百万级流量调优 & 车联网平台架构&a…...
2024江西ICPC部分题解
题目列表 A - Maliang Learning PaintingC - LiarG - Multiples of 5H - ConvolutionJ - Magic MahjongK - Magic Tree A - Maliang Learning Painting 题目来源:A - Maliang Learning Painting 思路分析 这是个签到题,直接输出abc即可 #include<b…...
RabbitMQ安装流程(Windows环境)
1.下载依赖,Downloads - Erlang/OTP 2.下载RabbitMQ安装包,Installing on Windows | RabbitMQ 3.下载的文件如下 4.安装ErLang依赖 5.安装RabbitMQ 6.RabbitMQ插件管理 6.1 进入Command Prompt命令行界面 6.2 输入rabbitmq-plugins.bat list 查看所有插…...
QT对话框及其属性
Qt中使用QDialog类表示对话框 对话框是一个顶层窗口,出现在程序最上层,用于实现短期任务或者简洁的用户交互 QDialog也是继承自QWidget,可以使用QWidget接口 Qt常用的内置对话框有: 对话框 说明 QFiledialog 文件对话框 QColorDialog 颜色对话框 …...
python怎么查看函数原型及变量是什么类型
python代码中看到一个变量或者对象名,怎么查看这个变量到底是个什么东西,是属性,还是函数,还是模块,还是个包,怎么去查看,要有一个查找流程: 1.可以先用print(变量名)和print(type(变量名)),确认变量是什么类型的参数 2.如果是模块或者类,可以通过dir()函数去查看模…...
住宅代理IP助力大规模数据采集实战
在数字化时代,数据就是燃料,而大规模数据采集则是从信息海洋中提炼价值的关键手段。面对目标网站的严格风控和地域限制,普通代理车轮战往往难以为继——流量一旦被识破,便可能付之东流。这时,住宅代理IP凭借来自真实家…...
【信息融合】卡尔曼滤波EKF毫米波雷达和红外数据信息融合
一、扩展卡尔曼滤波(EKF)的核心原理 EKF是针对非线性系统的改进卡尔曼滤波算法,其核心思想是通过一阶泰勒展开对非线性方程进行局部线性化,并利用雅可比矩阵(Jacobian Matrix)替换线性系统中的状态转移矩阵…...
一篇入门之-评分卡变量分箱(卡方分箱、决策树分箱、KS分箱等)实操例子
一、评分卡分箱-有哪些分箱方法 评分卡的分箱,是指将变量进行离散化。评分卡的分箱方法一般有:等频分箱、等距分箱、卡方分箱、决策树分箱、KS分箱等等。它们都属于自动分箱方法,其中,卡方分箱是实际中最常用的分箱方法。 1.1.等…...
【白雪讲堂】构建与优化企业知识图谱的实战指南
在GEO(生成式引擎优化)时代,知识图谱不仅是企业数据资产的“智慧大脑”,更是连接内容与AI理解之间的核心桥梁。一个高质量的知识图谱,能够显著提高AI平台对企业内容的识别度、相关性与推荐权重,从而在AI搜索…...
作为高速通道光纤传输模式怎么理解以及到底有哪些?
光纤的传输模式主要取决于光纤的结构(如纤芯直径和折射率分布),不同模式对应光波在光纤中传播的不同路径和电磁场分布。以下是光纤传输模式的主要分类及特点: 1. 单模光纤(Single-Mode Fiber, SMF) 核心特点: 纤芯直径极小(通常为 8-10微米),仅允许光以单一模式(…...
setup语法糖
为什么要有setup语法糖: 在选择式API中,一个模块涉及到的数据、方法、声明周期,会比较分撒,位置不集中,不利于解读代码,但是组合式API中的setup函数可以将他们组织在一起,提高了代码的可维护性…...
linux socket编程之tcp(实现客户端和服务端消息的发送和接收)
目录 一.创建socket套接字(服务器端) 二.bind将port与端口号进行绑定(服务器端) 2.1填充sockaddr_in结构 2.2bind绑定端口 三.建立连接 四.获取连接 五..进行通信(服务器端) 5.1接收客户端发送的消息 5.2给客户端发送消息 5.3引入多线程 六.客户端通信 6.1创建socke…...
Spring和Spring Boot集成MyBatis的完整对比示例,包含从项目创建到测试的全流程代码
以下是Spring和Spring Boot集成MyBatis的完整对比示例,包含从项目创建到测试的全流程代码: 一、Spring集成MyBatis示例 1. 项目结构 spring-mybatis-demo/ ├── src/ │ ├── main/ │ │ ├── java/ │ │ │ └── com.example/…...
Beta-VAE背景原理及解耦机制分析
Beta-VAE背景原理及解耦机制分析 论文链接:https://openreview.net/forum?idSy2fzU9gl¬eIdSy2fzU9gl 一、Beta-VAE的核心思想 Beta-VAE 是一种改进的变分自编码器(VAE),旨在通过调整潜在变量的独立性来增强模型的解耦能…...
用c语言实现——一个动态顺序存储的串结构
一、思路概要 ①动态顺序存储的串结构: 动态应该使用动态内存分配,也就是用指针来存储字符数组,同时记录长度和当前容量。 这样结构体应该包含三个成员:一个char*指针,一个int表示当前长度,另一个int表示…...
小程序Npm package entry file not found?
修改依赖包的入口文件 看是不是cjs,小程序不支持cjs...
vue3学习之防抖和节流
在前端开发中,我们经常会遇到这样的情况:某些事件(如滚动、输入、点击等)会频繁触发,如果不加以控制,可能会导致性能问题。Vue3 中的防抖(Debounce)和节流(Throttle&a…...
当高级辅助驾驶遇上“安全驾校”:NVIDIA如何用技术给无人驾驶赋能?
高级辅助驾驶技术的商业化落地,核心在于能否通过严苛的安全验证。国内的汽车企业其实也在做高级辅助驾驶,但是吧,基本都在L2级别。换句话说就是在应急时刻内,还是需要人来辅助驾驶,AI驾驶只是决策层,并不能…...
Linux | Mfgtools 修改单独只烧写 Uboot,内核,文件系统
01 1. 打开 mfgtools_for_6ULL 文件夹,找到 cfg.ini 文件,如果您的板子是 EMMC 的修改如下图: 如果您的板子是 NAND 的,修改如下图: 02 2. 打开“Pro...
【Agent python实战】ReAct 与 Plan-and-Execute 的融合之道_基于DeepSeek api
写在前面 大型语言模型(LLM)驱动的 Agent 正在从简单的任务执行者向更复杂的问题解决者演进。在 Agent 的设计模式中,ReAct (Reason + Act) 以其步步为营、动态适应的特性见长,擅长处理需要与环境实时交互、快速响应的任务。而 Plan-and-Execute 则强调前瞻性规划,先制定…...
Native层Trace监控性能
一、基础实现方法 1.1 头文件引用 #include <utils/Trace.h> // 基础版本 #include <cutils/trace.h> // 兼容旧版本1.2 核心宏定义 // 区间追踪(推荐) ATRACE_BEGIN("TraceTag"); ...被监控代码... ATRACE_END();// 函数级自…...
【C++】15. 模板进阶
1. 非类型模板参数 模板参数分类类型形参与非类型形参。 类型形参即:出现在模板参数列表中,跟在class或者typename之类的参数类型名称。 非类型形参:就是用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当…...
C#进阶学习(十四)反射的概念以及关键类Type
目录 本文末尾有相关类中的总结,如有需要直接跳到最后即可 前置知识: 1、程序集(Assembly) 2、元数据(Metadata) 3、中间语言(IL, Intermediate Language) 中间语言(…...
B. And It‘s Non-Zero
题目链接:https://codeforces.com/problemset/problem/1615/B 位运算之前没怎么写过,所以不会写。留一份题解,作为复习使用。 题解:按位与的结果不为0,则至少有一列全为1.要求删除的数最少,即要求该列原本…...
深入解析NuttX:为何它是嵌入式RTOS领域的标杆?
文章目录 引言一、NuttX简介:轻量级与高兼容性的结合二、架构特点:为何NuttX更灵活?三、横向对比:NuttX vs 主流嵌入式RTOS四、NuttX的核心优势五、何时选择NuttX?结语 引言 在资源受限的嵌入式系统中,实时…...
html初识
html 盖楼第一步:HTML1. HTML是啥玩意儿?2. 动手!搭个你的"网络小窝" (第一个HTML页面)3. 添砖加瓦:常用HTML"建材"详解3.1 标题家族3.2 段落哥俩好3.3 传送门:链接3.4 挂画:图片 盖楼…...
leetcode66.加一
从后向前遍历,直到碰到非9的数(也就是数组中中最后一个非9的数) ,该值+1,然后其后的数字全部0 class Solution {public int[] plusOne(int[] digits) {for (int i digits.length-1; i >0; i--) {if (d…...
【Vue】Vue3项目创建
执行npm run dev,如果报错检查nodejs版本...
缓存替换算法之 FIFO(先进先出)
FIFO(First In, First Out,先进先出)是一种常见的缓存替换算法,其基本思想是最早进入缓存的数据项将最先被移除。以下是FIFO的详细讲解: 一、FIFO的数据结构 队列(Queue) 队列是一种典型的线性…...
Linux下的I/O复用技术之epoll
I/O多路复用 指在单个线程或进程中,同时处理多个I/O操作的技术。 旨在提高程序处理多个并发I/O操作的能力,避免程序因等待某个I/O操作而被阻塞。在传统的I/O模型中当程序进行I/O操作时(如读取文件、接受网路数据等),如果数据还未准备好&…...
数据分析管理软件 Minitab 22.2.2 中文版安装包 免费下载
Minitab22.2.2 安装包下载链接: https://pan.baidu.com/s/1cWuDbvcWhYrub01C6QR81Q?pwd6666 提取码: 6666 Minitab软件是现代质量管理统计软件,全球六西格玛实施的共同语言。Minitab 已经在全球120多个国家,5000多所高校被广泛使用。...
chrony服务器(1)
简介 NTP NTP(Network Time Protocol,网络时间协议)是一种用于同步计算机系统时间的协议是TCP/IP协议族中的一个应用层协议,主要用于在分布式时间服务器和客户端之间进行时钟同步,提供高精准度的时间校正通过分层的时…...
2025.04.26-淘天春招笔试题-第三题
📌 点击直达笔试专栏 👉《大厂笔试突围》 💻 春秋招笔试突围在线OJ 👉 笔试突围OJ 03. 二进制信号转换器 问题描述 卢小姐是一位通信工程师,她设计了一种特殊的二进制信号处理装置。该装置可以对由 0 0 0...
腾讯二面:TCC分布式事务 | 图解TCC|用Go语言实现一个TCC
写在前面 前段时间,有同学反馈的一个面试问题,觉得分布式事务有点偏了,但其实也不算偏了,在java领域就有很火很成熟的seata分布式事务框架(阿里和蚂蚁的同学主导,目前在apache孵化)。 之前我们讲过了两阶段提交、三阶…...
如何在 Conda 环境中降级 Python 版本:详细指南
如何在 Conda 环境中降级 Python 版本:详细指南 Python 版本的管理在开发过程中至关重要,特别是在处理不同项目需求时。对于使用 Conda 环境的 Python 程序员来说,版本管理不仅仅是安装不同的 Python 版本,还涉及到依赖关系的兼容…...
MCP 协议解读:STDIO 高效通信与 JSON-RPC 实战
本文深度解析 MCP 协议的传输机制与消息格式,涵盖 stdio、SSE 及自定义传输方式,剖析 JSON-RPC 2.0 的请求、响应与通知设计。 结合 RooCode 开源实现与天气查询案例,揭秘如何通过 MCP 实现跨进程通信与高效服务集成,为开发者提供…...
AI心理健康服务平台项目面试实战
AI心理健康服务平台项目面试实战 第一轮提问: 面试官: 请简要介绍一下AI心理健康服务平台的核心技术架构。在AI领域,心理健康服务的机遇主要体现在哪些方面?如何利用NLP技术提升用户与AI的心理健康对话体验? 马架构…...