Spring Cloud 是一个用于构建分布式系统的开发工具包,它提供了一系列的微服务组件,其中之一就是 Feign。Feign 是一种声明式的 Web 服务客户端,它简化了在 Spring Cloud 中进行远程调用的过程。本文将介绍如何在 Spring Cloud 中使用 Feign 进行远程调用。
一、引入Feign依赖
我们在 Spring Cloud 项目的 pom.xml 中,添加 Feign 的依赖。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
二、定义和使用Feign客户端
在远程调用的服务模块中,创建一个 Feign 客户端接口
package com.example.eurekaconsumer.demos.web;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient ("userseryice")
public interface UserClient {
@GetMapping("/user/{name}")
User findById(@PathVariable("name") String name);
}
这个接口使用了 Spring MVC 的注解,定义了远程服务的调用方式。
三、启动类开启Feign客户端
启动类添加 @EnableFeignClients 注解:
package com.example.eurekaconsumer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@EnableFeignClients
@EnableEurekaClient
@SpringBootApplication
public class EurekaConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaConsumerApplication.class, args);
}
}
四、调用FeignClient接口
在需要应用的模块中,注入 Feign 客户端接口并使用它来进行远程调用。
package com.example.eurekaconsumer.demos.web;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@Autowired
private UserClient userClient;
@RequestMapping("/showUser")
@ResponseBody
public User showUser() {
User userInfo = userClient.findByName("Damon");
return userInfo;
}
}
可以看到,使用 Feign 调用的方法非常优雅,可维护性也很强。
五、FeignClient应用实例
1、实现负载均衡
我们可以用 FeignClient 代替 RestTemplate 以实现负载均衡。
我们先看下参考原有的 RestTemplate 实现负载均衡的代码:
package com.example.eurekaconsumer.demos.web;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class UserController {
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/showUser")
@ResponseBody
public User showUser() {
String baseUrl = "http://" + "eureka-provider" + "/user";
User userInfo = restTemplate.getForObject(baseUrl, User.class);
return userInfo;
}
}
可以看到我们用 RestTemplate 实现负载均衡时,遇到没有参数传递的情况还是比较方便的,但是遇到形如 url?param1=xxx¶m2=xxx¶m3=xxx¶m4=xxx 的应用场景时就需要重构代码,非常的不方便。
于是我们使用自带负载均衡的 Feign 远程调用方法,改造后的方法如下:
package com.example.eurekaconsumer.demos.web;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@Autowired
private UserClient userClient;
@RequestMapping("/showUser")
@ResponseBody
public User showUser() {
User userInfo = userClient.findByName("Damon");
return userInfo;
}
}
以上是一个简单的 Spring Cloud 中基于 Feign 的远程调用的示例。通过使用 Feign,你可以以声明式的方式定义远程服务调用,而无需手动处理 HTTP 请求和响应。这提高了代码的可读性和维护性,使远程调用更加方便。
Feign 替换 RestTemplate 的好处:
优势 | 详细内容 |
声明式 API 定义 | 使用Feign时,你可以通过简单的注解方式声明HTTP请求,而不需要手动构建请求和处理响应。Feign的注解功能使得定义和维护API变得更加直观和容易。 |
集成了 负载均衡 | 在Spring Cloud环境中,Feign与Eureka或其他服务发现组件集成,可以自动进行负载均衡。你只需通过@FeignClient 注解指定服务名,Feign就会在调用时自动帮你选择可用的服务实例。 |
支持多种编码 器和解码器 | Feign支持多种编码器和解码器,包括Jackson 、Gson 等,这使得处理不同的数据格式变得更加灵活。 |
支持 内置断路器 | Feign内置了断路器(Circuit Breaker)的支持,例如通过Hystrix。这使得在远程调用失败或超时时,可以采取快速失败和降级的策略,提高系统的稳定性和可靠性。 |
更易扩展 | Feign的设计使得它更易于扩展和自定义。你可以通过实现RequestInterceptor 接口来添加自定义的请求拦截器,或者通过实现ErrorDecoder 接口来处理自定义的错误解码逻辑。 |
简化了 配置和使用 | Feign的默认配置较为智能,使得在大多数情况下你无需进行额外的配置就能够正常工作。相比之下,RestTemplate 通常需要手动配置。 |
2、 实现多参数调用
当使用 FeignClient 进行远程调用时,有时我们需要传递多个参数给目标服务。使用 Feign 的多参数远程调用能够使代码更加优雅,避免了手动拼接 URL 或请求参数的繁琐工作。
以下是一个关于 FeignClient 多参数远程调用的应用实例:
① 创建FeignClient接口
首先,定义一个FeignClient接口,使用 @FeignClient 注解标记目标服务的名称。在接口中定义多个参数的远程调用方法。
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(name = "test-service")
public interface TestClient {
@GetMapping("/api/test")
String getResource(@RequestParam("param1") String param1,
@RequestParam("param2") int param2,
@RequestParam("param3") boolean param3);
}
在上述例子中,getResource 方法接收多个参数,分别使用 @RequestParam 注解进行标记。
② 基于FeignClient多参数调用
注入 FeignClient 接口并使用它进行多参数的远程调用。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@Autowired
private TestClient testClient;
@GetMapping("/test")
public String test(@RequestParam("param1") String param1,
@RequestParam("param2") int param2,
@RequestParam("param3") boolean param3) {
// 调用远程服务并传递多个参数
String result = testClient.getResource(param1, param2, param3);
return "Result from test service: " + result;
}
}
在这个例子中,TestController 的 test 方法接收多个参数,然后使用注入的 TestClient 进行远程调用,并传递这些参数。
通过使用 Feign 的方式,我们可以更加优雅地进行多参数的远程调用,避免了手动拼接URL或构建复杂的请求体。Feign 会自动将参数转化为请求参数,使得代码更加清晰、简洁。这种方式也符合 Spring Cloud 中微服务架构的设计理念,提高了代码的可读性和可维护性。