当前位置:   article > 正文

OpenFeign【微服务】_resttemplate feign openfeign

resttemplate feign openfeign

前言

Feign is a declarative web service client. It makes writing web service clients easier. To use Feign create an interface and annotate it. It has pluggable annotation support including Feign annotations and JAX-RS annotations. Feign also supports pluggable encoders and decoders. Spring Cloud adds support for Spring MVC annotations and for using the same HttpMessageConverters used by default in Spring Web. Spring Cloud integrates Ribbon and Eureka, as well as Spring Cloud LoadBalancer to provide a load-balanced http client when using Feign. link
Feign是一个声明式WebService客户端。使用Feign能让编写Web Service客户端更加简单。它的使用方法是定义一个服务接口然后在上面添加注解。Feign也支持可拔插式的编码器和解码器。Spring Cloud对Feign进行了封装,使其支持了Spring MVC标准注解和HttpMessageConverters。Feign可以与Eureka和Ribbon组合使用以支持负载均衡。

一、feign作用

使编写Java Http客户端变得更容易。

和httpClient一样,用于调用第三方api
Feign是一个接口声明式调用框架,实现了一个抽象层的逻辑,没有真正实现底层http请求,提供了一个client接口用于实现底层http操作,默认提供的实现是基于httpurlconnection,也有基于apachehttpclient的实现,且feign具有分布式负载均衡功能

二、feign原理

启动配置上检查是否有EnableFeignClients注解,如果有,开启包扫描,扫描Feignclient接口,扫描到后通过BeanDefinition注入到ioc容器中,方便被调用。

在FeignClientsRegister中,RegisterFeignClient完成了注册feign客户端的操作,包括注解时配置的所有信息。

ReflectiveFeign内部使用了jdk动态代理为目标接口生成动态代理类,生成了一个invocationHandler的统一方法拦截器,同时为接口的每个方法生成一个synchronousMethodHandler拦截器,并解析方法上的元数据,通过requestTemplate生成一个http请求模板

在这里插入图片描述

  • 在主程序入口类加上@EnableFeignClients 注解开启对 Feign Client 扫描加载处理,定义接口并加
    @FeignClients 注解。

  • 主程序启动时候会进行包扫描,扫描所有 @FeignClients 的注解的类,将信息注入到Spring IOC容器中,当定义的FeignClients接口被调用时候,通过JDK代理的方式,生成具体的RequestTemplate。当生成代理时,Feign会为每个接口方法创建一个 RequetTemplate 对象,该对象封装了 HTTP请求需要的全部信息,如请求参数名、请求方法等信息都是在这个过程中确定的。

  • 然后由RequestTemplate 生成Request,然后把Request交给Client处理,这里的Client可以是JDK原生的URlConnection、Apache 的httpClient 也可是okHttp。最后Client 被封装到LoadBalanceclient这个类结合 Ribbon 负载均衡发起服务之间的调用。

三、Feign 和openFeign区别

简单来说:
新增提供者API接口:feign简化了原先restTemplate+ribbon的远程调用,减少了代码量。达到远程调用微服务的一个service接口、对应的接口:类似于mybatis的mapper接口

Feign是Spring Cloud组件中的一个轻量级RESTful的HTTP服务客户端Feign内置了Ribbon,用来做客户端负载均衡,去调用服务注册中心的服务。Feign的使用方式是:使用Feign的注解定义接口,调用这个接口,就可以调用服务注册中心的服务。

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
  • 1
  • 2
  • 3
  • 4

OpenFeign是Spring Cloud在Feign的基础上支持了SpringMVC的注解,如@RequesMapping等等。**OpenFeign的@Feignclient可以解析SpringMVc的@RequestMapping注解下的接口,并通过动态代理的方式产生实现类,**实现类中做负载均衡并调用其他服务。

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
  • 1
  • 2
  • 3
  • 4

四、项目中使用案例

注册中心:Eureka 【cloud-eureka-server7001】
业务模块微服务:cloud-provider-payment8001

  1. 创建openFeign模块【cloud-consumer-feign-order80】
    在这里插入图片描述
  2. 修改POM文件,添加依赖
 <dependencies>
        <!--注册中心放到第一个,eureka 服务,用于注册中心-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--客户端使用openfeign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!--web下的两个配套-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
            <version>2.2.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

3.写yml

server:
  port: 80

eureka:
  client:
    register-with-eureka: false
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/
spring:
  application:
    name: cloud-consumer-feign-order80
  zipkin:
    base-url: http://localhost:9411
  sleuth:
    sampler:
      probability: 1
	
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

4、主启动类:OrderFeignMain80
添加@EnableFeignClients注解

@SpringBootApplication
@EnableFeignClients  //此处需要这个注解
public class OrderFeignMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderFeignMain80.class,args);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

5、写FeignClinet接口层
OpenFeign代替了Ribbon + RestTemplate的工作,即它还要承担RestTemplate,而在OpenFeign中的代替方案就是建一个接口并使用注解的方式来配置它。类似于SpringBoot项目中Dao层的工作。从其他地方查询数据。不过此处项目小故用service来代替。
在这里插入图片描述
业务逻辑接口+@FeignClient配置调用provider服务

import com.fan.springcloud.entity.CommonResult;
import com.fan.springcloud.entity.Payment;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@Component//标记成一个spring组件
@FeignClient(name = "CLOUD-PAYMENT-SERVICE") //那么name或者value的值为:服务提供方 的服务名称
//标注使用OpenFeign调用的springcloud-product-provider服务
public interface PaymentFeignService {
   //以下方法名和参数都需要和服务提供者者保持一致,@GetMapping中的就是服务提供者对应的全路径
    @GetMapping(value = "/payment/get/{id}")
    public CommonResult<Payment> getPaymentById(
            @PathVariable("id") Long id
    );
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

控制层Controller
使用FeignClients声明的接口,调用指定的微服务实现接口。

import com.lun.springcloud.entities.CommonResult;
import com.lun.springcloud.entities.Payment;
import com.lun.springcloud.service.PaymentFeignService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;

@RestController
@Slf4j
public class OrderFeignController
{
    @Resource
    private PaymentFeignService paymentFeignService;

    @GetMapping(value = "/consumer/payment/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id)
    {
        return paymentFeignService.getPaymentById(id);
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

参考资料:

https://blog.csdn.net/a617332635/article/details/114656454
https://zhuanlan.zhihu.com/p/269208311
https://blog.csdn.net/u011863024/article/details/114298270
https://blog.csdn.net/wo18237095579/article/details/83343915

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/428863
推荐阅读
相关标签
  

闽ICP备14008679号