还在用 OpenFeign?来试试 SpringBoot3 中的这个新玩意!

文章介绍了SpringBoot3引入的新特性——使用@HttpExchange注解进行声明式HTTP接口调用,它类似于OpenFeign但内建于Spring框架中。通过示例展示了如何创建和配置接口以及使用WebClient进行服务调用,提供了一种新的服务间通信方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 由来

Spring Boot3 去年底就已经正式发布,我也尝了一把鲜,最近有空会和小伙伴们慢慢聊聊 Spring Boot3 都给我们带来了哪些新东西。

今天我们就先来看看声明式 HTTP 接口。

用过 Spring Cloud 的小伙伴都知道,在 Spring Cloud 家族中,负责进程间通信的,我们可以使用 RestTemplate 或者 OpenFeign(当然也有其他方式如基于消息中间件的消息驱动的微服务或者基于 gRPC 的调用等)。

RestTemplate 我们可以将之当作一个普普通通的 HTTP 调用工具来对待,区别于其他的 HTTP 客户端,RestTemplate 用来调用 RESTful 风格的接口特别方便。

不过,比 RestTemplate 更加方便的是 OpenFeign,通过接口声明就可以实现远程调用,这些的具体用法松哥在之前的视频中讲过,这里就不再赘述了。

以前我们想要用声明式 HTTP 调用,需要通过 OpenFeign 来实现,这个需要第三方的依赖,从 Spring6 开始(Spring Boot3),Spring 自己提供了类似的功能通过 @HttpExchange 注解也能方便的实现 声明式 HTTP 调用。以后跨服务调用又多了一个选择。

2. 使用

接下来松哥通过一个案例来和小伙伴们演示一下 @HttpExchange 注解的具体玩法。

首先我们先创建一个普通的名为 server 的 Spring Boot 项目,这个普通的 Spring Boot 项目中只需要提供一个简单的测试接口即可,如下:

@RestController
public class HelloController {

    @GetMapping("/server/hello")
    public String hello(String name) {
        return "hello " + name;
    }

}
复制代码

这个对大家来说应该是没什么难度的,我就不多说了。

现在假设我有另外一个服务名为 client,我想在 client 中调用 server 中提供的这个接口。

首先我们来创建 client 这个项目,大家注意,创建的时候我们不仅需要添加 Web 依赖,还需要 Reactive Web,因为这个 @HttpExchange 底层基于 WebClient,而 WebClient 则是 Reactive Web 提供的:

创建完成后,接下来我们就可以声明 Http 接口了:

@HttpExchange("/server")
public interface ToDoService {
    @GetExchange("/hello")
    String hello(@RequestParam String name);
}
复制代码

这些用法跟我们在 SpringMVC 中常用的 @RequestMapping 和 @GetMapping 等特别类似:

  • @HttpExchange 类似于 @RequestMapping,可以将之放在类上,起到一个请求窄化的作用,也可以放在方法上,放在方法上我们可以通过 method 属性来指定具体的请求方法,这个也跟 @RequestMapping 类似: @HttpExchange(value = "/server",method = "GET")
  • @GetExchange 类似于 @GetMapping,这个就不再赘述了,其他类似的注解还有 @DeleteExchange@PatchExchange@PostExchange@PutExchange 等。
  • 另外需要注意的是请求方法的参数需要加上 @RequestParam 注解,这一点和 OpenFeign 比较类似。

接口声明好之后还没完,我们还需要配置一下才能使用。如下:

@Configuration
public class WebConfig {
    @Bean
    WebClient webClient() {
        return WebClient.builder()
                .baseUrl("http://localhost:8080")
                .build();
    }
    @Bean
    ToDoService toDoService() {
        HttpServiceProxyFactory httpServiceProxyFactory =
                HttpServiceProxyFactory.builder(WebClientAdapter.forClient(webClient()))
                        .build();
        return httpServiceProxyFactory.createClient(ToDoService.class);
    }
}
复制代码

这个配置主要是两方面:

  1. @HttpExchange 是基于 WebClient 的,所以我们首先需要配置 WebClient,配置 WebClient 的时候,也顺便配置了请求的具体地址(因为在 @HttpExchange 注解中并未指定请求的具体域名端口啥的);同时,对于 HTTP 请求头等如果需要定制,也是通过配置 WebClient 来实现的。
  2. 由于我们前面提供的 ToDoService 是一个接口,所以我们还需要提供一个该接口的实现类,当然这个配置完全是套路化模版化的,这块就没啥好说了。

全部配置完成后,接下来我们就可以在任何需要的地方,直接注入 ToDoService 的实例去使用了,举一个简单的例子小伙伴们参考下:

@SpringBootTest
class ClientApplicationTests {

    @Autowired
    ToDoService toDoService;

    @Test
    void contextLoads() {
        String hello = toDoService.hello("javaboy");
        System.out.println("hello = " + hello);
    }

}
复制代码

好啦,一个简单的例子,小伙伴们不妨体验下。

以后,不用 OpenFeign 也能实现声明式服务调用啦~

作者:江南一点雨
原文链接:https://juejin.cn/post/7195376356958404667

<think>好的,我现在需要帮助用户了解在Spring Boot 2.7中如何使用FeignClient。首先,用户之前的问题是关于Spring循环依赖的,现在转到了FeignClient的使用,可能他们在开发微服务时遇到了服务间调用的需求,而FeignClient是常用的解决方案。 首先,我应该确认用户的需求。他们可能已经知道FeignClient的基本概念,但需要具体的配置和使用步骤。用户提到的是Spring Boot 2.7,所以需要确保提供的代码和依赖版本与该版本兼容。 接下来,我需要回忆FeignClient在Spring Boot中的一般使用步骤。通常包括添加依赖、启用Feign、创建接口、配置参数等。可能还需要处理日志、拦截器、超时设置等高级配置。需要注意Spring Boot 2.7对应的Spring Cloud版本,因为不同版本的配置可能不同。例如,Spring Boot 2.7通常对应Spring Cloud 2021.0.3,因此需要确认依赖的正确性。 然后,用户可能需要示例代码,所以应该准备一个简单的例子,包括接口定义、启动类注解、配置文件的设置。此外,常见的注意事项和错误处理也是关键,比如熔断降级、请求编码、错误解码器等。需要提醒用户添加必要的依赖,如spring-cloud-starter-openfeign,以及可能的Hystrix支持,如果用到熔断的话。 还要考虑用户可能遇到的常见问题,比如FeignClient无法注入,接口未正确实现,配置参数错误等。在回答中应该包含这些问题的解决方法,或者至少提到如何调试和排查这些问题。 另外,用户可能对FeignClient的高级用法感兴趣,比如拦截器、自定义配置类、继承父接口等。需要简要介绍这些内容,但保持重点在基本使用上,避免信息过载。 最后,确保回答结构清晰,分步骤说明,让用户能够一步步跟着操作。同时,使用中文,避免术语混淆,保持口语化,但不过于随意,保持专业性。</think>### **Spring Boot 2.7 中 FeignClient 使用详解** --- #### **一、环境准备** 1. **依赖配置** 在 `pom.xml` 中添加 OpenFeign 核心依赖: ```xml <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> <version>3.1.3</version> <!-- Spring Boot 2.7 对应版本 --> </dependency> ``` 2. **启动类注解** 添加 `@EnableFeignClients` 激活 Feign: ```java @SpringBootApplication @EnableFeignClients(basePackages = "com.example.feign") // 指定扫描包 public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` --- #### **二、基础使用** ##### **1. 定义接口** ```java @FeignClient( name = "userService", // 服务标识(必填) url = "http://localhost:8080", // 直接指定URL(测试用) configuration = FeignConfig.class, // 自定义配置类 fallback = UserServiceFallback.class // 熔断降级类 ) public interface UserFeignClient { @GetMapping("/users/{id}") // 与目标服务接口一致 User getUser(@PathVariable("id") Long id); @PostMapping("/users") User createUser(@RequestBody User user); } ``` ##### **2. 熔断降级实现** ```java @Component public class UserServiceFallback implements UserFeignClient { @Override public User getUser(Long id) { return new User(-1L, "fallback-user"); // 默认返回值 } @Override public User createUser(User user) { throw new ServiceUnavailableException("服务不可用"); } } ``` --- #### **三、关键配置参数** 在 `application.yml` 中配置: ```yaml feign: client: config: default: # 全局默认配置 connectTimeout: 5000 # 连接超时(ms) readTimeout: 10000 # 读取超时(ms) loggerLevel: basic # 日志级别(none/basic/headers/full) userService: # 针对特定服务的配置 readTimeout: 30000 compression: request: enabled: true # 开启请求压缩 mime-types: text/xml,application/xml,application/json min-request-size: 2048 # 最小压缩阈值 ``` --- #### **四、高级功能** ##### **1. 自定义拦截器** ```java public class AuthInterceptor implements RequestInterceptor { @Override public void apply(RequestTemplate template) { template.header("Authorization", "Bearer " + getToken()); } } // 在配置类中注册 @Configuration public class FeignConfig { @Bean public AuthInterceptor authInterceptor() { return new AuthInterceptor(); } } ``` ##### **2. 继承式接口定义** ```java // 公共接口 public interface BaseUserApi { @GetMapping("/users/{id}") User getUser(@PathVariable("id") Long id); } // Feign客户端继承 @FeignClient(name = "userService", url = "${feign.client.userService.url}") public interface UserFeignClient extends BaseUserApi { // 可扩展其他方法 } ``` --- #### **五、常见问题解决** | **问题现象** | **解决方案** | |----------------------------------|-----------------------------------------------------------------------------| | 服务发现失败 (No instances available) | 检查是否添加 `spring-cloud-starter-loadbalancer` 依赖 | | 返回数据反序列化失败 | 确保DTO类有无参构造函数,字段类型与JSON匹配 | | 文件上传失败 | 使用 `@RequestPart` 注解并配置编码器: ```java @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) void upload(@RequestPart("file") MultipartFile file); ``` --- #### **六、性能优化建议** 1. **连接池配置** 替换默认HTTP客户端为 Apache HttpClient: ```xml <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-httpclient</artifactId> </dependency> ``` 配置连接池参数: ```yaml httpclient: max-connections: 200 # 最大连接数 max-connections-per-route: 50 # 单路由最大连接数 ``` 2. **响应缓存** 在 Feign 接口方法添加 Spring Cache 注解: ```java @Cacheable(value = "users", key = "#id") @GetMapping("/users/{id}") User getUser(@PathVariable("id") Long id); ``` --- #### **七、调试技巧** 1. **日志追踪** 开启完整日志: ```yaml logging: level: org.springframework.cloud.openfeign: DEBUG ``` 2. **请求响应查看** 在拦截器中打印请求信息: ```java template.header("X-Request-ID", UUID.randomUUID().toString()); System.out.println("Feign Request: " + template.toString()); ``` --- ### **核心总结** 1. **版本匹配**:Spring Boot 2.7 对应 Spring Cloud 2021.0.x,需确保依赖版本一致 2. **熔断必配**:生产环境必须实现 `fallback` 或 `fallbackFactory` 3. **性能优先**:推荐使用连接池替代默认实现,提升吞吐量 4. **契约模式**:可通过 `contract` 属性切换为原生Feign契约(需谨慎使用)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值