序言:上篇安装了Nacos并注册了系统服务,本篇主要介绍OpenFeign的集成使用。
OpenFeign简介
OpenFeign 是一个声明式的 HTTP 客户端,它通过注解的方式简化了调用 RESTful API 的过程。它是 Spring Cloud 的一部分,用于在微服务架构中简化服务间的通信。与传统的使用 RestTemplate 或 HttpClient 等方式不同,OpenFeign 提供了一种声明式的方式,通过接口和注解来定义 HTTP 请求,避免了手动编写底层 HTTP 请求的代码。
主要特性
- 声明式接口: 通过接口和注解定义 HTTP 请求方法,Feign 会自动为接口方法生成实现并执行 HTTP 请求。例如,使用 @RequestMapping 或其他 HTTP 方法的注解(如 @GetMapping、@PostMapping 等)来描述 API。
- 与 Spring Cloud 集成: OpenFeign 与 Spring Cloud 紧密集成,支持服务发现、负载均衡、熔断、超时控制等功能。
- 简化的客户端调用: 通过简单的接口和注解,OpenFeign 大大减少了 HTTP 请求的样板代码,开发者只需要关注业务逻辑而不需要关心底层的 HTTP 实现。
- 自定义配置: 可以通过自定义配置来扩展 OpenFeign,例如自定义请求拦截器、日志记录、重试机制等。
使用
引入依赖
简单介绍一下,接下来进入代码环节。
右键之前创建的shine-framework模块,新建一个子模块
注意两个地方,一个是位置,另一个是父项,请仔细观察。
创建好之后打开它的POM文件,添加如下依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<optional>true</optional> <!-- 禁止依赖向下传递 -->
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency> <!-- OpenFeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency> <!-- 负载均衡 -->
</dependencies>
记得点击IDEA右侧的刷新。
创建配置文件
在src/main/java下面创建包com.shine.feign.interceptor
创建配置文件FeignRequestTokenInterceptor,内容如下
@Component
public class FeignRequestTokenInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
// 获取当前请求上下文
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if (requestAttributes instanceof ServletRequestAttributes) {
HttpServletRequest currentRequest = ((ServletRequestAttributes) requestAttributes).getRequest();
// 从当前请求的头中获取 token
String token = currentRequest.getHeader("Authorization");
if (StringUtils.isNotBlank(token)) {
// 将 token 添加到 Feign 请求的头中
template.header("Authorization", token);
}
}
}
}
代码说明:
主要目的:将请求Token传递给下游服务,防止下游服务获取不到当前的用户信息(目前的目的是这样的)
@Component:该注解将这个类声明为一个 Spring 组件,使其被 Spring 容器自动扫描并管理。这样,Spring 在启动时会自动将这个拦截器注册到 Feign 中。
RequestInterceptor:实现了 Feign 提供的 RequestInterceptor 接口。RequestInterceptor 是 Feign 中的一个接口,用于定义拦截器逻辑。实现该接口的类可以在 Feign 发出请求前执行特定的操作。
apply(RequestTemplate template):这是 RequestInterceptor 接口中的方法,Feign 在每次发出 HTTP 请求之前都会调用这个方法。方法参数 RequestTemplate 是 Feign 用来描述请求的模板对象,通过它可以设置请求头、请求体等。
在src/main/java下面创建包com.shine.feign.config
@Configuration
@EnableFeignClients(basePackages = "com.shine.*.*")
public class OpenfeignConfig {
@Bean
public Feign.Builder feignBuilder() {
// 连接超时2秒,读取超时5秒
return Feign.builder().options(new Request.Options(2, TimeUnit.SECONDS, 5, TimeUnit.SECONDS, true));
}
@Bean
public RequestInterceptor oauthFeignRequestInterceptor() {
return new OAuthFeignRequestInterceptor();
}
}
代码说明:
@Configuration: Spring 的一个注解,表示该类是一个配置类,Spring 容器会加载它,类似于 XML 配置文件中的配置项。
@EnableFeignClients: 是 Spring Cloud 的注解,用于启用 Feign 客户端功能。它会扫描指定包下的所有 Feign 客户端接口(即使用 @FeignClient 注解的接口)。
basePackages = “com.shine.*.*”:这部分指定了 Feign 客户端接口扫描的包路径。在这里,它将扫描 com.shine 包下的所有子包和更深层的子包(*.* 表示递归扫描)。
@Bean: 注解用于将方法的返回值作为 Spring 容器中的 Bean。
Feign.builder():构建一个 Feign 的客户端实例。
Request.Options(2, TimeUnit.SECONDS, 5, TimeUnit.SECONDS, true):这里是配置 Feign 客户端的连接和读取超时:
- 2 秒:连接超时,表示连接到目标服务的最大时间。
- 5 秒:读取超时,表示在连接成功后,从目标服务读取响应的最大等待时间。
- TimeUnit.SECONDS:指定时间单位为秒。
- true:启用请求重试机制。
RequestInterceptor: 是 Feign 的一个接口,用于在每个 Feign 请求发出之前进行拦截操作,例如添加请求头、修改请求参数等。
FeignRequestTokenInterceptor: 是一个自定义的拦截器类(前面创建的那个类),它用于将当前 HTTP 请求的 Authorization 头信息传递到 Feign 请求中,从而实现认证信息的传递。
在src/main/java下面创建包com.shine.feign.constant,用于存放常量。
public interface FeignClientConstant {
String SYSTEM_NAME = "system-service";
}
由于上一章我们创建了系统服务,那么就先声明这一个常量,系统服务的服务名SYSTEM_NAME
至此,此模块初步创建完成,将此模块的版本管理交给父工程。
在shine-cloud-server的POM文件中添加如下内容:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.shine</groupId>
<artifactId>shine-openfeign-starter</artifactId>
<version>${shine-cloud.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
这样服务引入shine-openfeign-starter的时候就可以不用指定版本号。
使用
在之前创建的shine-api模块下创建一个新的模块:shine-system-api。
注意父项和位置。
创建好之后打开它的POM文件,添加如下内容:
<dependencies>
<dependency>
<groupId>com.shine</groupId>
<artifactId>shine-common</artifactId>
</dependency>
<dependency>
<groupId>com.shine</groupId>
<artifactId>shine-openfeign-starter</artifactId>
</dependency>
</dependencies>
不要忘了右侧的刷新哦
因为shine-common是公共依赖,所以这里直接引入。
创建包com.shine.system.feign,用来存放Feign客户端
右键刚才创建的包新建一个接口TestFeign
内容如下
@FeignClient(name = FeignClientConstant.SYSTEM_NAME, contextId = "test", path = "/user")
public interface TestFeign {
@GetMapping("/getUser")
String getUser(@RequestParam Long userId);
}
FeignClientConstant.SYSTEM_NAME为刚才创建的常量。
在shine-system-service的com.shine.system.feign.impl下面创建一个类TestFeignImpl
内容如下
@RestController
@RequestMapping("/user")
public class TestFeignImpl implements TestFeign {
@Override
public String getUser(Long userId) {
return "获取到用户:" + userId + "啦~";
}
}
至此,我们已经成功定义了一个Feign客户端。
测试
浏览器测试
其实可以不用创建一个消费者服务也可以测试,可以直接用浏览器测试
启动system服务,浏览器访问:http://localhost:9001/user/getUser?userId=100
返回内容如下即为成功
服务调用测试
服务调用我们就简单的测试一下就好,如果上面的没问题那么这个基本上也不会有问题。
在shine-service下面创建消费服务shine-feign-customer-service,名称随意
还是要注意这两个地方
打开它的POM文件,内容如下
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.shine</groupId>
<artifactId>shine-system-api</artifactId>
</dependency>
</dependencies>
不要忘了右侧的刷新
创建包com.shine.customer,创建启动类CustomerApplication
内容如下
@EnableFeignClients
@SpringBootApplication
@EnableDiscoveryClient
@ComponentScan(basePackages = { "com.shine" }) // 指定扫描包
public class CustomerApplication {
public static void main(String[] args) {
SpringApplication.run(CustomerApplication.class, args);
}
}
在com.shine.customer包下创建controller包并创建CustomerController类,内容如下
@RestController
@RequestMapping("/customer")
public class CustomerController {
@Autowired
private TestFeign testFeign;
@GetMapping("/callUser")
public String callUser() {
String res = testFeign.getUser(100L);
return "调用结果是:" + res;
}
}
因为默认端口是8080,系统服务已经占用,所以在resource文件夹下面创建一个配置文件bootstrap.yml,内容如下
server:
port: 8081
nacos:
server-addr: 127.0.0.1:8848
username: nacos
password: nacos
namespace: 7a315776-c8ed-4a70-be9c-2d60debde2e8
group: DEFAULT_GROUP
spring:
application:
name: customer-service
cloud:
nacos:
discovery:
server-addr: ${nacos.server-addr}
username: ${nacos.username}
password: ${nacos.password}
namespace: ${nacos.namespace}
group: ${nacos.group}
OpenFeign要根据服务名找对应的请求地址,需要注册到注册中心
整体目录结构如下
启动CustomerApplication,访问Nacos,出现如下界面表示注册成功
访问浏览器:http://localhost:8081/customer/callUser
出现如下界面表示调用成功
至此,OpenFeign集成完成。
结语:我在写这篇文章的时候发现公共模块内的内容很重要,所以下一章节就围绕着shine-common展开,定义一些通用的内容,之后我们再继续进行扩展。
标签:shine,Feign,OpenFeign,04,SpringCloudAlibaba,创建,com,public,请求 From: https://blog.csdn.net/m0_56441750/article/details/145197706