SpringMVC注解与Feign客户端注解对比

1. 背景知识

梳理SpringMVC和Feign客户端常用注解后,本文对两类注解做个对比。

理解两者定位(服务端 vs 客户端)是掌握注解使用的关键:

  • Spring MVC注解用于服务端,描述如何解析一个HTTP请求;
  • Feign客户端注解用于客户端,描述如何构造一个HTTP请求(包括URL、参数、头、体等)

2.功能定位对比

特性Spring MVC 注解Feign客户端 注解
定位方向服务端(接收请求)客户端(发送请求)
主要功能

处理传入的 HTTP 请求;

路由请求、解析请求参数、处理请求体、渲染响应等。

构建对外的 HTTP 请求;

将 Java 接口转化为 HTTP 请求,发送到远程服务端。

运行位置服务提供方服务消费方
典型场景暴露 REST API调用其他服务的 REST API

3.核心注解对比

3.1 请求映射

功能Spring MVC注解Feign客户端注解
类级别映射

@RestController

@RequestMapping

@FeignClient
方法级别映射@GetMapping/@PostMapping 等@GetMapping/@PostMapping 等
绑定路径变量@PathVariable@PathVariable(必须显式命名)

3.2 参数处理

参数类型Spring MVC(获取)Feign客户端(设置)
绑定查询参数自动绑定 POJO 或 @RequestParam@RequestParam 或 @SpringQueryMap
绑定请求体@RequestBody@RequestBody
绑定请求头@RequestHeader(获取请求头)@RequestHeader(在客户端设置请求头发送给服务端)
表单数据@ModelAttribute需自定义编码器
文件上传@RequestPart@RequestPart(需配置编码器)

3.3 特殊功能

功能Spring MVCFeign客户端
声明/@FeignClient(Feign特有,声明一个Feign客户端)
对象转查询参数自动绑定 POJO@SpringQueryMap(Feign特有,用于GET请求传递对象参数)
错误处理@ExceptionHandlerErrorDecoder 实现
熔断降级无原生支持(需整合)fallback/fallbackFactory(Feign特有)
请求拦截HandlerInterceptorRequestInterceptor
配置方式@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
    @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.相关阅读

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值