Openfeign入门使用教程

一、OpenFeign简介

概述:feign是一个声明式的http客户端其作用就是帮助我们优雅的实现http请求的发送。官方地址

二、 入门使用

1、 在消费者的一方引入依赖

<!-- 加入OpenFeign的依赖 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2、在启动类上添加**@EnableFeignClients**开启OpenFeign的功能支持

3、编写OpenFeign的客户端

@FeignClient(value="spzx-cloud-user")  
//	spzx-cloud-user 是服务的名称,它是注册在服务注册中心(我用的是Nacos)  其余的例如 Eureka 或 Consul中的服务名。Feign 会使用该服务名来进行服务发现和路由
//一个属性value可以省略
public interface UserFeignClient {
    
    

    @GetMapping("/api/user/selectByUserId/{userId}")
    User selectById(@PathVariable Long userId);
}

在这里插入图片描述
这个客户端主要是基于SpringMVC的注解来声明远程调用的信息,比如:
① 请求方式:GET

② 请求路径:/api/user/selectByOrderId/{userId}

③ 请求参数:Long userId

④ 返回值类型:User

这样,Feign就可以帮助我们发送http请求,无需自己使用RestTemplate来发送了。

@Service
public class OrderServiceImpl implements OrderService {
    
    
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private UserFeignClient userFeignClient;
    //使用feign 可以更简便的发请求, 代替restTemplate

    @Override
    public Order selectByOrderId(Long orderId) {
    
    
        // 根据orderId查询订单信息
        Order order = orderMapper.selectByOrderId(orderId);
        // 发送请求, 请求user微服务模块
        User user = userFeignClient.selectById(order.getUserId());
        order.setUser(user);
        return order;
    }
}

#OpenFeign自定义配置

日志配置

OpenFeign可以支持很多的自定义配置,如下表所示:

类型 作用 说明
feign.Logger.Level 修改日志级别 包含四种不同的级别:NONE、BASIC、HEADERS、FULL
feign.codec.Decoder 响应结果的解析器 http远程调用的结果做解析,例如解析json字符串为java对象
feign.codec.Encoder 请求参数编码 将请求参数编码,便于通过http请求发送
feign.Contract 支持的注解格式 默认是SpringMVC的注解
feign.Retryer 失败重试机制 请求失败的重试机制,默认是没有,不过会使用Ribbon的重试

一般情况下,默认值就能满足我们使用,如果要自定义时,只需要创建自定义的@Bean覆盖默认Bean即可。

下面以日志为例来演示如何自定义配置,支持两种方式的配置:

基于配置文件的方式

基于配置文件修改feign的日志级别可以针对单个服务:

# 将feign包下产生的日志的级别设置为debug
#  spring的日志级别方是info
#  ERROR > WARN > INFO > DEBUG > TRACE  设置的级别只有比当前级别更高才会输出
logging:
  level:
    com.chen.spzx.cloud.order.feign: debug

也可以针对所有服务:

# openfeign日志级别配置
spring:
  cloud:
    openfeign:
      client:
        config: 
          default:  # 这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置
            loggerLevel: full

而日志的级别分为四种:

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

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

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

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

-------上面是一组方式, 下面是一组方式---------

Java代码的方式

也可以基于Java代码来修改日志级别,先声明一个类,然后声明一个Logger.Level的对象:

@Configuration
public class DefaultFeignConfiguration  {
    
    
    @Bean
    public Logger.Level feignLogLevel(){
    
    
        return Logger.Level.BASIC; // 日志级别为BASIC
    }
}

如果要全局生效,将其放到启动类的@EnableFeignClients这个注解中:

@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration .class) 

如果是局部生效,则把它放到对应的@FeignClient这个注解中:

@FeignClient(value = "spzx-cloud-user", configuration = DefaultFeignConfiguration .class)  //用的是 configuration 这个属性

注意需要指定feign包的配置

logging:
  level:
    com.atguigu.spzx.cloud.order.client: debug

feign所在的包:com.atguigu.spzx.cloud.order.client

原因:# 因为feign调试日志是debug级别输出,springboot默认的日志级别是info,所以feign的debug日志级别就不会输出
  # logging.level=debug这样配置是对所有的日志级别进行配置
  # 该场景只需要对feign接口进行debug配置,所以是这样配置logging.level.com.atguigu.spzx.cloud.order.client=debug

超时配置

超时机制概述:Feign 的超时机制是指在使用 Feign 进行服务间的 HTTP 调用时,设置请求的超时时间。当请求超过设定的超时时间后,Feign 将会中断该请求并抛出相应的异常。

spring:
  cloud:
    openfeign:
      client:
        config:
          default:
            loggerLevel: full	
            read-timeout: 2000			# 读取数据的超时时间设置为2s
            connect-timeout: 2000		# 简历连接的超时时间设置为2s

重试配置

feign一旦请求超时了,那么此时就会直接抛出SocketTimeoutException: Read timed out的异常。请求超时的原因有很多种,如网络抖动、服务不可用等。如果由于网络暂时不可用导致触发了超时机制,那么此时直接返回异常信息就并不是特别的合理,尤其针对查询请求,肯定希望得到一个结果。合理的做法:触发超时以后,让feign进行重试

1、自定义重试器

public class FeignClientRetryer implements Retryer {
    
    

    // 定义两个成员变量来决定重试次数
    private int start = 1 ;
    private int end = 3 ;

    @Override
    public void continueOrPropagate(RetryableException e) {
    
         // 是否需要进行重试取决于该方法是否抛出异常,如果抛出异常重试结束
        if(start >= end) {
    
    
            throw new RuntimeException(e) ;
        }
        start++ ;
    }

    @Override
    public Retryer clone() {
    
        // 框架底层调用该方法得到一个重试器
        return new FeignClientRetryer();
    }
}

2、配置重试器

spring:
  cloud:
    openfeign:
      client:
        config:
          default:
            loggerLevel: full
            read-timeout: 2000
            connect-timeout: 2000
            retryer:  这里写类的全限定名	# 配置自定义重试器

三、 开发中把openFeign抽取出来当一个单独的模块

通过将 OpenFeign 抽取成独立模块,可以使系统更加清晰、灵活、易于维护,同时也提高了代码复用性和测试的便利性。这种做法在微服务架构中尤其重要,因为微服务之间的调用复杂且多样化,统一管理和解耦能大大简化系统的复杂性。

新建一个module, 这个module 中写的是Feign的配置和接口. 使用的时候让消费者依赖这个模块 并且消费者还需要在启动类配置包扫描, 确定能够扫到.

@EnableFeignClients(basePackages = {
    
     //扫描指定包及其子包
        "com.chen.spzx.cloud.feign"
})

在这里插入图片描述

代码只是做了迁移, 写到了单独的模块, 内容都一样. 这里不重复粘贴了