SpringMVC注解与SpringCloudOpenFeign注解对比
1. 背景知识
梳理SpringMVC和SpringCloudOpenFeign常用注解后:
- Spring MVC中常用注解_笔记-CSDN博客
- Spring Cloud OpenFeign 常用注解_笔记-CSDN博客
这里对两类注解做个对比。理解两者定位(服务端 vs 客户端)是掌握注解使用的关键:
- Spring MVC注解用于服务端,描述如何解析一个HTTP请求;
- OpenFeign注解用于客户端,描述如何构造一个HTTP请求(包括URL、参数、头、体等)
2.功能定位对比
处理传入的 HTTP 请求;
路由请求、解析请求参数、处理请求体、渲染响应等。
构建对外的 HTTP 请求;
将 Java 接口转化为 HTTP 请求,发送到远程服务端。
3.核心注解对比
3.1 请求映射
@RestController
@RequestMapping
@FeignClient
@GetMapping
/@PostMapping
等@GetMapping
/@PostMapping
等@PathVariable
@PathVariable
(必须显式命名)3.2 参数处理
@RequestParam
@RequestParam
或 @SpringQueryMap
@RequestBody
@RequestBody
@RequestHeader
(获取请求头)@RequestHeader
(在客户端设置请求头发送给服务端)@ModelAttribute
@RequestPart
@RequestPart
(需配置编码器)3.3 特殊功能
@FeignClient(
Feign特有,声明一个Feign客户端)@SpringQueryMap(
Feign特有,用于GET请求传递对象参数)
@ExceptionHandler
ErrorDecoder
实现fallback
/fallbackFactory(
Feign特有)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 searchUsers(UserQuery query) { // 自动处理 ?name=xxx&age=xxx 到query的映射}// OpenFeign(需要@SpringQueryMap注解)@FeignClient(name=\"user-service\")public interface UserClient { @GetMapping(\"/search\") List 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 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 searchProducts(@SpringQueryMap ProductQuery query);}// 配置类@Configurationpublic class FeignConfig { // OpenFeign使用的拦截器为 RequestInterceptor @Bean public RequestInterceptor authInterceptor() { return template -> template.header(\"X-Auth\", \"token123\"); }}// 调用示例@Servicepublic 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 简介-笔记