spring mvc中不同服务调用类型(声明式(Feign)、基于模板(RestTemplate)、基于 SDK、消息队列、gRPC)对比详解
@RestControllerAdvice 和 @ControllerAdvice 对比详解
1. 基本概念
| 注解 | 等效组合 | 核心作用 |
|---|---|---|
@ControllerAdvice | @Component + @RequestMapping(隐式) | 定义全局控制器增强类,处理跨控制器的异常、数据绑定或全局响应逻辑。 |
@RestControllerAdvice | @ControllerAdvice + @ResponseBody | 继承 @ControllerAdvice,并默认将返回值序列化为 HTTP 响应体(如 JSON)。 |
2. 核心区别
| 对比维度 | @ControllerAdvice | @RestControllerAdvice |
|---|---|---|
| 返回值处理 | 默认返回视图名称(需配合 @ResponseBody 才能序列化) | 直接返回数据对象,自动序列化为响应体(如 JSON) |
| 适用场景 | 传统 MVC 应用(如返回 HTML 视图或混合响应) | RESTful API(需返回 JSON/XML 格式数据) |
| 注解组合 | 需手动添加 @ResponseBody 才能返回 JSON | 内置 @ResponseBody,无需额外声明 |
| 返回类型示例 | String(视图名称)、ModelAndView | ResponseEntity, Map, 自定义 POJO |
3. 代码示例对比
场景:全局异常处理
@ControllerAdvice 示例(返回视图名称)
@ControllerAdvice
public class GlobalViewExceptionHandler {@ExceptionHandler(IOException.class)public String handleIOException() {return "error/500"; // 返回视图名称(如 Thymeleaf 模板)}
}
@RestControllerAdvice 示例(返回 JSON)
@RestControllerAdvice
public class GlobalApiExceptionHandler {@ExceptionHandler(IOException.class)public ResponseEntity<ErrorDetails> handleIOException() {ErrorDetails error = new ErrorDetails(500, "Internal Server Error", null);return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);}
}
4. 关键功能对比
| 功能 | @ControllerAdvice | @RestControllerAdvice |
|---|---|---|
| 异常处理 | 支持,需手动定义返回类型(视图或 JSON) | 支持,直接返回 JSON 格式错误对象 |
| 数据绑定 | 可通过 @InitBinder 统一配置绑定规则 | 同样支持 @InitBinder,但返回值默认序列化 |
| 全局方法增强 | 可通过 @ModelAttribute 注入公共数据 | 同样支持,但返回数据自动序列化 |
| 响应体控制 | 需显式使用 @ResponseBody 或 ResponseEntity | 内置 @ResponseBody,无需额外声明 |
5. 配置与扩展
共同特性
-
包级作用域:通过
basePackages指定需要增强的控制器包:@ControllerAdvice(basePackages = "com.example.controllers") -
方法级过滤:通过
annotations指定仅处理特定注解的控制器:@ControllerAdvice(annotations = RestController.class)
差异点
- 响应体格式:
-
@ControllerAdvice需显式配置@ResponseBody或ResponseEntity才能返回 JSON:@ControllerAdvice public class MixHandler {@ResponseBody // 显式声明返回 JSON@ExceptionHandler(IOException.class)public ErrorDetails handleIOException() { ... } } -
@RestControllerAdvice默认支持序列化:@RestControllerAdvice public class ApiHandler {@ExceptionHandler(IOException.class)public ErrorDetails handleIOException() { ... } // 自动序列化为 JSON }
-
6. 典型使用场景
| 场景 | 推荐注解 | 原因 |
|---|---|---|
| 传统 Web 应用(返回 HTML) | @ControllerAdvice | 需返回视图名称(如 Thymeleaf 模板路径)。 |
| RESTful API 异常处理 | @RestControllerAdvice | 直接返回结构化的 JSON 错误信息,无需额外配置 @ResponseBody。 |
| 混合场景(需同时处理视图和 JSON) | @ControllerAdvice | 需通过 @ResponseBody 区分返回类型,或使用 ResponseEntity 控制响应格式。 |
7. 总结表格
| 维度 | @ControllerAdvice | @RestControllerAdvice |
|---|---|---|
| 核心作用 | 全局异常处理、数据绑定、视图增强 | 专为 REST API 设计,返回 JSON 格式响应 |
| 返回值默认行为 | 返回视图名称或需 @ResponseBody 显式声明 | 直接返回数据对象,自动序列化为响应体 |
| 适用场景 | 传统 MVC 应用、混合响应场景 | 纯 REST API 开发(如 Spring Boot 微服务) |
| 注解组合关系 | 独立注解,需手动配置响应格式 | 等效于 @ControllerAdvice + @ResponseBody |
关键总结### 声明式服务调用与其他服务调用类型对比详解
1. 什么是声明式服务调用?
定义:通过注解或配置声明服务调用接口,无需手动编写底层网络请求代码,由框架自动生成代理实现。
核心特点:
- 声明式:通过注解(如
@FeignClient)或配置定义服务接口。 - 自动代理:框架(如 Spring Cloud Feign)自动处理 HTTP 请求、序列化、负载均衡等。
- 解耦:开发者只需关注业务逻辑,无需关心网络细节。
示例(Spring Cloud Feign):
@FeignClient(name = "service-provider") // 声明调用的服务名称
public interface ProductClient {@GetMapping("/products/{id}")Product getProduct(@PathVariable("id") String id);
}
2. 其他服务调用类型及对比
类型 1:基于模板的调用(如 RestTemplate/HttpClient)
定义:手动构造 HTTP 请求,通过模板工具(如 RestTemplate、OkHttp)发送请求并处理响应。
特点:
- 灵活控制:可完全控制请求参数、超时、重试等。
- 无侵入性:无需框架支持,纯 Java 实现。
- 代码冗长:需手动处理异常、序列化等。
使用方法:
// 使用 RestTemplate 调用服务
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<Product> response = restTemplate.getForEntity("http://service-provider/products/123",Product.class
);
Product product = response.getBody();
类型 2:基于 SDK 的调用
定义:通过第三方或自定义 SDK 封装服务调用逻辑,提供统一接口。
特点:
- 封装复杂逻辑:如 AWS SDK 封装了 S3、DynamoDB 的调用细节。
- 依赖性强:需引入 SDK 依赖,版本需与服务端兼容。
- 易用性高:开发者无需关心底层协议。
使用示例(AWS S3 SDK):
AmazonS3 s3Client = AmazonS3ClientBuilder.standard().withRegion("us-west-2").build();
S3Object object = s3Client.getObject("my-bucket", "key-name");
类型 3:基于消息队列的异步调用
定义:通过消息中间件(如 RabbitMQ、Kafka)发送异步消息,由消费者处理。
特点:
- 解耦:生产者与消费者无直接依赖。
- 异步:支持高并发和最终一致性。
- 需消息中间件:需维护消息队列基础设施。
使用示例(Spring Cloud Stream):
// 生产者发送消息
@Service
public class OrderService {@Autowiredprivate MessageChannel orderChannel;public void sendOrder(Order order) {orderChannel.send(MessageBuilder.withPayload(order).build());}
}// 消费者处理消息
@Service
public class OrderConsumer {@StreamListener("order-inbound")public void processOrder(Order order) {// 处理订单逻辑}
}
类型 4:基于 gRPC 的调用
定义:使用 gRPC 框架进行高性能的 RPC 调用,基于 Protocol Buffers 定义接口。
特点:
- 高性能:二进制协议,支持流式传输。
- 强类型定义:通过
.proto文件定义接口和数据结构。 - 学习成本高:需掌握 gRPC 和 Protocol Buffers。
使用示例:
// 定义 proto 文件
service ProductService {rpc GetProduct (ProductRequest) returns (ProductResponse) {}
}// 生成客户端代码
ProductServiceBlockingStub stub = ProductGrpc.newBlockingStub(channel);
ProductResponse response = stub.getProduct(request);
类型 5:基于 HTTP 客户端(如 OkHttp)的直接调用
定义:直接使用低层 HTTP 客户端(如 OkHttp、URLConnection)发送请求。
特点:
- 完全控制:可配置超时、连接池等。
- 无需框架依赖:纯 Java 实现。
- 代码复杂度高:需手动处理序列化、异常等。
示例(OkHttp):
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url("http://service-provider/products/123").build();
Response response = client.newCall(request).execute();
String responseBody = response.body().string();
3. 对比总结表格
| 类型 | 声明式 | 基于模板 | 基于 SDK | 消息队列 | gRPC |
|---|---|---|---|---|---|
| 核心特点 | 注解声明,框架代理 | 手动构造请求 | 封装第三方接口 | 异步解耦 | 高性能 RPC |
| 代码复杂度 | 简单(无需手动请求) | 中等(需处理细节) | 简单(依赖 SDK) | 中等(需消息配置) | 高(需 proto 定义) |
| 适用场景 | 微服务内同步调用 | 需灵活控制的场景 | 第三方服务调用 | 解耦异步场景 | 高性能同步 RPC |
| 框架依赖 | Spring Cloud | 无(需 RestTemplate) | SDK 依赖 | RabbitMQ/Kafka | gRPC 库 |
| 是否同步/异步 | 同步(可配置异步) | 同步/异步 | 同步/异步 | 异步 | 同步/异步流 |
| 典型工具 | Feign | RestTemplate,OkHttp | AWS SDK | Spring Cloud Stream | gRPC |
4. 选择依据
| 需求场景 | 推荐类型 | 原因 |
|---|---|---|
| 快速集成微服务同步调用 | 声明式(Feign) | 零代码实现负载均衡、熔断,开发效率高。 |
| 需灵活控制 HTTP 请求细节 | 基于模板(RestTemplate) | 直接控制超时、重试等参数。 |
| 调用第三方服务(如 AWS) | 基于 SDK | 使用官方 SDK 确保兼容性和易用性。 |
| 解耦服务间依赖 | 消息队列 | 异步通信,高并发场景下避免阻塞。 |
| 高性能低延迟的 RPC 调用 | gRPC | 二进制协议和流式传输适合高频、低延迟场景。 |
5. 关键总结
- 声明式服务调用(如 Feign):开发效率最高,适合微服务内同步调用。
- 基于模板/SDK:灵活性与易用性平衡,适合复杂或第三方服务调用。
- 消息队列:解耦与异步的首选方案。
- gRPC:高性能场景的最优选择,需权衡学习成本。
根据项目需求(如性能、耦合度、开发效率),选择合适的调用方式,或混合使用多种类型以满足不同场景。
- 选择原则:
- REST API:优先使用
@RestControllerAdvice,简化 JSON 响应处理。 - 传统 MVC:使用
@ControllerAdvice,灵活控制视图或 JSON 响应(需配合@ResponseBody)。
- REST API:优先使用
- 注意事项:
@ControllerAdvice若需返回 JSON,必须显式添加@ResponseBody或使用ResponseEntity。@RestControllerAdvice内置@ResponseBody,无需额外声明,适合统一 API 响应格式。
- 最佳实践:
- 对于纯 API 项目,用
@RestControllerAdvice集中处理异常和响应。 - 在混合项目中,通过
basePackages区分不同场景的增强类。
- 对于纯 API 项目,用
相关文章:
spring mvc中不同服务调用类型(声明式(Feign)、基于模板(RestTemplate)、基于 SDK、消息队列、gRPC)对比详解
RestControllerAdvice 和 ControllerAdvice 对比详解 1. 基本概念 注解等效组合核心作用ControllerAdviceComponent RequestMapping(隐式)定义全局控制器增强类,处理跨控制器的异常、数据绑定或全局响应逻辑。RestControllerAdviceControll…...
【Java设计模式】第1章 课程导学
第1章 课程导学 1-1 课堂导学 课程介绍 设计模式是工程师必备知识,面试高频考点。课程目标:提炼常用设计模式精华,结合场景演进和源码解析,系统学习设计模式。课程特色: 动态递进式讲解,通过场景变化展示…...
Java + WebAssembly 2025:如何用Rust优化高性能Web应用?
📝 摘要 随着WebAssembly(WASM)技术的成熟,Java开发者现在可以通过结合Rust来构建更高性能的Web应用。本文将详细介绍如何在2025年的技术栈中使用Java和Rust通过WebAssembly实现性能优化,包括基础概念、实际应用场景、详细代码示例以及性能对…...
MCU控制4G模组(标准AT命令),CatM的最大速率?
根据3GPP标准,Cat M1的上行峰值速率大约是1 Mbps,下行大约是1 Mbps。但实际速率会受到多种因素影响,比如网络条件、信号强度、模块配置等。 考虑使用AT命令时的开销。每次发送数据都需要通过AT命令,比如ATQISEND,会引…...
致远OA —— 表单数据获取(前端)
文章目录 :apple: 业务需求描述 🍎 业务需求描述 测试案例: https://pan.quark.cn/s/3f58972f0a27 官网地址: https://open.seeyoncloud.com/v5devCAP/94/355/359/399/405/406.html 需求描述: 点击获取数据接口,…...
游戏引擎学习第214天
总结并为当天的任务做好准备 昨天,我们将所有调试控制代码迁移到使用新的调试接口中,但我们没有机会实际启用这些代码。我们做了很多准备工作,比如规划、将其做成宏、并将其放入调试流中,但实际上我们还没有办法进行测试。 今天…...
码率自适应(ABR)相关论文阅读简报2
论文5简介 标题:PAR:IMPROVING VIDEO BITRATE ADAPTATION VIA PAYLOAD-A W ARE THROUGHPUT PREDICTION 作者:Jialiang Pei, Congkai An, Anfu Zhou, Liang Liu, Huadong Ma 单位: 中国北京邮电大学计算机学院 发表会议: Conference on Mu…...
环信鸿蒙版 UIKit 快速上手指南
环信鸿蒙版 UIKit 是专为 HarmonyOS 开发者设计的 IM UI 组件库,基于环信 IM SDK 开发,可帮助开发者快速集成即时通讯功能。 环信UIKit 的特点 ArkUI 声明式开发范式:采用高效简洁的声明式开发方式状态管理 V2:支持深度观测和精…...
核心机制与主流协议解析
一、收益聚合器的核心逻辑 收益聚合器(Yield Aggregator)通过算法自动优化用户在DeFi协议中的资金配置,解决「收益耕作(Yield Farming)」的两大痛点: 机会捕捉:实时追踪高收益矿池(…...
使用stm32cubeide stm32f407 lan8720a freertos lwip 实现udp client网络数据转串口数据过程详解
1前言 项目需要使用MCU实现网络功能,后续确定方案stm32f407 外接lan8720a实现硬件平台搭建,针对lan8720a也是用的比较多的phy,网上比较多的开发板,硬件上都是选用了这个phy,项目周期比较短,选用了这个常用…...
Go:入门
文章目录 Hello, World命令行参数找出重复行GIF动画获取一个URL并发获取多个URL一个 Web 服务器其他 Hello, World Hello world package main import "fmt" func main() {fmt.Println("Hello, 世界") }package main表明这是一个可独立执行的程序包&#…...
createContext+useContext+useReducer组合管理React复杂状态
createContext、useContext 和 useReducer 的组合是 React 中管理全局状态的一种常见模式。这种模式非常适合在不引入第三方状态管理库(如 Redux)的情况下,管理复杂的全局状态。 以下是一个经典的例子,展示如何使用 createContex…...
JVM常见问题与调优
目录 一、内存管理问题 1、内存泄漏(Memory Leak) 2、内存溢出(OOM, OutOfMemoryError) 2.1 堆内存溢出(OutOfMemoryError: Java heap space) 2.2 元空间溢出(OutOfMemoryError: Metaspace…...
汽车售后诊断 ODX 和 OTX 对比分析报告
一、引言 在汽车行业不断发展的当下,汽车售后诊断技术对于保障车辆性能、维护车主权益以及提升汽车品牌服务质量起着至关重要的作用。随着汽车电子化程度的不断提高,售后诊断所涉及的数据和流程愈发复杂,这就促使行业需要更加标准化、高效化…...
AI重构农业:从“面朝黄土“到“数字原野“的产业跃迁—读中共中央 国务院印发《加快建设农业强国规划(2024-2035年)》
在东北黑土地的万亩良田上,无人机编队正在执行精准施肥作业;在山东寿光的智慧大棚里,传感器网络实时调控着番茄生长的微环境;在云南的咖啡种植园中,区块链溯源系统记录着每粒咖啡豆的旅程。这场静默的农业革命…...
go游戏后端开发33:解散房间
接下来,我们来实现房间的解散功能。因为在调试过程中,如果不能取消房间,就需要频繁重启程序,这非常不方便。所以,我们先来实现这个解散功能。 房间解散的流程其实很简单。当发起解散请求后,我们会向所有用…...
Cloudflare教程:免费优化CDN加速配置,提升网站访问速度 | 域名访问缓存压缩视频图片媒体文件优化配置
1、启用 Tiered Cache 缓存开关:通过选择缓存拓扑,可以控制源服务器与 Cloudflare 数据中心的连接方式,以确保缓存命中率更高、源服务器连接数更少,并且 Internet 延迟更短。 2、增加浏览器缓存时间TTL:在此期间&#…...
Python设计模式:策略模式
1. 什么是策略模式 策略模式(Strategy Pattern)是一种行为型设计模式,它定义了一系列算法,将每个算法封装起来,并使它们可以互换。策略模式使得算法的变化独立于使用算法的客户。换句话说,策略模式允许在运…...
JavaScript(JS进阶)
目录 00闭包 01函数进阶 02解构赋值 03通过forEach方法遍历数组 04深入对象 05内置构造函数 06原型 00闭包 <!-- 闭包 --><html><body><script>// 定义:闭包内层函数(匿名函数)外层函数的变量(s&…...
C/C++共有的类型转换与c++特有的四种强制类型转换
前言 C 语言和 C 共有的类型转换: 自动类型转换(隐式类型转换): 编译器在某些情况下会自动进行的类型转换。强制类型转换(显示类型转换): 使用 (type)expression 或 type(expression) 语法进行…...
Nginx 负载均衡案例配置
负载均衡案例 基于 docker 进行 案例测试 1、创建三个 Nginx 实例 创建目录结构 为每个 Nginx 实例创建单独的目录,用于存储 HTML 文件和配置文件 mkdir -p data/nginx1/html mkdir -p data/nginx2/html mkdir -p data/nginx3/html添加自定义 HTML 文件 在每个…...
【蓝桥杯】贪心算法
1. 区间调度 1.1. 题目 给定个区间,每个区间由开始时间start和结束时间end表示。请选择最多的互不重叠的区间,返回可以选择的区间的最大数量。 输入格式: 第一行包含一个整数n,表示区间的数量 接下来n行,每行包含两个整数,分别表示区间的开始时间和结束时间 输出格式:…...
LLaMA-Factory 数据集成从入门到精通
一、框架概述 LLaMA-Factory 框架通过Alpaca/Sharegpt双格式体系实现多任务适配,其中Alpaca专注结构化指令微调(含SFT/DPO/预训练),Sharegpt支持多角色对话及多模态数据集成。核心配置依托 dataset_info.json 实现数据源映射、格…...
数据库架构
常见数据库架构类型及其优势解析 1. 集中式架构(Centralized Architecture) 定义:所有数据存储在单个服务器或主机上,由中央处理器统一管理。核心优势: ✅ 数据一致性:单一数据源避免数据冗余和不一致。 …...
OSPF接口的网络类型和不规则区域
网络类型(数据链路层所使用的协议所构建的二层网络类型) 1、MA --- 多点接入网络 BMA --- 支持广播的多点接入网络 NBMA --- 不支持广播的多点接入网络 2、P2P --- 点到点网络 以太网 --- 以太网最主要的特点是需要基于MAC地址进行物理寻址,主要是因为以太网接口所连…...
MySQL SQL Mode
SQL Mode 是 MySQL 中一个重要的系统变量,它决定了 MySQL 应遵循的 SQL 语法规则和数据验证规则。 什么是 SQL Mode SQL Mode 定义了 MySQL 应该支持的 SQL 语法以及执行数据验证的方式。通过设置不同的 SQL Mode,可以让 MySQL 在不同程度上兼容其他数据…...
Mysql备忘记录
1、简介 Mysql操作经常忘记命令,本文将持续记录Mysql一些常用操作。 2、常见问题 2.1、忘记密码 # 1、首先停止Mysql服务 systemctl stop mysqld # windows 从任务管理器里面停 # 2、更改配置文件 my.cnf (windows是 ini文件) vim /etc/my.cnf 在[mysqld]下面添…...
idea 创建 maven-scala项目
文章目录 idea 创建 maven-scala项目1、创建普通maven项目并且配置pom.xml文件2、修改项目结构1)创建scala目录并标记成【源目录】2)导入scala环境3)测试环境 idea 创建 maven-scala项目 1、创建普通maven项目并且配置pom.xml文件 maven依赖…...
ansible+docker+docker-compose快速部署4节点高可用minio集群
目录 github项目地址 示例服务器列表 安装前 修改变量文件group_vars/all.yml 修改ansible主机清单 修改setup.sh安装脚本 用法演示 安装后验证 github项目地址 https://github.com/sulibao/ansible_minio_cluster.git 示例服务器列表 安装前 修改变量文件group_var…...
使用libcurl编写爬虫程序指南
用户想知道用Curl库编写的爬虫程序是什么样的。首先,我需要明确Curl本身是一个命令行工具和库,用于传输数据,支持多种协议。而用户提到的“Curl库”可能指的是libcurl,这是一个客户端URL传输库,可以用在C、C等编程语言…...
