目录
前言
一、什么是OpenFeign?
Feign 的实现
Feign 和 OpenFeign 的区别
二、OpenFeign的优点
三、基本用法
新建子工程
配置文件
服务注册
编辑
新建Controller
引入依赖
创建接口
启动类开启Feign注解
访问测试
四、@FeignClient 标签的常用属性
1、name
2、url
3、configuration
4、fallback
5、fallbackFactory
6、path
7、decode404
8、primary
9、contextId
五、添加请求头信息
1、在方法参数上添加请求头信息
2、使用 Feign 配置类定义请求拦截器
定义请求拦截器
应用配置类
3、动态添加请求头信息
总结
前言
在微服务架构中,服务之间的通信是一个非常重要的环节。为了简化和高效地进行服务间通信,Spring Cloud 提供了 OpenFeign 这个强大的工具。本文将介绍 OpenFeign 的概念、优点、基本用法以及在实际项目中的应用。也希望通过本文,能够帮助你们在 Spring Cloud 项目中轻松地集成和使用 OpenFeign。
一、什么是OpenFeign?
OpenFeign 是一个声明式的 HTTP 客户端,用于简化微服务间的 HTTP 调用。它集成了 Ribbon 以实现负载均衡,并且与 Eureka、Consul 等服务发现组件无缝对接。通过使用 OpenFeign,开发者只需要定义接口并使用注解来配置 HTTP 请求,而无需编写大量的模板代码。
Feign 的实现
Feign 在 Ribbon + RestTemplate 基础上做了进一步封装, 它来帮助我们定义和实现依赖服务接口的定义。在 Feign 的实现下,我们只需创建一个接口并使用注解的方式来配置它(以前是在 Dao 接口上面标注 Mapper 注解,现在是一个 Service 接口上面标注 Feign 注解),即可完成对服务提供方的接口绑定,简化了使用 Spring Cloud Ribbon 时,自动封装服务调用客户端的开发量。
Feign 和 OpenFeign 的区别
依赖 | 作用 | |
Feign | org.springframework.cloud spring-cloud-starter-feign | Feign 是 Spring Cloud 组件中的一个轻量级 RESTful 的 HTTP 服务客户端。Feign 内置了 Ribbon,用来做客户端负载均衡,去调用服务注册中心的服务。Feign 的使用方式是:使用 Feign 的注解定义接口,调用这个接口就可以调用服务注册中心的服务。 |
OpenFeign | org.springframework.cloud spring-cloud-starter-openfeign | OpenFeign 是 Spring Cloud 在Feign 的基础上支持了 SpringMVC的注解如 @RequesMapping 等等。OpenFeign 的 @FeignClient 可以解析 SpringMVC 的 @RequestMapping 注解下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务。 |
二、OpenFeign的优点
声明式调用:通过注解定义 HTTP 请求,代码更简洁。
集成 Ribbon:支持客户端负载均衡。
支持服务发现:与 Eureka、Consul 等服务发现组件无缝集成。
支持熔断:与 Hystrix、Sentinel 等熔断器集成,提升系统稳定性。
可扩展:支持自定义拦截器、编码器和解码器,便于扩展和定制化。
三、基本用法
新建子工程
配置文件
server:
port: 9091
spring:
application:
name: demo-order
cloud:
nacos:
discovery:
server-addr: 192.168.1.85:8848
namespace: demo
config:
server-addr: 192.168.1.85:8848
prefix: ${spring.application.name}
file-extension: yml
namespace: demo
<dependencies>
<!-- Nacos 服务发现 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
服务注册
新建Controller
引入依赖
user模块引入OpenFeign依赖
创建接口
启动类开启Feign注解
在用户模块的启动类,加上 @EnableFeignClients 注解。
访问测试
如图所示,证明已经访问成功了。
四、@FeignClient 标签的常用属性
@FeignClient 注解是 Spring Cloud OpenFeign 中用于声明一个 Feign 客户端的核心注解。它可以用来指定服务的名称、配置类、负载均衡策略等。下面是 @FeignClient 注解的一些常用属性及其用途:
1、name
name 属性用于指定 Feign 客户端调用的服务名称。这是一个必填属性,通常是注册在服务发现(如 Nacos)中的服务名。
@FeignClient(name = "demo-user")
public interface UserClient {
// ...
}
2、url
url 属性用于指定服务的 URL,通常用于调试或服务未注册到服务发现时。url
属性会覆盖 name
属性。
@FeignClient(name = "demo-user", url = "http://localhost:8080")
public interface UserClient {
// ...
}
3、configuration
configuration 属性用于指定自定义配置类,配置类可以用来定制 Feign 客户端的行为,如请求拦截器、编码器和解码器等。
@FeignClient(name = "demo-user", configuration = FeignConfig.class)
public interface UserClient {
// ...
}
配置类示例
@Configuration
public class FeignConfig {
@Bean
public RequestInterceptor requestInterceptor() {
return template -> template.header("Custom-Header", "CustomHeaderValue");
}
}
4、fallback
fallback 属性用于指定服务降级的实现类。当 Feign 客户端调用失败时,会调用 fallback 指定的类中的方法。
@FeignClient(name = "demo-user", fallback = UserClientFallback.class)
public interface UserClient {
// ...
}
@Component
public class UserClientFallback implements UserClient {
@Override
public User getUserById(Long id) {
return new User(); // 返回一个默认的用户对象
}
}
5、fallbackFactory
fallbackFactory 属性用于指定服务降级的工厂类,该工厂类可以提供更多的上下文信息,例如异常信息。
@FeignClient(name = "demo-user", fallbackFactory = UserClientFallbackFactory.class)
public interface UserClient {
// ...
}
@Component
public class UserClientFallbackFactory implements FallbackFactory<UserClient> {
@Override
public UserClient create(Throwable cause) {
return new UserClient() {
@Override
public User getUserById(Long id) {
// 返回一个默认的用户对象,并打印异常信息
System.out.println("Fallback cause: " + cause);
return new User();
}
};
}
}
6、path
path 属性用于指定服务的统一前缀路径,在定义 Feign 接口的方法时可以省略该路径。
@FeignClient(name = "demo-user", path = "/api/users")
public interface UserClient {
@GetMapping("/{id}")
User getUserById(@PathVariable("id") Long id);
}
7、decode404
decode404属性用于指定是否将 HTTP 404 响应解码为 Feign 客户端的 fallback,默认值为 false。
@FeignClient(name = "demo-user", decode404 = true)
public interface UserClient {
// ...
}
8、primary
primary属性用于指定该 Feign 客户端是否为主要的 @Primary Bean,这对某些场景下的自动装配很有用,默认值为 true。
@FeignClient(name = "demo-user", primary = false)
public interface UserClient {
// ...
}
9、contextId
contextId 属性用于在多 Feign 客户端实例中区分不同的上下文 ID。特别适用于多个 Feign 客户端指向同一服务时的配置。
@FeignClient(name = "demo-user", contextId = "userClient1")
public interface UserClient1 {
// ...
}
@FeignClient(name = "demo-user", contextId = "userClient2")
public interface UserClient2 {
// ...
}
@FeignClient 注解通过丰富的属性配置,提供了强大的功能来满足不同场景下的微服务调用需求。通过合理使用这些属性,可以定制化 Feign 客户端的行为,提升微服务间的通信效率和容错能力。
五、添加请求头信息
1、在方法参数上添加请求头信息
示例:
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
@FeignClient(name = "demo-user")
public interface UserClient {
@GetMapping("/users/{id}")
User getUserById(@PathVariable("id") Long id, @RequestHeader("Authorization") String token);
}
在调用接口时,传递请求头参数:
@RestController
public class UserController {
@Autowired
private UserClient userClient;
@GetMapping("/users/{id}")
public User getUser(@PathVariable("id") Long id) {
String token = "xxxxxxxxxxxxxxxxxxxx";
return userClient.getUserById(id, token);
}
}
2、使用 Feign 配置类定义请求拦截器
如果需要在所有请求中添加相同的请求头,可以通过定义一个 Feign 请求拦截器来实现。
定义请求拦截器
创建一个 Feign 配置类,并定义请求拦截器:
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FeignConfig {
@Bean
public RequestInterceptor requestInterceptor() {
return new RequestInterceptor() {
@Override
public void apply(RequestTemplate template) {
template.header("Authorization", "xxxxxxxxxxxxxxxxx");
}
};
}
}
应用配置类
在 Feign 客户端接口上指定配置类:
@FeignClient(name = "demo-user", configuration = FeignConfig.class)
public interface UserClient {
@GetMapping("/users/{id}")
User getUserById(@PathVariable("id") Long id);
}
这样,每次调用 UserClient 的方法时,请求头中都会自动包含 Authorization:xxxxxxxxxxxxx
3、动态添加请求头信息
如果需要根据某些条件动态添加请求头信息,可以在拦截器中编写逻辑:
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
@Configuration
public class FeignConfig {
@Bean
public RequestInterceptor requestInterceptor() {
return new RequestInterceptor() {
@Override
public void apply(RequestTemplate template) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (attributes != null) {
HttpServletRequest request = attributes.getRequest();
String token = request.getHeader("Authorization");
if (token != null) {
template.header("Authorization", token);
}
}
}
};
}
}
这种方式可以将来自原始 HTTP 请求的请求头信息传递给 Feign 客户端的请求。
总结
本文介绍了 OpenFeign 的基本概念、优点以及在 Spring Boot 项目中的基本用法。OpenFeign 作为声明式的 HTTP 客户端,大大简化了微服务间的通信,使代码更加简洁和易于维护。在实际项目中,OpenFeign 还提供了许多高级特性,如超时设置、自定义拦截器和熔断器集成等,可以根据具体需求进行灵活配置。