SpringCloud学习笔记(六)Feign

6.http客户端Feign

6.1 Feign代替RestTemplate

RestTemplate缺点:代码可读性差;url维护不方便

Feign:一个声明式的http客户端,优雅地实现http请求的发送,官网 RPC(远程过程调用)

原理:基于接口的动态代理(动态代理应用:AOP)

定义和使用

1.引入feign依赖

 <!--feign客户端依赖-->
 <dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-openfeign</artifactId>
 </dependency>

2.添加注解@EnableFeignClients开启feign功能-order-service

 @MapperScan("cn.itcast.order.mapper")
 @SpringBootApplication
 @EnableFeignClients
 public class OrderApplication {
 ​
     public static void main(String[] args) {
         SpringApplication.run(OrderApplication.class, args);
    }
 ​
     @Bean
     @LoadBalanced
     public RestTemplate restTemplate() {
         // todo 据说官方推荐RestTemplateBuilder
         return new RestTemplate();
    }
 ​
 }

3.编写Feign客户端

 @FeignClient("user-service")
 public interface UserClient {
     @GetMapping("/user/{id}")
     User findById(@PathVariable("id") Long id);
 }

4.使用feign进行http访问

 @Autowired
 private UserClient userClient;
 ​
 public Order queryOrderById(Long orderId){
     Order order = orderMapper.findById(orderId);
     if(null!=order && null!=order.getUserId()){
         //类型解析
         ObjectMapper mapper = new ObjectMapper();
         User user = mapper.convertValue(result.getData(),User.class);
    order.setUser(user);
    }
     return order;
 }

6.2 自定义配置

image-20230410162223857

由于新版(4.0.2)的Feign已经不支持yml文件自定义配置了,所以需要编写配置类

1.编写配置类

 public class UserFeignConfig {
     //feign4.0.2貌似不支持yml文件配置feign,所以使用配置类的方式实现覆写配置
     //自定义feign的配置
 ​
     //定义日志输出级别
     @Bean
     public Logger.Level feignLoggerLevel(){
         return Logger.Level.FULL;
    }
 }

2.在自定义的FeignClient中声明要加载的配置类configuration

 @FeignClient(value = "user-service",configuration = UserFeignConfig.class)
 public interface UserClient {
     @GetMapping("/user/{id}")
     Result findById(@PathVariable("id") Long id);
 }

3.如果是全局配置,则需要把config文件写在全局注解里

 @EnableFeignClients(defaultConfiguration=UserFeignConfig.class)
 public class OrderApplication(...){
    ...
 }
⭐为什么把FeignClient定义为接口而不是类:
  • Feign是一个声明式的REST客户端,可以根据接受定义来生成HTTP客户端代码,并将HTTP请求映射到接口方法上,从而实现了简易的REST调用.在feign中,需要定义一个接口来描述REST接口的URL、HTTP方法、请求参数和请求头等信息,然后使用注解来描述请求参数和返回值的格式,Feign就会根据这些信息生成HTTP客户端代码.
  • 简化客户端开发,只需要定义接口,避免手动构建HTTP请求
  • 提高代码可读性和可维护性

6.3 Feign使用优化

image-20230418220112248

步骤:

1.替换默认URLConnection,在pom中引入新的客户端依赖

 <!--代替feign默认的URLConnection,使用带有连接池的客户端-->
 <dependency>
     <groupId>io.github.openfeign</groupId>
     <artifactId>feign-httpclient</artifactId>
 </dependency>

2.配置最大连接数等信息

 spring:
  cloud:
    openfeign:
      httpclient:
      # 开启httpclient的开关,默认为true
        enabled: true
         # 最大连接数和单个路径的最大连接数,需要通过实际ya'li'v'c
        max-connections: 200
        max-connections-per-route: 50

6.4 最佳实践

1.因为服务消费者能够调用的http方法来自于服务提供者的已有方法,所以可以为消费者的FeignClient和提供者的controller定义统一的父接口

image-20230419112030304
image-20230419112004758

eg.采用方式二.

创建一个子模块feign-api,在order-service中引入子模块的dependency并使用.

bug&debug:

image-20230419160654077
image-20230419161004591

bug:使用@Autowired注解注入UserClient时报错,启动OrderApplication失败,提示userclient为空。

思路:文件中已经引入了userclient,说明spring是可以找到这个接口的,但是userclient仍然为空是因为spring并没用使用动态代理为其生成bean对象.

原因:order-service默认只扫描OrderApplication所在的包并为其生成bean对象,而userclient不在这里,故没有bean对象.

image-20230419161108895

debug:

方法一:在EnableFeignClients注解中指明FeignClient所在package 

@EnableFeignClients(basePackages = "cn.itcast.feign.clients")

方法二:在EnableFeignClients注解中指明字节码 

@EnableFeignClients(clients = {UserClient.class})

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注