1. 背景知识
梳理SpringMVC和SpringCloudOpenFeign常用注解后:
- Spring MVC中常用注解_笔记-CSDN博客
- Spring Cloud OpenFeign 常用注解_笔记-CSDN博客
这里对两类注解做个对比。理解两者定位(服务端 vs 客户端)是掌握注解使用的关键:
- Spring MVC注解用于服务端,描述如何解析一个HTTP请求;
- OpenFeign注解用于客户端,描述如何构造一个HTTP请求(包括URL、参数、头、体等)
2.功能定位对比
特性 | Spring MVC 注解 | Spring Cloud OpenFeign 注解 |
---|---|---|
定位方向 | 服务端(接收请求) | 客户端(发送请求) |
主要功能 | 处理传入的 HTTP 请求; 路由请求、解析请求参数、处理请求体、渲染响应等。 | 构建对外的 HTTP 请求; 将 Java 接口转化为 HTTP 请求,发送到远程服务端。 |
运行位置 | 服务提供方 | 服务消费方 |
典型场景 | 暴露 REST API | 调用其他服务的 REST API |
3.核心注解对比
3.1 请求映射
功能 | Spring MVC | OpenFeign |
---|---|---|
类级别映射 |
| @FeignClient |
方法级别映射 | @GetMapping /@PostMapping 等 | @GetMapping /@PostMapping 等 |
绑定路径变量 | @PathVariable | @PathVariable (必须显式命名) |
3.2 参数处理
参数类型 | Spring MVC(获取) | OpenFeign(设置) |
---|---|---|
绑定查询参数 | 自动绑定 POJO 或 @RequestParam | @RequestParam 或 @SpringQueryMap |
绑定请求体 | @RequestBody | @RequestBody |
绑定请求头 | @RequestHeader (获取请求头) | @RequestHeader (在客户端设置请求头发送给服务端) |
表单数据 | @ModelAttribute | 需自定义编码器 |
文件上传 | @RequestPart | @RequestPart (需配置编码器) |
3.3 特殊功能
功能 | Spring MVC | OpenFeign |
---|---|---|
声明 | / | @FeignClient( Feign特有,声明一个Feign客户端) |
对象转查询参数 | 自动绑定 POJO | @SpringQueryMap( Feign特有,用于GET请求传递对象参数) |
错误处理 | @ExceptionHandler | ErrorDecoder 实现 |
熔断降级 | 无原生支持(需整合) | fallback /fallbackFactory( Feign特有) |
请求拦截 | HandlerInterceptor | RequestInterceptor |
配置方式 | @ControllerAdvice | @EnableFeignClients |
4. 关键差异演示
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(name="user-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) {...}// OpenFeign(@PathVariable 必须显式命名)
@FeignClient(name="order-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 List<User> searchUsers(UserQuery query) {// 自动处理 ?name=xxx&age=xxx 到query的映射
}// OpenFeign(需要@SpringQueryMap注解)
@FeignClient(name="user-service")
public interface UserClient {@GetMapping("/search")List<User> searchUsers(@SpringQueryMap UserQuery query);//需要使用@SpringQueryMap注解构建query到 ?name=xxx&age=xxx 的映射
}
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 List<Product> 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")List<Product> searchProducts(@SpringQueryMap ProductQuery query);
}// 配置类
@Configuration
public class FeignConfig {// OpenFeign使用的拦截器为 RequestInterceptor@Beanpublic 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 简介-笔记