1. 背景知识梳理SpringMVC和Feign客户端常用注解后本文对两类注解做个对比。Spring MVC中常用注解Feign客户端常用注解理解两者定位服务端 vs 客户端是掌握注解使用的关键Spring MVC注解用于服务端描述如何解析一个HTTP请求Feign客户端注解用于客户端描述如何构造一个HTTP请求包括URL、参数、头、体等2.功能定位对比特性Spring MVC 注解Feign客户端 注解定位方向服务端接收请求客户端发送请求主要功能处理传入的 HTTP 请求路由请求、解析请求参数、处理请求体、渲染响应等。构建对外的 HTTP 请求;将 Java 接口转化为 HTTP 请求发送到远程服务端。运行位置服务提供方服务消费方典型场景暴露 REST API调用其他服务的 REST API3.核心注解对比3.1 请求映射功能Spring MVC注解Feign客户端注解类级别映射RestControllerRequestMappingFeignClient方法级别映射GetMapping/PostMapping等GetMapping/PostMapping等绑定路径变量PathVariablePathVariable必须显式命名3.2 参数处理参数类型Spring MVC(获取)Feign客户端(设置)绑定查询参数自动绑定 POJO 或RequestParamRequestParam或SpringQueryMap绑定请求体RequestBodyRequestBody绑定请求头RequestHeader获取请求头RequestHeader在客户端设置请求头发送给服务端表单数据ModelAttribute需自定义编码器文件上传RequestPartRequestPart需配置编码器3.3 特殊功能功能Spring MVCFeign客户端声明/FeignClient(Feign特有声明一个Feign客户端对象转查询参数自动绑定 POJOSpringQueryMap(Feign特有用于GET请求传递对象参数)错误处理ExceptionHandlerErrorDecoder实现熔断降级无原生支持需整合fallback/fallbackFactory(Feign特有请求拦截HandlerInterceptorRequestInterceptor配置方式ControllerAdviceEnableFeignClients4. 关键差异演示4.1. URL路径差异//Spring MVC: RestController RequestMapping(/users) public class UserController { GetMapping(/{id}) public User getUser(PathVariable Long id) { ... } } //Feign接口中必须指定完整路径包括类上的路径因为Feign不支持类级别的路径继承 FeignClient(name user-service) public interface UserClient { GetMapping(/users/{id}) // 这里必须写完整路径包括类上没有公共前缀 User getUser(PathVariable(id) Long id); }4.2. 参数处理差异//Spring MVC 注解用于获取参数(如使用RequestHeader获取请求头) PostMapping(/users) public User createUser(RequestBody User user,RequestHeader(X-Token) String token) {...} // Feign注解用于设置参数(如使用RequestHeader设置请求头) FeignClient(nameuser-service) public interface UserClient { PostMapping(/users) User createUser(RequestBody User user,RequestHeader(X-Token) String token); }4.3. 路径变量处理差异// Spring MVC支持隐式绑定 GetMapping(/orders/{orderId}/items/{itemId}) public Item getItem(PathVariable Long orderId, PathVariable String itemId) {...} // OpenFeignPathVariable 必须显式命名 FeignClient(nameorder-service) public interface OrderClient { GetMapping(/orders/{orderId}/items/{itemId}) Item getItem(PathVariable(orderId) Long orderId, PathVariable(itemId) String itemId); }4.4. 查询参数处理差异// Spring MVC自动绑定POJO GetMapping(/search) public ListUser searchUsers(UserQuery query) { // 自动处理 ?namexxxagexxx 到query的映射 } // OpenFeign需要SpringQueryMap注解 FeignClient(nameuser-service) public interface UserClient { GetMapping(/search) ListUser searchUsers(SpringQueryMap UserQuery query); //需要使用SpringQueryMap注解构建query到 ?namexxxagexxx 的映射 }5. 二者协作演示服务A使用Spring MVC暴露API服务端// 服务A使用Spring MVC暴露API服务端 RestController RequestMapping(/products) public class ProductController { GetMapping(/{id}) public Product getProduct(PathVariable Long id) { // 返回产品信息 } GetMapping(/search) public ListProduct searchProducts(ProductQuery query) { // 返回产品列表信息 } }服务B使用OpenFeign调用服务A 客户端// 服务B使用OpenFeign调用服务A 客户端 FeignClient(name product-service, configuration FeignConfig.class) public interface ProductClient { GetMapping(/products/{id}) Product getProduct(PathVariable(id) Long id); PostMapping(/products/search) ListProduct searchProducts(SpringQueryMap ProductQuery query); } // 配置类 Configuration public class FeignConfig { // OpenFeign使用的拦截器为 RequestInterceptor Bean public RequestInterceptor authInterceptor() { return template - template.header(X-Auth, token123); } } // 调用示例 Service public class OrderService { private final ProductClient productClient; public Product getProductForOrder(Long productId) { return productClient.getProduct(productId); } }6.相关阅读Spring MVC中常用注解_笔记Spring Cloud OpenFeign 常用注解_笔记Spring MVC拦截器HandlerInterceptor介绍-笔记OpenFeign拦截器feign.RequestInterceptor 简介-笔记