【深入浅出SpringCloud源码探究】「Netflix系列之Ribbon+Fegin」微服务化的负载均衡组件源码剖析与实战开发全流程(Fegin篇)

什么是Feign

Feign是一种具备声明式和模板化特性的高级HTTP客户端。在Spring Cloud中,Feign提供了一种简洁、直观的编码体验,使得远程服务调用就像调用本地方法一样简单。它允许开发者无需关注底层的HTTP请求细节。

Feign的设计灵感来自于Retrofit、JAXRS-2.0和WebSocket等优秀的HTTP客户端框架。它以提供更加便捷的方式来编写Java的HTTP客户端为目标,通过最小的代码量和资源开销实现与HTTP API的交互。

Maven依赖引入

在使用Feign时,可以通过在Maven项目的pom.xml文件中添加相应的依赖来引入Feign。以下是Feign的Maven依赖引入示例:

xml 复制代码
<dependencies>    
    <!-- Feign 相关依赖 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
</dependencies>

在上述示例中,通过将spring-cloud-starter-openfeign添加到dependencies节点下,您就可以引入Feign的Maven依赖。这个依赖是Spring Cloud框架中用于支持Feign的模块。此外,里面的 jar 包含有 spring-cloud-starter-Ribbon,是基于 Ribbon 来实现的

注意,您需要确保您的项目中已经引入了Spring Cloud相关的依赖,并将其与Feign的依赖一起添加到项目中。同时,根据您的实际需要,您可能还需要添加其他相关的依赖,例如Spring Boot等

让调用更轻松

通过使用Feign提供的特性,我们可以为每个微服务创建一个自定义的API工程,并使用Maven将此API工程引入到其他调用者项目中。这样一来,调用者在调用远程服务时就可以像调用本地方法一样简单,无需关心实际的REST接口。

使用介绍

在使用Feign时,可以通过在Spring Boot应用程序的主类上添加注解@EnableFeignClients来开启Feign注解的功能。

@EnableFeignClients注解的作用是启用Feign相关的注解处理器,以便在定义Feign客户端接口时使用Feign提供的注解。通过使用这个注解,可以方便地将Feign客户端与实际的服务提供者进行关联,并在进行远程服务调用时得到Feign的支持。

在启动类上面增加配置

为了让Spring能够正确扫描到使用@FeignClient注解的类,可以通过设置@EnableFeignClients注解的basePackages属性来指定需要扫描的包名。这样,Spring将会在指定的包及其子包中查找Feign客户端接口,并进行相应的处理。

示例代码如下:

java 复制代码
@SpringBootApplication
@EnableFeignClients((basePackages = "com.xxx.xx")
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

注意,basePackages属性可以设置为一个字符串数组,以同时指定多个包名。这样有助于更灵活地管理Feign客户端接口的扫描范围

定义Fegin调研方法请求类以及方法

Spring将会正确识别带有@FeignClient注解的接口,并将其注册为Feign客户端,使得您可以在应用程序中使用Feign进行远程服务调用。

java 复制代码
@FeignClient(value = "spring-cloud-provider")
public interface FeginClientTest {
	/**
	* @return
	*/
	@RequestMapping(value = "/api/test/{id}", method = RequestMethod.GET)
	String test(@PathVariable(value = "id") int id);
}

@PathVariable注解

使用@PathVariable注解时,必须要在注解中定义value或name属性,以指定路径变量的名称。例如,可以使用@PathVariable(value = "id")或@PathVariable(name = "id")来标识路径变量为"id"。

java 复制代码
@RequestMapping(value = "/api/user/{id}", method = RequestMethod.GET)
String test(@PathVariable(name = "id") int id);

定义调用方法

java 复制代码
@RestController
@RequestMapping(value = "/feign/user", method = RequestMethod.POST)
public class FeignUserController {
	@Autowired
	private FeginClientTest  testClient;
	@RequestMapping(value = "/{id}", method = RequestMethod.GET)
	public String get(@PathVariable(value = "id") int id) {
		return testClient.test(id);
	}
}

@RequestParam注解

没有使用@RequestParam注解的情况下

Spring MVC会根据请求类型自动进行参数绑定。如果请求类型为GET,那么参数将会通过查询字符串的形式进行传递。如果请求类型为POST,那么参数将会通过请求体的形式进行传递,并且会以JSON的格式进行转换。

当在方法参数上没有使用@RequestParam注解时,默认情况下请求类型将被视为POST(即使指定为GET),并且请求的数据将使用Jackson转换为JSON并放置在请求体中。在这种情况下,方法只能接受一个没有带注解的参数。

java 复制代码
@RequestMapping(value = "/api/user/get/{id}", method = RequestMethod.GET)
User get1(@PathVariable(value = "id") int id, String name);
@RequestMapping(value = "/api/user/get/{id}", method = RequestMethod.GET)
User get2(@PathVariable(value = "id") int id, Map<String, Object> name);

注意:当方法参数没有使用@RequestParam注解时,默认情况下请求类型被处理为POST,即使在方法上指定为GET。同时,请求数据被解析为JSON格式,并使用Jackson库进行转换,然后放置在请求体中。然而,这种默认行为只适用于单个非注解参数的情况下,其他参数需要通过注解的方式进行明确指定。

有@RequestParam 注解的情况下

在使用@RequestParam注解时,如果不指定value属性,那么参数必须以Map的形式提供。这样,参数会被转换为键值对的形式,并将其添加到请求的URL中作为查询参数。而如果指定了value属性,那么参数将按照指定的value值进行传递。

不指定value属性

如果没有指定@RequestParam注解的value属性,那么方法参数必须使用Map类型来接收参数。参数将以键值对的形式进行提供,并将其添加到请求URL中作为查询参数。

示例代码如下
java 复制代码
@GetMapping("/users")
public String getUsers(@RequestParam Map<String, String> params) {}

在上述示例中,参数params将会接收所有的查询参数,并以键值对的形式提供给方法进行处理。

指定value属性

如果指定了@RequestParam注解的value属性,那么参数将按照指定的value值进行传递。参数将以指定的value作为名称进行传递,而不会使用键值对的形式。

java 复制代码
@GetMapping("/users")
public String getUsers(@RequestParam(value = "name") String userName, @RequestParam(value = "age") int userAge) {}

在上述示例中,通过指定@RequestParam注解的value属性,明确了每个参数的名称。当请求"/users?name=John&age=25"。

Feign的默认配置

Spring Cloud Netflix 提供的默认实现类:FeignClientsConfiguration

编码器和解码器

编码器的作用是将方法参数对象序列化为请求参数,并将其放置到HTTP请求中;解码器的作用是将HTTP响应的数据反序列化为Java对象。

编码器

编码器是在客户端将方法参数对象转换为HTTP请求参数时使用的工具。它将方法参数对象序列化为某种特定格式的数据,例如JSON或XML,并将其放置到HTTP请求中作为请求参数。这样,当客户端发起HTTP请求时,编码器将负责将方法参数对象转换为适合在请求中传递的格式,并将其发送到服务器。

解码器

解码器是在客户端接收到HTTP响应时使用的工具,它将HTTP响应体中的数据反序列化为Java对象。这个过程通常涉及将JSON、XML或其他格式的数据转换为相应的Java对象,以便在客户端的应用程序中进行处理和使用。解码器的主要目标是将HTTP响应数据转换为可操作的Java对象,以便于进一步处理和分析。

自定义配置

java 复制代码
@Configuration
public class RcFeignConfiguration {}

配置FeignClient的指定配置信息

java 复制代码
@FeignClient(value = "test-app", configuration = RcFeignConfiguration.class)

日志配置

日志配置默认情况下不会打印任何日志信息。

properties 复制代码
logging.level.com.xxx.xxx.xxx.TestServer=debug

若需启用Feign的详细日志,需在配置类中添加以下代码:

java 复制代码
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 feign.Logger.Level.FULL;
    }
}

上述配置中,将Feign客户端的日志级别设置为FULL,以便在日志中显示详细的请求和响应信息。这对于调试和排查问题时非常有帮助。## 支持压缩

开启压缩

ini 复制代码
feign.compression.request.enabled=true
feign.compression.response.enabled=true
  • feign.compression.request.enabled=true: 这个设置表明Feign客户端启用了请求压缩功能。当发送请求时,Feign会对请求进行压缩以减小数据的大小。
  • feign.compression.response.enabled=true: 这个设置表明Feign客户端启用了响应压缩功能。当接收到来自服务端的响应时,Feign会对响应数据进行压缩,以减小网络传输的数据量。

更多配置

  • feign.compression.request.mime-types: 这个配置指定了需要进行请求压缩的MIME类型。只有当请求的MIME类型与此配置匹配时,Feign才会对请求进行压缩。在这个示例中,指定了text/xml、application/xml和application/json这三种MIME类型会被压缩。
  • feign.compression.request.min-request-size: 这个配置指定了请求数据的最小大小。如果请求数据的大小小于该值,Feign将不会对其进行压缩。在这个示例中,设置最小请求大小为2048字节,即2KB,意味着只有请求数据大于等于2KB时,才会进行压缩。
ini 复制代码
feign.compression.request.mime-types=text/xml,application/xml,application/json
feign.compression.request.min-request-size=2048

通过这些配置,可以有效减小请求和响应的数据大小,提升网络传输的效率,减少网络带宽的占用,同时服务端也需要支持压缩功能,并且按照相应的设置进行配置,以便正确地解压缩请求和压缩响应。

相关推荐
喵叔哟41 分钟前
【.NET 8 实战--孢子记账--从单体到微服务】--简易权限--访问权限中间件
微服务·中间件·.net
man20171 小时前
【2024最新】基于springboot+vue的闲一品交易平台lw+ppt
vue.js·spring boot·后端
hlsd#1 小时前
关于 SpringBoot 时间处理的总结
java·spring boot·后端
路在脚下@1 小时前
Spring Boot 的核心原理和工作机制
java·spring boot·后端
幸运小圣2 小时前
Vue3 -- 项目配置之stylelint【企业级项目配置保姆级教程3】
开发语言·后端·rust
菜菜-plus2 小时前
分布式,微服务,SpringCloudAlibaba,nacos,gateway,openFeign
java·分布式·微服务·nacos·gateway·springcloud·openfeign
前端SkyRain3 小时前
后端Node学习项目-用户管理-增删改查
后端·学习·node.js
提笔惊蚂蚁3 小时前
结构化(经典)软件开发方法: 需求分析阶段+设计阶段
后端·学习·需求分析
老猿讲编程3 小时前
Rust编写的贪吃蛇小游戏源代码解读
开发语言·后端·rust
黄小耶@3 小时前
python如何使用Rabbitmq
分布式·后端·python·rabbitmq