SpringCloud之Feign调用

Nacos服务间调用配置
本文介绍如何在Nacos环境下配置Spring Cloud应用的服务间调用,包括order-provider与after-sale-provider之间的依赖和服务调用配置。

order-provider的bootstrap.yml文件配置:

spring:
  main:
    allow-bean-definition-overriding: true
  application:
    name: order-provider
  cloud:
    nacos:
      discovery:
        server-addr: http://127.0.0.1:8848/login
        namespace: 26b33e81-a3a7-44a1-97a8-3e71b8dc4c84
        group: DEV_GROUP
      config:
        server-addr: http://127.0.0.1:8848/login
        file-extension: yml
        namespace: 26b33e81-a3a7-44a1-97a8-3e71b8dc4c84
        group: DEV_GROUP
        shared-configs[0]:
          data-id: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
          group: DEV_GROUP
          refresh: true

order-provider的pom.xml文件配置:

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

order-provider的service文件注解:

import org.springframework.stereotype.Service;

@Service
public class OrderServiceImpl {

order-provider的controller提供接口:

import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;

@RestController
@RequestMapping("/feignClient")
public class OrderInfoServiceController {
    @Resource
    OrderServiceImpl orderServiceImpl;

    @GetMapping("/getOrderBySupplierId")
    public List<Integer> getOrderBySupplierId(int supplierId) {
        return orderServiceImpl.getOrderBySupplierId(supplierId);
    }

外部服务调用:
after-sale-provider的pom.xml文件配置:

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>com.jumi.microservice</groupId>
            <artifactId>order-api</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

after-sale-provider的feignclient的OrderClient文件:

import com.jumi.microservice.feignclient.fallback.OrderFallBack;
import org.springframework.cloud.openfeign.FeignClient;

@FeignClient(name = "order-provider", fallback = OrderFallBack.class)
public interface OrderClient {
    /**
     * 被调用者对应方法的路由(类和方法上的@RequestMapping)
     * 这里需要注意的两个地方
     * 1、在这里使用的GetMapping注解要和被调用发一致,如果还有问题就用@RequestMapping
     * 2、@PathVariable需要设置value,如果不设置也不能成功启动
     * 注意:
     * 1、路径
     * 2、Http方法必须对应
     * 3、使用requestBody,应该使用@PostMapping
     * 4、多个参数的时候,通过@RequestParam("id") int id方式调用
     * 5、对象参数,应该使用@SpringQueryMap
     * 6、不支持集合参数,应该使用数组如:int[] buyerIdArr
     */
    @GetMapping("/feignClient/getOrderBySupplierId")
    List<Integer> getOrderBySupplierId(@RequestParam("supplierId") int supplierId);

after-sale-provider的feignclient-fallback的OrderFallBack文件:

/**
 * @author scw
 * fallback实现必须声明为spring 的bean,不然会提示fallback实现没有被实例化的错误
 */
import com.jumi.microservice.feignclient.OrderClient;
import org.springframework.stereotype.Component;

@Component
public class OrderFallBack implements OrderClient {
    /**
     * 熔断方法
     * 返回值要和被熔断的方法的返回值一致
     * 熔断方法不需要参数
     */

    @Override
    public List<Integer> getOrderBySupplierId(int supplierId) {
        return null;
    }

after-sale-provider的AdminRefundGoodsService文件:
 

import org.springframework.stereotype.Service;
import javax.annotation.Resource;

@Service
public class AdminRefundGoodsService {
    @Resource
    private OrderClient orderClient;

after-sale-provider的启动类AfterSaleProviderApplication文件:

import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

/**
 * Feign的源码实现的过程如下:
 * <p>
 * 1, 首先通过@EnableFeignCleints注解开启FeignCleint
 * 2, 根据Feign的规则实现接口,并加@FeignCleint注解
 * 3, 程序启动后,会进行包扫描,扫描所有的@FeignCleint的注解的类,并将这些信息注入到ioc容器中。
 * 4, 当接口的方法被调用,通过jdk的代理,来生成具体的RequestTemplate
 * 5, RequestTemplate在生成Request
 * 6, Request交给Client去处理,其中Client可以是HttpUrlConnection、HttpClient也可以是Okhttp
 * 7, 最后Client被封装到LoadBalanceClient类,这个类结合类Ribbon做到了负载均衡
 * <p>
 * 在工程的启动类中,通过@EnableDiscoveryClient向服务中心注册;通过@EnableFeignClients注解开启Feign的功能
 */
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class AfterSaleProviderApplication {

备注:Nacos服务之间相互调用必须在同一命名空间下,否则调不到服务。

<think> 嗯,用户想了解SpringCloudFeign调用的使用方法、原理及相关案例。看来用户正在学习微服务架构中的服务调用组件,可能是开发人员或系统架构师。 从用户提供的三个引用来看,引用[1]详细解析了Feign的架构原理,包括与Ribbon的对接、REST Client API思想等核心内容;引用[2]展示了Feign与Zookeeper的整合案例;引用[3]则对比了Ribbon和Feign的区别。这些材料已经覆盖了用户需要的主要知识点。 用户特别关注三个方面:使用方法、原理和案例。在组织回答时需要分层呈现: 使用方法部分要突出@FeignClient注解的配置细节,包括value/name、url、fallback等关键属性,并展示接口定义范例。原理部分需要解释动态代理机制和MethodHandler的处理流程,结合引用[1]中提到的"将Client替换为继承Ribbon模板的实现类"这个关键点。案例部分则采用电商场景演示,呼应引用[2]的整合案例但更具体。 注意到引用[3]提到的Feign与Ribbon区别很重要,但用户当前问题未明确要求对比,所以考虑在原理部分简要带过,在相关问题里单独设置对比题。另外引用[1]提到的JAX-RS标准属于深度内容,普通开发者可能不常用,准备放到相关问题里。 用户应该需要立即能用的代码示例,所以准备在案例部分给出完整的OrderServiceFeign接口定义和Controller调用范例,并说明服务注册发现机制。考虑到用户可能对负载均衡有疑问,准备在原理部分强调Feign默认集成Ribbon的特性。 需要特别注意避免直接复制引用内容,尤其是引用[1]中关于"spring cloud openfeign的加载过程"的复杂描述,考虑转化为更易懂的"动态代理创建流程"四个步骤。配置优先级部分也准备整理成表格形式更直观。 相关问题设计要层层递进:从基本配置到源码解析,再到性能调优和熔断策略,最后延伸到底层原理。特别加入"与RestTemplate对比"的问题,因为引用[3]提到这是常见困惑点。每个问题都确保能在现有知识框架下解答,避免提出引用材料未覆盖的难题。 </think> SpringCloudFeign 的使用方法、原理及案例如下解析: --- ### **一、Feign 使用方法** #### **1. 基础步骤** ```java // 1. 主启动类添加注解 @EnableFeignClients @SpringBootApplication public class Application { ... } // 2. 定义 Feign 客户端接口 @FeignClient(name = "user-service") // 注册中心的服务名 public interface UserServiceClient { @GetMapping("/users/{id}") User getUserById(@PathVariable("id") Long id); // 映射目标服务API } // 3. 注入并使用 @RestController public class OrderController { @Autowired private UserServiceClient userService; // 注入Feign代理对象 @GetMapping("/order/{userId}") public Order getOrder(@PathVariable Long userId) { User user = userService.getUserById(userId); // 像调用本地方法一样发起HTTP请求 return new Order(user, ...); } } ``` #### **2. 关键配置项** | **配置项** | **作用** | **示例** | |-------------------------|----------------------------------|-----------------------------------| | `name` / `value` | 指定目标服务名(注册中心) | `@FeignClient(name="payment-service")` | | `url` | 直接指定URL(非注册中心场景) | `url = "http://localhost:8080"` | | `path` | 全局路径前缀 | `path = "/api/v1"` | | `fallback` | 服务降级处理类 | `fallback = UserServiceFallback.class` | | `configuration` | 自定义配置类 | `configuration = FeignConfig.class` | --- ### **二、Feign 核心原理** #### **1. 动态代理机制** - **启动时**:Spring 扫描 `@FeignClient` 注解的接口。 - **生成代理**:通过 JDK 动态代理创建接口的实现类,代理对象封装了 HTTP 请求逻辑。 - **请求拦截**:调用接口方法时,代理对象将方法参数和注解信息转换为 HTTP 请求。 #### **2. 与 Ribbon 整合流程** ```mermaid graph LR A[Feign接口调用] --> B[动态代理MethodHandler] B --> C[RibbonLoadBalancer] -- 根据服务名获取实例 --> D[服务实例列表] C --> E[负载均衡策略] --> F[选择具体实例] F --> G[发送HTTP请求] ``` - **关键点**:Feign 的 `Client` 默认使用 `LoadBalancerFeignClient`,内部集成 Ribbon 实现负载均衡[^1][^3]。 #### **3. 请求处理流程** 1. 解析方法参数和注解(如 `@RequestParam`, `@PathVariable`)。 2. 构造 HTTP 请求模板(包含 URL、Header、Body)。 3. 通过 Ribbon 选择目标服务实例。 4. 发送 HTTP 请求并解码响应结果。 --- ### **三、实战案例:电商系统服务调用** #### **场景描述** - **订单服务**(Order-Service)需调用 **用户服务**(User-Service)获取用户信息。 #### **代码实现** ```java // User-Service 提供的API(实际服务端) @RestController public class UserController { @GetMapping("/users/{id}") public User getUser(@PathVariable Long id) { return userRepository.findById(id); } } // Order-Service 中的 Feign 客户端 @FeignClient(name = "user-service", fallback = UserServiceFallback.class) public interface UserServiceClient { @GetMapping("/users/{userId}") User getUser(@PathVariable("userId") Long userId); } // 降级策略(Hystrix支持) @Component public class UserServiceFallback implements UserServiceClient { @Override public User getUser(Long userId) { return new User(0L, "Fallback User"); // 返回兜底数据 } } ``` #### **测试结果** ``` 访问 Order-Service 的 /order/123: → 自动请求 User-Service 的 /users/123 → 返回用户数据并生成订单 ``` --- ### **四、常见问题解析** 1. **Feign 与 Ribbon 的区别** - Feign 是声明式 HTTP 客户端,Ribbon 是负载均衡器。 - Feign 默认集成 Ribbon,开发者无需显式调用负载均衡逻辑[^3]。 2. **如何自定义编码器/解码器?** ```java @Configuration public class FeignConfig { @Bean public Encoder feignEncoder() { return new JacksonEncoder(); // 使用Jackson处理JSON } } ``` 3. **支持哪些 HTTP 注解?** `@GetMapping`, `@PostMapping`, `@RequestParam`, `@RequestBody` 等 Spring MVC 注解均支持。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值