当前位置: 首页 > java >正文

OpenFeign服务接口调用

        在使用Spring Cloud开发微服务应用时,可使用RestTemplate+Ribbon的方式实现服务接口的远程调用。

package com.hl.service.impl;import com.hl.clients.OrderClient;
import com.hl.pojo.Order;
import com.hl.service.OrderService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;import java.util.Map;@Service
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {private final RestTemplate restTemplate;@Overridepublic Order getOrder() {Map map = restTemplate.exchange("http://localhost:8082/order",HttpMethod.GET,null,Map.class).getBody();Order order = new Order();if (map != null) {order = new Order(1, (String) map.get("name"), (String) map.get("address"));}return order;}
}

        但这种方式需要填写远程地址,并配置相关参数,那么有没有更简单的方式呢?还可以使用OpenFeign来实现服务接口的远程调用。OpenFeign是一个声明式的HTTP客户端,可以在程序中像调用本地方法一样调用服务接口,并且支持负载均衡。

一、基于OpenFeign的微服务接口调用

        OpenFeign 是一个声明式的 Web Service 客户端,它使得编写 HTTP 客户端变得更简单。通过使用 Feign,开发者只需创建一个接口并在上面添加注解即可完成服务调用。

主要特点

  1. 声明式 API:通过接口和注解定义服务调用

  2. 集成 Ribbon:支持客户端负载均衡

  3. 集成 Hystrix:支持服务熔断(需额外配置)

  4. 支持 Spring MVC 注解:如 @RequestMapping@PathVariable 等

远程调用的关键点就在于四个:

  • 请求方式

  • 请求路径

  • 请求参数

  • 返回值类型

所以,OpenFeign就利用SpringMVC的相关注解来声明上述4个参数,然后基于动态代理帮我们生成远程调用的代码,而无需我们手动再编写,非常方便。

1. OpenFeign基本使用

        将服务提供者和服务消费者整合到Nacos注册中心之后,给服务消费者添加Feign依赖,并创建Feign接口,服务消费者使用Feign接口来调用服务提供者。下面以一个简单的案例说明如何使用OpenFeign实现服务调用。

案例说明:分别创建一个简单的微服务模拟服务提供者和服务消费者,并将其整合到Nacos注册中心,然后通过OpenFeign实现服务调用。

1.1 父工程

创建父工程统一管理Spring Boot、Spring Cloud和Spring Cloud Alibaba。父工程统一管理子模块依赖的版本号,pom.xml文件代码如下所示。

<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.hl</groupId><artifactId>shop</artifactId><version>1.0.0</version><packaging>pom</packaging><modules><module>order-consumer</module><module>order-provider</module></modules><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.12</version><relativePath/></parent><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><spring-cloud.version>2021.0.3</spring-cloud.version><spring-cloud-alibaba.version>2021.0.4.0</spring-cloud-alibaba.version><spring-boot-web.version>2.7.12</spring-boot-web.version></properties><dependencyManagement><dependencies><!--spring cloud--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency><!--spring cloud alibaba--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>${spring-cloud-alibaba.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.22</version></dependency><!--单元测试--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency></dependencies></project>

1.2 service-provider微服务——服务提供者

① 在父工程中创建service-provider微服务来模拟服务提供者。修改service-provider微服务中的pom.xml文件,代码如下所示。

<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>com.hl</groupId><artifactId>shop</artifactId><version>1.0.0</version></parent><artifactId>service-provider</artifactId><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--nacos 服务注册发现--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency></dependencies></project>

② 在resources目录下创建application.yaml文件,配置服务端口号为9001、微服务名为

“service-provider”、Nacos注册中心地址为“localhost:8848”,代码如下所示。

server:port: 9001 
spring:application: name: service-provider   cloud:nacos:discovery:server-addr: localhost:8848 

③ 创建项目启动类ServiceProviderApplication,在该启动类上追加@EnableDiscoveryClient

注解,开启服务注册与发现功能,代码如下所示。

package com.hl;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;@SpringBootApplication
@EnableDiscoveryClient
public class ServiceProviderApplication{public static void main(String[] args) {SpringApplication.run(ServiceProviderApplication.class, args);}
}

④ 创建OrderController类,在该类上追加@RestController注解,在该类中定义一个getOrder()方法。

package com.hl.controller;import com.hl.properties.OrderProperties;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.HashMap;
import java.util.Map;@RestController
@RequiredArgsConstructor
public class OrderController {private final OrderProperties orderProperties;@GetMapping("/order")public Map<String, String> getOrder() {System.out.println(orderProperties.getName());System.out.println(orderProperties.getAddress());Map<String, String> map = new HashMap<>();map.put("name", orderProperties.getName());map.put("address", orderProperties.getAddress());return map;}
}

1.3 service-consumer微服务——服务消费者

在父工程中创建service-consumer微服务来模拟服务消费者。

① 修改pom.xml文件,在<dependencies></dependencies>标签中添加OpenFeign依赖spring-cloud-starter-openfeign,代码如下所示。

<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>com.hl</groupId><artifactId>shop</artifactId><version>1.0.0</version></parent><artifactId>service-consumer</artifactId><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--nacos 服务注册发现--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--openFeign--><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></dependencies></project>

② 在resources目录下创建application.yaml文件,配置服务端口号为8081、微服务名为

“service-consumer”、Nacos注册中心地址为“localhost:8848”,代码如下所示。

server:port: 8081
spring:application:name: service-consumerprofiles:active: devcloud:nacos:server-addr: localhost:8848 # nacos地址

③ 创建项目启动类ServiceConsumerApplication,在该启动类上追加@EnableDiscoveryClient注解和@EnableFeignClients注解,代码如下所示。

package com.hl;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;@SpringBootApplication
@EnableFeignClients
@EnableDiscoveryClient
public class ServiceConsumerApplication{public static void main(String[] args) {SpringApplication.run(ServiceConsumerApplication.class, args);}
}

④ 创建Feign接口OrderClient ,使用@FeignClient注解声明要调用的服务 “service-provider”,使用@GetMapping注解声明要调用的接口“/order”,代码如下所示。

package com.hl.clients;import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;import java.util.Map;@FeignClient("service-provider")
public interface OrderClient {@GetMapping("/order")public Map<String, String> getOrder();
}

⑤ 创建OrderServiceImpl 类,在该类上追加@Service注解,在该类中注入OrderClient 接口,然后调用该接口,代码如下所示。

        其中feign替我们完成了服务拉取、负载均衡、发送http请求的所有工作

package com.hl.service.impl;import com.hl.clients.OrderClient;
import com.hl.pojo.Order;
import com.hl.service.OrderService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;import java.util.Map;@Service
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {private final OrderClient orderClient;@Overridepublic Order getOrder() {Map<String, String> map = orderClient.getOrder();Order order = new Order();if (map != null) {order = new Order(1, (String) map.get("name"), (String) map.get("address"));}return order;}
}

⑥编写测试类OrderTest

package com.hl;import com.hl.pojo.Order;
import com.hl.service.OrderService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
public class OrderTest {@Autowiredprivate OrderService orderService;@Testpublic void test() {Order order = orderService.getOrder();System.out.println(order);}
}

        在IDEA工具中启动两个微服务:service-provider和service-consumer。启动Nacos,访问http://localhost:8848/nacos,查看“服务管理”下的“服务列表”,可发现service-provider和service-consumer微服务实例

        运行测试类OrderTest的test方法,验证远程调用是否生效

2. 连接池

Feign底层发起http请求,依赖于其它的框架。其底层支持的http客户端实现包括:

  • HttpURLConnection:默认实现,不支持连接池

  • Apache HttpClient :支持连接池

  • OKHttp:支持连接池

因此我们通常会使用带有连接池的客户端来代替默认的HttpURLConnection。比如,我们使用OK Http。

2.1.引入依赖

在service-consumer的pom.xml中引入依赖:

<!--OK http 的依赖 -->
<dependency><groupId>io.github.openfeign</groupId><artifactId>feign-okhttp</artifactId>
</dependency>

2.2.开启连接池

在service-consumer的application.yml配置文件中开启Feign的连接池功能:

feign:okhttp:enabled: true # 开启OKHttp功能

重启服务,连接池就生效了。

3. OpenFeign日志管理

OpenFeign只会在FeignClient所在包的日志级别为DEBUG时,才会输出日志。而且其日志级别有4级:

  • NONE:不记录任何日志信息,这是默认值。

  • BASIC:仅记录请求的方法,URL以及响应状态码和执行时间

  • HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息

  • FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据。

Feign默认的日志级别就是NONE,所以默认我们看不到请求日志。

3.1 包日志级别

定位到service-consumer微服务的application.yaml文件,新增配置项logging.level,声明接口的包名,代码如下所示。

server:port: 8081
spring:application:name: service-consumerprofiles:active: devcloud:nacos:server-addr: localhost:8848 # nacos地址
logging:level:com.hl: debug

3.2 日志配置类

package com.hl.config;import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class DefaultFeignConfig{@Beanpublic Logger.Level level() {//FULL日志级别return Logger.Level.FULL;}
}

3.3 配置

接下来,要让日志级别生效,还需要配置这个类。有两种方式:

  • 局部生效:在某个FeignClient中配置,只对当前FeignClient生效

@FeignClient(value = "item-service", configuration = DefaultFeignConfig.class)

  • 全局生效:在@EnableFeignClients中配置,针对所有FeignClient生效。

@EnableFeignClients(defaultConfiguration = DefaultFeignConfig.class)

重新运行测试方法,返回IDEA控制台,可以看到Feign接口名、调用的方法名等内容

4. OpenFeign超时控制

        OpenFeign默认等待返回接口的数据时间是1s,超过1s就会报错。这种情况下大部分接口没有问题,但是不能排除部分接口耗时较长,在执行过程中用时超过1s。若直接返回报错信息并不是最合理的选择。OpenFeign提供了超时设置。

feign:client:config:default:# 超时时间,单位毫秒,默认2000connect-timeout: 5000# 读取超时时间,单位毫秒,默认5000read-timeout: 5000

 

 

http://www.xdnf.cn/news/2464.html

相关文章:

  • 使用Three.js搭建自己的3Dweb模型(从0到1无废话版本)
  • [特殊字符] SQL注入攻击的常见写法及危害
  • Zookeeper断开连接时分布式锁释放问题的解决方案
  • 基于深度学习的智能交通流量监控与预测系统设计与实现
  • vue3 vite打包后动态修改打包后的请求路径,无需打多个包给后端
  • 从基础到实战的量化交易全流程学习:1.3 数学与统计学基础——概率与统计基础 | 数字特征
  • 常用第三方库:shared_preferences数据持久化
  • 基于大模型的急性化脓性阑尾炎全程诊疗预测与方案研究
  • 【音视频】视频解码实战
  • RAG(Retrieval-Augmented Generation,检索增强生成)
  • CSDN编辑文章时如何自动生成目录
  • 生成式人工智能认证(GAI认证)含金量怎么样?
  • 雪铁龙C5车机系统恢复
  • Java使用微信云服务HTTP API操作微信云开发数据库
  • Redis 缓存并发问题深度解析:击穿、雪崩与穿透防治指南
  • Java + Seleium4.X + TestNG自动化技术
  • 第三方软件检测报告:热门办公软件评估及功能表现如何?
  • Linux用户管理
  • 内存四区(堆)
  • Git命令(Gitee)
  • Linux—— 版本控制器Git
  • Linux 在个人家目录下添加环境变量 如FLINK_PROPERTIES=“jobmanager.rpc.address: jobmanager“
  • Android LiveData关键代码
  • Docker小游戏 | 使用Docker部署文字修仙网页小游戏
  • Xray-安全评估工具
  • 月之暗面开源-音频理解、生成和对话生成模型:Kimi-Audio-7B-Instruct
  • 【DNS】BIND9 域名解析快速入门
  • Spring框架的ObjectProvider用法
  • 【C++】类和对象【中上】
  • C++ 完全数