前面章节已经搭建好了 Spring Cloud OpenFeign 学习的环境,一个 Eureka 服务和一个 service-demo 服务,下面将通过一个简单示例,快速上手 Spring Cloud OpenFeign。
项目结构如下图:
包说明:
entity 存放实体,仅有一个 User 实体
dto 数据传输对象,其中 CommonReturn 定义了接口通用传输格式
feign 存放所有的 Feign 客户端类
controller 定义三个业务 Controller,分别用于简单 POST、GET 服务,用户信息管理 Controller
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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.2.9</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.hxstrive</groupId> <artifactId>openfeign-demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>openfeign-demo</name> <description>openfeign-demo</description> <properties> <java.version>17</java.version> <spring-cloud.version>2023.0.3</spring-cloud.version> <base.path>${project.basedir}</base.path> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <!-- feign 依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <!-- 缓存 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <dependency> <groupId>com.github.ben-manes.caffeine</groupId> <artifactId>caffeine</artifactId> <version>3.1.8</version> </dependency> <!-- 熔断依赖 --> <!--<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</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> <build> <finalName>demo_netflix_feign</finalName> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
application.yml 配置内容如下:
server: port: 8080 spring: application: name: open_feign_application # 服务地址 eureka: client: enabled: true service-url: # 注册中心路径,表示我们向这个注册中心注册服务,如果向多个注册中心注册,用“,”进行分隔 defaultZone: http://localhost:8761/eureka instance: hostname: localhost # 心跳间隔5s,默认30s。每一个服务配置后,心跳间隔和心跳超时时间会被保存在server端, # 不同服务的心跳频率可能不同,server端会根据保存的配置来分别探活 lease-renewal-interval-in-seconds: 5 # 心跳超时时间10s,默认90s。从client端最后一次发出心跳后, # 达到这个时间没有再次发出心跳,表示服务不可用,将它的实例从注册中心移除 lease-expiration-duration-in-seconds: 10
package com.hxstrive.demo_springcloud_openfeign.dto; import lombok.Data; /** * 通用返回对象 * @author hxstrive.com */ @Data public class CommonReturn<T> { private int code; private String message; private T data; private String appName; private String port; public static <T> CommonReturn<T> success(T data) { CommonReturn<T> commonReturn = new CommonReturn<>(); commonReturn.setCode(1); commonReturn.setData(data); return commonReturn; } public static <T> CommonReturn<T> fail(String message) { CommonReturn<T> commonReturn = new CommonReturn<>(); commonReturn.setCode(0); commonReturn.setMessage(message); return commonReturn; } public CommonReturn<T> ext(String appName, String port) { this.setAppName(appName); this.setPort(port); return this; } }
package com.hxstrive.demo_springcloud_openfeign.entity; import lombok.Builder; import lombok.Data; import lombok.ToString; import java.util.Date; /** * 用户实体 * @author hxstrive.com */ @Data @Builder @ToString public class User { private Long id; private String name; private Integer age; }
下面代码定义了一个使用 OpenFeign 进行服务调用的接口 SimpleFeign。通过这个接口,能够方便地向名为 SERVICE-DEMO 的服务发起特定的 HTTP 请求来获取数据或执行操作。代码如下:
package com.hxstrive.demo_springcloud_openfeign.feign; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; /** * 用户 Feign * @author hxstrive.com */ @FeignClient("SERVICE-DEMO") public interface SimpleFeign { @GetMapping("/simple/hello") String hello(); }
注意:
SERVICE-DEMO 是一个服务名,可以通过 Eureka 管理页面获取,不区分大小写。
@FeignClient("SERVICE-DEMO") 用于标识该接口是一个 OpenFeign 客户端接口,并且指定了要调用的目标服务名称为 SERVICE-DEMO。OpenFeign 就能够根据配置(如服务发现配置,常见的有基于 Eureka 等服务发现组件的配置)找到对应的服务实例所在的位置,以便后续发起准确的服务调用。
@GetMapping("/simple/hello") 表示该方法将处理一个 HTTP GET 请求,并且请求的路径为 /simple/hello。在 SimpleFeign 接口中,它明确了当通过这个 OpenFeign 客户端调用目标服务时,要发送的具体请求路径。
通过 Spring 的依赖注入自动将 SimpleFeign 接口注入到当前控制器,然后通过调用 SimpleFeign 接口的 hello() 方法发起远程 HTTP 调用,代码如下:
package com.hxstrive.demo_springcloud_openfeign.controller; import com.hxstrive.demo_springcloud_openfeign.feign.SimpleFeign; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; /** * 控制器 * @author hxstrive.com */ @RestController public class FeignController { @Autowired private SimpleFeign simpleFeign; @GetMapping("/hello") public Object hello() { return simpleFeign.hello(); } }
该类也是一个简单的 Spring Boot 启动类,唯一不同的是在该类上添加了 @EnableFeignClients 注解。@EnableFeignClients 是 Spring Cloud 提供的一个注解,用于开启 Feign 客户端功能。当在 Spring Boot 应用的主配置类(通常是带有 @SpringBootApplication 注解的类)上添加这个注解后,Spring Cloud 会自动扫描并注册带有@FeignClient注解的接口,将它们配置为 Feign 客户端,从而能够方便地进行远程服务调用。
代码如下:
package com.hxstrive.demo_springcloud_openfeign; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.openfeign.EnableFeignClients; /** * 启动类 * @author hxstrive.com */ @SpringBootApplication // 启动 Feign 客户端 @EnableFeignClients //(defaultConfiguration = FeignConfig.class) public class OpenfeignDemoApplication { public static void main(String[] args) { SpringApplication.run(OpenfeignDemoApplication.class, args); } }
完成上述开发后,启动 Demo 程序,启动后的状态如下图:
上图中,目前我们启动了三个应用程序,分别是 Eureka 服务端、Service Demo 服务和示例 Demo。
此时,访问 http://localhost:8761 地址,查看 Eureka 管理页面,如下图:
这是,Eureka 上面注册了两个服务,分别为 OPEN_FEIGN_APPLICATION 和 SERVICE-DEMO。
最后,使用浏览器访问 http://localhost:8080/hello 地址,效果如下图: