Feign是一种具备声明式和模板化特性的高级HTTP客户端。在Spring Cloud中,Feign提供了一种简洁、直观的编码体验,使得远程服务调用就像调用本地方法一样简单。它允许开发者无需关注底层的HTTP请求细节。
Feign的设计灵感来自于Retrofit、JAXRS-2.0和WebSocket等优秀的HTTP客户端框架。它以提供更加便捷的方式来编写Java的HTTP客户端为目标,通过最小的代码量和资源开销实现与HTTP API的交互。
在使用Feign时,可以通过在Maven项目的pom.xml文件中添加相应的依赖来引入Feign。以下是Feign的Maven依赖引入示例:
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-openfeignartifactId>
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客户端接口,并进行相应的处理。
示例代码如下:
@SpringBootApplication
@EnableFeignClients((basePackages = "com.xxx.xx")
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
注意,basePackages属性可以设置为一个字符串数组,以同时指定多个包名。这样有助于更灵活地管理Feign客户端接口的扫描范围。
Spring将会正确识别带有@FeignClient注解的接口,并将其注册为Feign客户端,使得您可以在应用程序中使用Feign进行远程服务调用。
@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注解时,必须要在注解中定义value或name属性,以指定路径变量的名称。例如,可以使用@PathVariable(value = “id”)或@PathVariable(name = “id”)来标识路径变量为"id"。
@RequestMapping(value = "/api/user/{id}", method = RequestMethod.GET)
String test(@PathVariable(name = "id") int id);
@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);
}
}
Spring MVC会根据请求类型自动进行参数绑定。如果请求类型为GET,那么参数将会通过查询字符串的形式进行传递。如果请求类型为POST,那么参数将会通过请求体的形式进行传递,并且会以JSON的格式进行转换。
当在方法参数上没有使用@RequestParam注解时,默认情况下请求类型将被视为POST(即使指定为GET),并且请求的数据将使用Jackson转换为JSON并放置在请求体中。在这种情况下,方法只能接受一个没有带注解的参数。
@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注解时,如果不指定value属性,那么参数必须以Map的形式提供。这样,参数会被转换为键值对的形式,并将其添加到请求的URL中作为查询参数。而如果指定了value属性,那么参数将按照指定的value值进行传递。
如果没有指定@RequestParam注解的value属性,那么方法参数必须使用Map类型来接收参数。参数将以键值对的形式进行提供,并将其添加到请求URL中作为查询参数。
@GetMapping("/users")
public String getUsers(@RequestParam Map<String, String> params) {}
在上述示例中,参数params将会接收所有的查询参数,并以键值对的形式提供给方法进行处理。
如果指定了@RequestParam注解的value属性,那么参数将按照指定的value值进行传递。参数将以指定的value作为名称进行传递,而不会使用键值对的形式。
@GetMapping("/users")
public String getUsers(@RequestParam(value = "name") String userName, @RequestParam(value = "age") int userAge) {}
在上述示例中,通过指定@RequestParam注解的value属性,明确了每个参数的名称。当请求"/users?name=John&age=25"。
Spring Cloud Netflix 提供的默认实现类:FeignClientsConfiguration
编码器的作用是将方法参数对象序列化为请求参数,并将其放置到HTTP请求中;解码器的作用是将HTTP响应的数据反序列化为Java对象。
编码器是在客户端将方法参数对象转换为HTTP请求参数时使用的工具。它将方法参数对象序列化为某种特定格式的数据,例如JSON或XML,并将其放置到HTTP请求中作为请求参数。这样,当客户端发起HTTP请求时,编码器将负责将方法参数对象转换为适合在请求中传递的格式,并将其发送到服务器。
解码器是在客户端接收到HTTP响应时使用的工具,它将HTTP响应体中的数据反序列化为Java对象。这个过程通常涉及将JSON、XML或其他格式的数据转换为相应的Java对象,以便在客户端的应用程序中进行处理和使用。解码器的主要目标是将HTTP响应数据转换为可操作的Java对象,以便于进一步处理和分析。
@Configuration
public class RcFeignConfiguration {}
@FeignClient(value = "test-app", configuration = RcFeignConfiguration.class)
日志配置默认情况下不会打印任何日志信息。
logging.level.com.xxx.xxx.xxx.TestServer=debug
若需启用Feign的详细日志,需在配置类中添加以下代码:
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,以便在日志中显示详细的请求和响应信息。这对于调试和排查问题时非常有帮助。## 支持压缩
feign.compression.request.enabled=true
feign.compression.response.enabled=true
feign.compression.request.mime-types=text/xml,application/xml,application/json
feign.compression.request.min-request-size=2048
通过这些配置,可以有效减小请求和响应的数据大小,提升网络传输的效率,减少网络带宽的占用,同时服务端也需要支持压缩功能,并且按照相应的设置进行配置,以便正确地解压缩请求和压缩响应。