Springcloud-openfeign和feign和openfeign还在傻傻分不清楚?

/ 默认分类 / 0 条评论 / 1581浏览

Springcloud-openfeign和feign和openfeign还在傻傻分不清楚?

一.前言介绍(Feign和OpenFeign和springcloud之间的关系)

关于Feign和OpenFeign这些项目他们之间的关系,我看很多文章解释的都是错的. 比如下面这些文章:
1
2 .....
这里我简单说明一下


首先OpenFeign是feign系列框架的主项目名,目前(2021/11/19)在github上作为个人项目名称,其中包含的模块有feign,feign-form 等等,只不过openfeign里面主要就是feign,其他项目只是对feign的补充拓展功能模块,具体可以参考其官方的github地址你就会明白,所以说,我们 可以认为(openfeign==feign),springcloud中的feign叫做springcloudopenfeign,这个项目是对feign的封装,或者 说是对openfeign的封装(openfeign==feign),让其融入springcloud的生态中,所以这里加入了很多 springmvc的注解,并且还加入了@FeignClient注解,使得我们不需要手动编码构造一个feign客户端然后 手动注入spring容器中,使用@FeignClient注解可以很方便的整合进spring框架,让feign可以很方便的在spring中进行开发. 关于这一点了解过单独使用feign进行开发和使用springcloudfeign进行开发的朋友应该明白.其实这个在 官方文档中写的十分清除;

下面是springcloudopenfeign官方的一段描述:

This project provides OpenFeign integrations for Spring Boot apps through autoconfiguration and binding to the Spring Environment and other Spring programming model idioms. ps:OpenFeign主要就是指feign

Feign(openfeign)官方文档
springcloudopenfeign官方文档

所以综上所述,openfeign可以认为就是feign(所以无论说openfeign还是feign都是指同一个),它是github上一个独立的优秀的远程过程调用框架(伪rpc,或者叫做 http请求调用封装,可以有效的减少程序员编写http接口调用和处理响应的环节),springcloudopenfeign是对openfeign作的 封装整合后适用于spring系列框架的远程过程调用框架,最主要的修改就是加入了@FeignClient和支持了springmvc注解来声明 客户端接口调用封装.

所以可以看出,springcloud系列的框架很多项目其实都是看github上有哪些优秀的框架,然后对其进行封装,使用动态代理 封装一个增强的实现然后注入spring中来使用,类似的还有rabbitmq和springbootrabbitmq.
好了解释完了,有不同意见的欢迎留言.

二.详细介绍

无论是openfeign还是springcloudopenfeign,对于学习这些框架的使用,个人觉得是程序员最基础的能力,很多优秀的开源框架都有 完善的使用文档,所以对于这些框架的使用,不作过多记录,都已经有了官方文档了还要个锤子哦.

1. 单独使用Feign时如何构造一个http客户端

Feign.builder()

builder之后可以为当前客户端设置一系列的属性,包括封装调用的http请求的请求头header,整合其他的一些开源 组件来添加一些功能,比如decoder和encoder编码和解码,logging日志记录组件,异常http响应捕获处理,请求 拦截器,动态参数,重试机制

        pay = Feign.builder()
                //设置数据编解码器
                .encoder(new JacksonEncoder())
                .decoder(new JacksonDecoder())
                //设置http异常响应处理器
                .errorDecoder(new MyFeignErrorDecoder(decoder))
                //日志相关设置
                .logger(new Slf4jLogger(PostPayClient.class))
                .logLevel(Logger.Level.FULL)
                //设置重试机制
                .retryer(new Retryer.Default(100, SECONDS.toMillis(1), 5))
                //设置请求拦截器
                .requestInterceptor(new MyFeignRequestInterceptor())
                //设置feign封装的调用请求使用的http客户端
                .client(new Client.Default(null,null))
                //设置http请求选项参数,比如连接超时时间,响应超时时间
                .options(new Request.Options(10, TimeUnit.SECONDS, 60, TimeUnit.SECONDS, true))
                .target(UserApi.class, url);
                
                
//定义接口方法                
public interface UserApi {

    @RequestLine(value = "GET /user/get?param={param}")
    String getUser(@Param("param") String param);

}

如果你对上面的代码有疑问,那么恭喜你,这里有非常完善的官方文档
Feign(openfeign)官方文档
springcloudopenfeign官方文档

feign自带请求重试机制,可以自定义重试策略或者使用自带的重试策略 下面就是默认的设置,后面分析源码的时候也会介绍(feign的http请求重试机制可没有那么简单,后面我有文章做了专门的分析,欢迎阅读)

  public static Builder builder() {
    return new Builder();
  }
  
  
  public static class Builder {

    private final List<RequestInterceptor> requestInterceptors =
        new ArrayList<RequestInterceptor>();
    private Logger.Level logLevel = Logger.Level.NONE;
    private Contract contract = new Contract.Default();
    private Client client = new Client.Default(null, null);
    private Retryer retryer = new Retryer.Default();
    private Logger logger = new NoOpLogger();
    private Encoder encoder = new Encoder.Default();
    private Decoder decoder = new Decoder.Default();
    private QueryMapEncoder queryMapEncoder = new QueryMapEncoder.Default();
    private ErrorDecoder errorDecoder = new ErrorDecoder.Default();
    private Options options = new Options();
    private InvocationHandlerFactory invocationHandlerFactory =
        new InvocationHandlerFactory.Default();
    private boolean decode404;
    private boolean closeAfterDecode = true;
    private ExceptionPropagationPolicy propagationPolicy = NONE;

2. 如果使用springcloudopenfeign创建http客户端

那么可以在@FeignClient注解中设置http客户端的配置类,就像这样:

@FeignClient(name="order-service",url="${order.url}", configuration = OrderFeignConfiguration.class)
public interface OrderClient {

    @RequestMapping(value="/api/v1/order/test",method= RequestMethod.GET)
    R<Order> queryOrder(@RequestParam("memberId") String id);
}
public class OrderFeignConfiguration implements RequestInterceptor {

	@Override
	public void apply(RequestTemplate requestTemplate) {
		requestTemplate.header("test", "test12");
	}

	@Bean
	Request.Options feignOptions() {
		return new Request.Options(60 * 1000, 60 * 1000);
	}

	@Bean
	Retryer feignRetryer() {
		return Retryer.NEVER_RETRY;
	}

	@Bean
	public Logger.Level feignLoggerLevel() {
		return Logger.Level.FULL;
	}

	@Bean
	FeignLoggerFactory palmpayFeignLoggerFactory() {
		return new PalmPayFeignLoggerFactory();
	}

}

上述这样的写法,可以将配置本省作为一个feign的拦截器来使用,当然你也可以在里面通过@Bean设置一些配置

三. 简单总结

前面也说过了,springcloudfeign和feign的主要区别就是springcloudfeign对feign进行了封装,并且使其支持了@FeignClient来进行http客户端注入,而不需要自己builder一个feign然后使其能够被spring扫描,并且对于请求参数的传递也可以使用springmvc的注解来使用,他们使用方法的对比上面已经列出来了,可以再去看一下.


后面我的文章会详细介绍feign的内部实现,欢迎订阅