spring cloud 之 feign

spring cloud的feign是用来发送http,https请求的,他的特点:

1.可插拔的注解支持,包括Feign注解和JAX-RS注解。

2.支持可插拔的HTTP编码器和解码器。

3.支持Hystrix和它的Fallback。

4.支持Ribbon的负载均衡。

5.支持HTTP请求和响应的压缩。

Feign是一个声明式的Web Service客户端,它的目的就是让Web Service调用更加简单。它整合了Ribbon和Hystrix,从而不需要开发者针对Feign对其进行整合。Feign还提供了HTTP请求的模板,通过编写简单的接口和注解,就可以定义好HTTP请求的参数、格式、地址等信息。Feign会完全代理HTTP的请求,在使用过程中我们只需要依赖注入Bean,然后调用对应的方法传递参数即可。

以下代码是一个完整的maven项目,demo版:演示了如何利用feign向github发送get请求。

复制代码
package mr.li.hello;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;


@SpringBootApplication
@EnableFeignClients
public class HelloWorld {
    
    public static void main(String[] args) {
        SpringApplication.run(HelloWorld.class, args);
    }
}
复制代码
复制代码
package mr.li.hello.config;

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

import feign.Logger;

@Configuration
public class FeignConfigDemo {

    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
}
复制代码
复制代码
package mr.li.hello.demo;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import mr.li.hello.config.FeignConfigDemo;

@FeignClient(name = "github-client", url = "https://api.github.com", configuration = FeignConfigDemo.class)
public interface FeignDemo {

    @RequestMapping(value = "/search/repositories", method = RequestMethod.GET)
    String searchRepo(@RequestParam(name = "q") String param);
}
复制代码
复制代码
package mr.li.hello.web;

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;

import mr.li.hello.demo.FeignDemo;

@RestController
public class FeignDemoController {

    @Autowired
    private FeignDemo feignDemo;
    
    @GetMapping(value = "/search/github")
    public String search(@RequestParam("str") String param) {
        String str1 = feignDemo.searchRepo(param);
        return str1;
    }
}
复制代码
复制代码
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>cn.mr.li</groupId>
    <artifactId>hello-world</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <!-- 父依赖为spring2.1.6 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
    </parent>
     <properties>
        <spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- Spring Cloud OpenFeign的Starter的依赖 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>
复制代码
复制代码
server:
  port: 8888
  
spring:
  application:
    name: hello-world
logging:
     level:
       mr.li.hello.demo.FeignDemo: debug    
          
            
复制代码

 ❑ 在开发微服务应用时,我们会在主程序入口添加@EnableFeignClients注解开启对Feign Client扫描加载处理。根据Feign Client的开发规范,定义接口并加@FeignClients注解。

❑ 当程序启动时,会进行包扫描,扫描所有@ FeignClients的注解的类,并将这些信息注入Spring IOC容器中。当定义的Feign接口中的方法被调用时,通过JDK的代理的方式,来生成具体的RequestTemplate。当生成代理时,Feign会为每个接口方法创建一个RequetTemplate对象,该对象封装了HTTP请求需要的全部信息,如请求参数名、请求方法等信息都是在这个过程中确定的。

❑ 然后由RequestTemplate生成Request,然后把Request交给Client去处理,这里指的Client可以是JDK原生的URLConnection、Apache的HttpClient,也可以是Okhttp。最后Client被封装到LoadBalanceClient类,这个类结合Ribbon负载均衡发起服务之间的调用。

FeignClient注解的常用属性归纳如下:

  ❑ name:指定FeignClient的名称,如果项目使用了Ribbon, name属性会作为微服务的名称,用于服务发现。

  ❑ url:url一般用于调试,可以手动指定@FeignClient调用的地址。

  ❑ decode404:当发生404错误时,如果该字段为true,会调用decoder进行解码,否则抛出FeignException。

  ❑ configuration:Feign配置类,可以自定义Feign的Encoder、Decoder、LogLevel、Contract。

  ❑ fallback:定义容错的处理类,当调用远程接口失败或超时时,会调用对应接口的容错逻辑,fallback指定的类必须实现@FeignClient标记的接口。

  ❑ fallbackFactory:工厂类,用于生成fallback类示例,通过这个属性我们可以实现每个接口通用的容错逻辑,减少重复的代码。

  ❑ path:定义当前FeignClient的统一前缀。

1.@FeignClient的配置信息可以通过application.properties或application.yml来配置,application. yml示例配置信息如下:

 2.作用于所有Feign的配置方式:这种配置就不用yml配置了,直接在指定java类中进行配置即可,若同时既配置了yml又配置了java配置,那么yml会代理java配置。

 

 

 yml配置示例:

 

 

 

java类配置示例:

 

 3.Feign文件上传:客户端代码

 

 

 

 

 4.Feign文件上传的服务端

 

 

 

 针对Feign首次请求失败的问题,可参考如下链接:https://github.com/spring-cloud/spring-cloud-netflix/issues/768

 

 

5.Feign调用传递Token:在进行认证鉴权的时候,不管是jwt,还是security,当使用Feign时就会发现外部请求到A服务的时候,A服务是可以拿到Token的,然而当服务使用Feign调用B服务时,Token就会丢失,从而认证失败。解决方法相对比较简单,需要做的就是在Feign调用的时候,向请求头里面添加需要传递的Token。我们只需要实现Feign提供的一个接口RequestInterceptor,假设我们在验证权限的时候放在请求头里面的key为oauthToken,先获取当前请求中的key为oauthToken的Token,然后放到Feign的请求Header上,示例代码如代码清单4-20所示(像这种通用的代码确定传递的key之后,建议统一到通用的二方库里使用)。

 

 

posted @   ~~mr.li~~  阅读(159)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
点击右上角即可分享
微信分享提示