【SpringCloud系列】@FeignClient微服务轻舞者

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。

  • 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老
  • 导航
    • 檀越剑指大厂系列:全面总结 java 核心技术点,如集合,jvm,并发编程 redis,kafka,Spring,微服务,Netty 等
    • 常用开发工具系列:罗列常用的开发工具,如 IDEA,Mac,Alfred,electerm,Git,typora,apifox 等
    • 数据库系列:详细总结了常用数据库 mysql 技术点,以及工作中遇到的 mysql 问题等
    • 懒人运维系列:总结好用的命令,解放双手不香吗?能用一个命令完成绝不用两个操作
    • 数据结构与算法系列:总结数据结构和算法,不同类型针对性训练,提升编程思维,剑指大厂

非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。💝💝💝 ✨✨ 欢迎订阅本专栏 ✨✨

博客目录

一.简单介绍

1.什么是 FeignClient?

@FeignClient 是 Spring Cloud 中的一个注解,用于创建基于接口的声明式服务客户端。它是在微服务架构中用于进行服务之间通信的一种方式。通过 @FeignClient,您可以定义一个接口,该接口包含要调用的远程服务的方法,而 Feign 将自动处理底层的 HTTP 请求和负载均衡。

2.FeignClient 优点?

@FeignClient 在微服务架构中的使用具有多个优点和特点,这使得它成为一个方便且强大的工具:

  1. 声明式 REST 客户端: @FeignClient 允许您使用声明式的方式定义服务间的 HTTP 调用。通过简单地定义一个接口,而不需要手动编写 HTTP 请求,您可以将服务调用抽象为接口的方法。

  2. 集成了 Ribbon 负载均衡: @FeignClient 集成了 Netflix 的 Ribbon 负载均衡器,自动处理了服务的负载均衡。这使得微服务之间的调用更加健壮和可靠。

  3. 支持服务发现: 默认情况下,@FeignClient 集成了 Eureka 服务发现,允许您使用服务的逻辑名称而不是直接的 IP 地址进行服务调用。这增加了服务调用的灵活性。

  4. 支持多种注解: 除了 @FeignClient,Feign 还支持一系列其他的注解,如 @RequestMapping@RequestParam 等,使得您可以在接口上使用这些注解定义 HTTP 请求的各个方面。

  5. 集成了 Hystrix 进行服务降级: @FeignClient 支持集成 Hystrix,可以通过设置 fallbackfallbackFactory 属性,定义服务降级的逻辑。当远程服务不可用时,可以提供备选方案,防止整个系统崩溃。

  6. 支持自定义配置: 通过 configuration 属性,您可以自定义 Feign 客户端的配置,包括连接超时、读取超时、重试策略等。这使得您可以根据实际需求进行灵活的配置。

  7. 集成了 Spring Cloud Contract: Spring Cloud Contract 可以通过测试契约来确保服务之间的契约一致性。@FeignClient 集成了 Spring Cloud Contract,使得可以通过契约来测试和验证服务之间的通信。

  8. 简化代码: 使用 @FeignClient 可以大大简化微服务之间的通信代码。由于 Feign 处理了底层的 HTTP 请求和负载均衡,开发者只需要关注业务逻辑,使得代码更加清晰简洁。

@FeignClient 是一个强大的工具,它简化了微服务之间的通信,提高了开发效率,同时集成了一系列的微服务治理功能,使得服务调用更加可靠和灵活。

二.基本使用

1.引入依赖

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

2.获取 token 接口

使用 FeignClient 封装获取 token 的接口

java 复制代码
@FeignClient(
        url = "${xxx.open-api.host}",
        value = "xxx-open-api",
        contextId = "oauth",
        path = "/cas/oauth"
)
public interface AuthOpenApi {

    @Log("xxx-open-api,获取token")
    @GetMapping("/token")
    TokenResponse getToken(@SpringQueryMap GetTokenRequest request);
}

3.RequestParam

请求参数类

java 复制代码
@Data
public class GetTokenRequest {
    private String scope = "xxx";
    private String grant_type = "xxx";
    private String client_id;
    private String client_secret;

    public GetTokenRequest() {
        this.client_id = SpringContextHolder.getBean(OpenApiProperties.class).getClientId();
        this.client_secret = SpringContextHolder.getBean(OpenApiProperties.class).getSecret();
    }
}

4.Interceptor

拦截器,用于给 FeignClient 添加自定义拦截器

java 复制代码
@Slf4j
public class OpenApiRequestInterceptor implements RequestInterceptor {

    @Autowired
    private JedisClient JedisClient;
    @Autowired
    private AuthOpenApi AuthOpenApi;
    @Autowired
    private OpenApiProperties OpenApiProperties;

    @Override
    public void apply(RequestTemplate requestTemplate) {
        String accessToken = JedisClient.get(CommonConstant.REDIS__KEY_PREFIX + "accessToken");
        if (StringUtils.isEmpty(accessToken)) {
            TokenResponse response = AuthOpenApi.getToken(new GetTokenRequest());
            if (response.getCode() != 200) {
                throw new ApplicationException("获取 accessToken失败");
            }
            accessToken = response.getData().getAccessToken();
            final int expiresIn = response.getData().getExpiresIn();
            log.info("apply() called with: expiresIn = [" + expiresIn + "]");
            JedisClient.set(CommonConstant.REDIS__KEY_PREFIX + "accessToken", accessToken, Math.max(expiresIn - 10, 1));
        }
        long timestamp = System.currentTimeMillis();
        String requestId = UUID.randomUUID().toString();
        String str = OpenApiProperties.getClientId() + timestamp + requestId + accessToken + this.OpenApiProperties.getSecret();
        String signature = DigestUtils.md5Hex(str).toUpperCase();

        requestTemplate.header("clientId", this.OpenApiProperties.getClientId());
        requestTemplate.header("timestamp", timestamp + "");
        requestTemplate.header("requestId", requestId);
        requestTemplate.header("signatureMethod", "MD5");
        requestTemplate.header("accessToken", accessToken);
        requestTemplate.header("signature", signature);
    }
}

5.配置文件类

鉴权需要的参数配置信息

java 复制代码
@Configuration
@ConfigurationProperties(prefix = "open-api")
@Data
public class OpenApiProperties {
    private String url;
    private String clientId;
    private String secret;
    private String aesKey;
    private String aesIv;
}

开启 FeignClients 的功能

java 复制代码
@EnableFeignClients
@Configuration
public class OpenFeignConfig {
}

6.业务接口

获取图片的权限

java 复制代码
@FeignClient(
        url = "${open-api.host}",
        value = "open-api",
        configuration = {
                OpenApiRequestInterceptor.class
        },
        contextId = "picAuth",
        path = "/permission-portal/picture/auth"
)
public interface PicOpenApi {

    @Log("open-api,图片授权模块")
    @GetMapping
    PicResultDto auth(@RequestParam(value = "userNo") String userNo);
}

7.yaml 配置文件

yaml 复制代码
open-api:
  host: xxxxx
  clientId: insight
  secret: xxxx
  aesKey: xxxx
  aesIv: xxxx

8.使用总结

首先用@FeignClient 定义了 2 个接口,一个是获取 token 的接口,一个是获取图片权限的接口,在获取图片权限的接口中添加了 configuration 属性,该属性指向 OpenApiRequestInterceptor 类,在请求获取图片接口的时候,会前置处理拦截器中的逻辑,在拦截器中我们调用的是获取 token 的接口,并解析返回结果,放入到了 http 的请求头中,非常方便的给获取图片的接口添加了 header 鉴权信息。

三.原理解析

1.value/name

value/name : 用于指定目标服务的名称。valuename 都可以用来设置服务的名称,它们是互换的。这是 @FeignClient 唯一需要指定的参数。

java 复制代码
@FeignClient(value = "example-service")
public interface ExampleFeignClient {
    // ...
}

2.url

url : 如果不想使用服务发现,可以使用 url 参数指定目标服务的 URL。这个 URL 可以是完整的服务地址。

java 复制代码
@FeignClient(url = "http://example.com")
public interface ExampleFeignClient {
    // ...
}

3.path

path: 用于为 Feign 客户端的所有请求添加一个基本路径。

java 复制代码
@FeignClient(value = "example-service", path = "/api")
public interface ExampleFeignClient {
    // ...
}

4.configuration

configuration: 用于指定 Feign 客户端的配置类,可以配置连接超时、重试策略、拦截器等。可以指定一个,也可以指定多个,非常给力的功能参数。

java 复制代码
@FeignClient(value = "example-service", configuration = MyFeignConfig.class)
public interface ExampleFeignClient {
    // ...
}

5.fallback

fallback: 用于指定一个降级处理的类,当调用失败时会执行该类的方法。

java 复制代码
@FeignClient(value = "example-service", fallback = ExampleFallback.class)
public interface ExampleFeignClient {
    // ...
}

6.fallbackFactory

fallbackFactory : 与 fallback 类似,用于指定一个降级处理的工厂类,可以在工厂类中对异常进行更详细的处理。

java 复制代码
@FeignClient(value = "example-service", fallbackFactory = ExampleFallbackFactory.class)
public interface ExampleFeignClient {
    // ...
}

7.decode404

decode404 : 默认情况下,Feign 不会解码 404 响应。通过设置 decode404 = true,可以让 Feign 解码 404 响应。

java 复制代码
@FeignClient(value = "example-service", decode404 = true)
public interface ExampleFeignClient {
    // ...
}

@FeignClient 注解的参数,提供了灵活性和配置选项,以适应不同的微服务调用场景。Feign 会根据这些参数配置底层的 HTTP 请求,实现服务之间的通信。

觉得有用的话点个赞 👍🏻 呗。

❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄

💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍

🔥🔥🔥Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙

相关推荐
Miketutu3 小时前
Spring MVC消息转换器
java·spring
小小虫码5 小时前
项目中用的网关Gateway及SpringCloud
spring·spring cloud·gateway
带刺的坐椅10 小时前
无耳科技 Solon v3.0.7 发布(2025农历新年版)
java·spring·mvc·solon·aop
精通HelloWorld!13 小时前
使用HttpClient和HttpRequest发送HTTP请求
java·spring boot·网络协议·spring·http
LUCIAZZZ14 小时前
基于Docker以KRaft模式快速部署Kafka
java·运维·spring·docker·容器·kafka
拾忆,想起14 小时前
如何选择Spring AOP的动态代理?JDK与CGLIB的适用场景
spring boot·后端·spring·spring cloud·微服务
zhuyasen14 小时前
多维度详细比较 kratos、go-zero、goframe、sponge 框架
后端·http·微服务·rpc·golang
鱼骨不是鱼翅15 小时前
Spring Web MVC基础第一篇
前端·spring·mvc
掘金-我是哪吒16 小时前
分布式微服务系统架构第90集:现代化金融核心系统
分布式·微服务·金融·架构·系统架构
hong_zc17 小时前
Spring MVC (三) —— 实战演练
java·spring·mvc