Spring cloud 中使用 OpenFeign:让 http 调用更优雅

注意:本文演示所使用的 Spring Cloud、Spring Cloud Alibaba 的版本分为为 2023.0.02023.0.1.0。不兼容的版本可能会导致配置不生效等问题。

1、什么是 OpenFeign

Feign 是一个声明式的 Web service 客户端。

它使编写 Web service 客户端更加容易。只需使用 Feign 创建一个Java 接口并对其进行注释就能发起远程 Http 调用。它支持可插拔的注解,包括 Feign 注解和 JAX-RS 注解。Feign 还支持可插拔式编码器和解码器来对请求体和响应体进行编解码。SpringCloud OpenFeign 增加了对 SpringMVC 注解的支持(例如 @GetMapping、@PostMapping等),并支持使用与 SpringWeb 中默认使用的 HttpMessageConverters 相同的 HttpMessageConverters。Spring Cloud OpenFeign 能配合 Nacos(或Eureka) 、Spring Cloud CircuitBreaker 以及 Spring Cloud LoadBalancer,达到服务负载均衡的机制。

2、如何引入 Spring cloud OpenFeign

引入 spring-cloud-starter-openfeignspring-cloud-starter-loadbalancer 依赖。

spring-cloud-starter-loadbalancer 依赖用于提供复杂均衡能力。

xml 复制代码
<dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-openfeign</artifactId>
 </dependency>
 <dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-loadbalancer</artifactId>
 </dependency>

3、启用 OpenFeign

在 Spring Boot 的主启动类上加上 @EnableFeignClients 注解,使 OpenFeign 生效。

java 复制代码
@SpringBootApplication
@EnableFeignClients
public class Application {
	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}
}

3.1 @EnableFeignClients 注解详解:

java 复制代码
package org.springframework.cloud.openfeign;
import org.springframework.context.annotation.Import;
/**
 * 扫描 Feign 客户端接口(被 @FeignClient注解的 Java 接口)
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(FeignClientsRegistrar.class)
public @interface EnableFeignClients {

	/**
	 * basePackages 属性的别名。
	 */
	String[] value() default {};

	/**
	 * 扫描的基础包。
	 * 如果 feign 客户端接口不在Spring Boot 所在的启动类的包(或子包)中
	 * 则需要配置 feign 客户端接口所在的基础包。
	 */
	String[] basePackages() default {};

	/**
	 * 类型安全替代 basePackages () ,也是用于指定要扫描带 @FeignClient 注释组件的包。
	 * 将扫描该类所在包及其子包下的 Feign 客户端。
	 * 可以在需要扫描的每个包中创建一个特殊的非操作标记类或接口,
	 * 该类或接口除了被此属性引用之外没有其他用途。
	 * 
	 */
	Class<?>[] basePackageClasses() default {};

	/**
	 * 指定全局 Feign 客户端配置类(@Configuration的Spring 配置类)。
	 * 能够覆盖默认配置,例如 Decoder 和 Encoder 以及 Contract。
	 * 默认配置类为 FeignClientsConfiguration。
	 */
	Class<?>[] defaultConfiguration() default {};

	/**
	 * 带有@FeignClient注释的类列表。如果不为空,则禁用类路径扫描。
	 */
	Class<?>[] clients() default {};
}

4、使用 OpenFeign 客户端

4.1 一个例子

java 复制代码
@FeignClient("stores")
public interface StoreClient {
	@RequestMapping(method = RequestMethod.GET, value = "/stores")
	List<Store> getStores();

	@GetMapping("/stores")
	Page<Store> getStores(Pageable pageable);

	@PostMapping(value = "/stores/{storeId}", consumes = "application/json",
				params = "mode=upsert")
	Store update(@PathVariable("storeId") Long storeId, Store store);

	@DeleteMapping("/stores/{storeId:\\d+}")
	void delete(@PathVariable Long storeId);
}

创建一个接口并使用 @FeignClient 标注使其能够被扫描到。

4.2 @FeignClient 注解详解

@FeignClient 是 Spring Cloud OpenFeign 中的一个核心注解,用于声明一个接口为 Feign 客户端,使得开发者可以通过简单的接口调用来实现微服务之间的 HTTP 请求。通过使用 @FeignClient,Spring Cloud 可以帮助开发者轻松地将 HTTP 客户端的调用封装成服务调用的形式,从而简化了服务之间的通信。

java 复制代码
package org.springframework.cloud.openfeign;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.core.annotation.AliasFor;

/**
 * Annotation for interfaces declaring that a REST client with that interface should be
 * created (e.g. for autowiring into another component). If SC LoadBalancer is available
 * it will be used to load balance the backend requests, and the load balancer can be
 * configured using the same name (i.e. value) as the feign client.
 *
 * @author Spencer Gibb
 * @author Venil Noronha
 * @author Olga Maciaszek-Sharma
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface FeignClient {
	@AliasFor("name")
	String value() default "";
	String contextId() default "";
	@AliasFor("value")
	String name() default "";
	String[] qualifiers() default {};
	String url() default "";
	boolean dismiss404() default false;
	Class<?>[] configuration() default {};
	Class<?> fallback() default void.class;
	Class<?> fallbackFactory() default void.class;
	String path() default "";
	boolean primary() default true;
}

@FeignClient 注解包含多个属性,用于配置 Feign 客户端的行为:

  • value: 下面 name 属性的别名,作用同 name属性。
  • name:指定 Feign 客户端的名称,如果配置了服务发现(如 Eureka,Nacos等),Spring Cloud 会通过这个名字来查找服务的实例。
  • url:直接指定服务的基础 URL。如果指定了这个属性,Feign 客户端将不会通过服务发现来解析服务地址。
  • configuration:指定 Feign 客户端的配置类,这个类可以定义一些自定义的 Feign 配置,如日志级别、编码器、解码器等。
  • fallback:指定一个类,用于定义服务调用失败时的回退逻辑。这个类需要实现被 @FeignClient 注解的接口。
  • fallbackFactory:与 fallback 类似,但提供了更灵活的回退机制,允许在回退方法中访问抛出的异常。
  • path:定义全局的路径前缀,所有通过该 Feign 客户端发起的请求都会自动加上这个前缀。
  • decode404:当服务返回 404 时,是否应该解码响应体。默认为 false。
  • primary:标记该 Feign 客户端是否为主要的,当有多个相同名称的 Feign 客户端时,可以使用这个属性来指定。

5、开启 OpenFeign 请求响应日志

5.1 配置 application.properties

properties 复制代码
logging.level.com.github.cloudgyb.springcloud.testservice=debug

上边的配置开启了 com.github.cloudgyb.springcloud.testservice 包的 debug 级别日志。

5.2 配置 OpenFeign 日志级别

通过下面的配置类来开启。

java 复制代码
package com.github.cloudgyb.springcloud.testservice;

import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FeignConfig {
    @Bean
    public Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
}

然后重启项目,将会看到下面的日志输出,这对于调试很有帮助,但在生产环环境不建议打印这些日志。

6、使用 OkHttp 作为底层 http 客户端

OpenFeign 底层默认使用 JDK 自带的 HttpURLConnection 执行 Http 请求,它不支持线程池所以效率不高。OKHttp 支持线程池,是一个不错的选择。

6.1 引入依赖 OKHttp

xml 复制代码
<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
</dependency>
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-okhttp</artifactId>
</dependency>

6.2 配置 application.properties

properties 复制代码
spring.cloud.openfeign.okhttp.enabled=true

6.3 验证 OKHttp 是否生效

重启项目,debug 代码,发现 OKHTTP 已经生效。

6.4 其他HTTP客户端选择

OpenFeign 除了支持 OKHTTP 作为底层的 Http 通信客户端,还支持 Apache HttpComponents Client 5、JDK 11 HttpClient。

下面是一个使用 Apache HttpComponents Client 5的例子:

  1. 引入依赖
xml 复制代码
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-hc5</artifactId>
</dependency>
  1. 配置 application.proerties
properties 复制代码
spring.cloud.openfeign.httpclient.hc5.enabled=true
  1. 重启项目即可。
相关推荐
星河梦瑾26 分钟前
SpringBoot相关漏洞学习资料
java·经验分享·spring boot·安全
黄名富29 分钟前
Redis 附加功能(二)— 自动过期、流水线与事务及Lua脚本
java·数据库·redis·lua
love静思冥想31 分钟前
JMeter 使用详解
java·jmeter
言、雲33 分钟前
从tryLock()源码来出发,解析Redisson的重试机制和看门狗机制
java·开发语言·数据库
TT哇40 分钟前
【数据结构练习题】链表与LinkedList
java·数据结构·链表
Yvemil71 小时前
《开启微服务之旅:Spring Boot 从入门到实践》(三)
java
Anna。。1 小时前
Java入门2-idea 第五章:IO流(java.io包中)
java·开发语言·intellij-idea
.生产的驴2 小时前
SpringBoot 对接第三方登录 手机号登录 手机号验证 微信小程序登录 结合Redis SaToken
java·spring boot·redis·后端·缓存·微信小程序·maven
爱上语文2 小时前
宠物管理系统:Dao层
java·开发语言·宠物
王ASC2 小时前
SpringMVC的URL组成,以及URI中对/斜杠的处理,解决IllegalStateException: Ambiguous mapping
java·mvc·springboot·web