9. 应用通信 RestTemplate和Feign

在这里插入图片描述

Dubbo是通过RPC来通信的,是一套很完善的服务治理框架

SpringCloud 使用HTTP Rest通信;
在这里插入图片描述

使用RestTemplate(推荐第三种):

使用的测试项目:微信点餐项目

首先我们在服务端 商品项目建立服务提供的接口,然后在订单项目中去调用;

@RestController
public class ServerController {
    @GetMapping("/msg")
    public String msg(){
        return "this is product msg";
    }

}

第一种方式:使用RestTemplate直接访问 这样的访问有个问题就是必须知道对方IP而在正式线上部署多台服务器你可能是不知道对方ip的这是第一种情况;第二种情况就是说对方也就是服务提供方做了负载均衡,应该是服务方收到一个请求后自动分配相应的服务,显然这种情况是不满足的。

	//第一种方式 直接使用RestTemplate 写死URL
	RestTemplate restTemplate=new RestTemplate();
	String response=restTemplate.getForObject("http://localhost:8080/msg",String.class);
	log.info("response:{}",response);

第二种方式:通过Spring Cloud的LoadBalancerClient 根据名称获取地址 然后在使用RestTemplate访问 这样的话是需要每次获取地址,是比较麻烦

	@Autowired
     private LoadBalancerClient loadBalancerClient;
	//第二种方式 利用LoadBalancerClient 通过应用名称获取url 使用RestTemplate 访问
    ServiceInstance instance=loadBalancerClient.choose("PRODUCT");
    String url=String.format("http://%s:%s/msg",instance.getHost(),instance.getPort());
    RestTemplate restTemplate=new RestTemplate();
    String response=restTemplate.getForObject(url,String.class);
    log.info("response:{}",response);

第三种方式:将RestTemplate作为一个Bean创建,创建时添加@LoadBalanced注解

	@Component
	public class RestTemplateConfig {
	    
	    @Bean
	    @LoadBalanced
	    public RestTemplate restTemplate(){
	        return new RestTemplate();
	    }
	}

因为已经当作Bean创建 那么可以直接注入

	@Autowired
    private RestTemplate restTemplate;

在调用时直接使用服务的名称

	//第三种 利用@LoadBalanced 可以直接在restTemplatel里直接使用应用名称
    String response=restTemplate.getForObject("http://PRODUCT/msg",String.class);
    log.info("response:{}",response);

Feign

简介

声明式REST客户端(伪RPC)
采用了基于接口的注解,本质还是http请求,内部也使用了Ribbon做负载均衡

在微服务架构中,Spring Cloud Ribbon和Spring Cldou Hystrix实现了客户端负载均衡的服务调用以及如何通过断路器来保护我们的微服务应用。这两者将被作为基础工具类框架广泛应用在各个微服务的实现中,不仅包括我们自身的业务也包括一些基础设施类服务(比如网关)。并且这两个框架是同时出现的,所以,Feign封装整合了这两个基础框架同时它还提供了一种声明式的Web服务客户端定义方式。

我们使用Spring Cloud Ribbon时,通常都会利用它对RestTemplate的 请求进行拦截 来实现对依赖服务的调用,而RestTemplate已经实现了对HTTP请求的封装处理形成了一套模板化的调用方法。之前我们只是简单的介绍了RestTemplate的调用,但是在开发中 由于对服务的依赖 调用的地方可能不止一处,往往一个接口可能被对多处调用,所以我们通常都会针对各个微服务自行封装一些客户端来包装这些依赖的服务调用。但是由于RestTemplate的封装所以会导致几乎每个调用都是简单的模块化内容。

综上所述,Spring Cloud Feign 在此基础做了进一步封装。在Spring Cloud Feign 的实现下我们只需要创建一个接口并用注解的方式配置它,即可完成对服务提供方接口的绑定,简化了Spring Cloud Ribbon时自行封装服务调用客户端的开发量。Spring Cloud Feign 具备可插拔的注解支持,包括Feign注解和JAX-RS注解。同时为了适应Spring 的用户,它在Netflix Feign的基础上扩展了对Spring MVC的注解支持,对于习惯Spring MVC的开发者来说可以减少学习成本。另外,对于Feign自身的一些主要组件,比如编码解码器,也已可插拔方式提供,在需要的时候可以替换。

使用方法

第一步:订单服务-添加Feign的jar包

<dependency>
   <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-feign</artifactId>
</dependency>

第二步:订单服务-在启动类添加注解@EnableFeignClients

第三步:订单服务-客户端创建client,其中@FeignClient(name = “product”)为服务名称,@GetMapping("/msg")为服务的某个接口地址,访问方式(get或者post),参数需要相同。@FeignClient会根据服务名创建一个同名的Ribbon客户端

@FeignClient(name = "product")
public interface ProductClient {

    @GetMapping("/msg")
    String productMst();
}

注:在使用参数绑定时,@RequestParam、@Request Header等可以指定参数名称的注解,它们的value千万不能少。在Spring MVC程序中,这些注解会根据参数名称来作为默认值,但是在Feign中绑定参数必须通过value属性来指明具体的参数名,不然会抛出IllegalStateException异常,value属性不能为空。使用@RequestBody 传对象时,这个对象必须要有默认的构造函数也就是无参构造
第四步:订单服务-在Controller中注入添加好的接口 然后调用方法

	@Autowired
    private ProductClient productClient;
    
	@GetMapping("/getProductMsg")
    public String getProductMsg(){
        String response=productClient.productMst();
        log.info("response:{}",response);
        return response;
    }

获取商品列表 在ProductClient 定义获取商品的接口

 	@PostMapping("product/listForOrder")
    List<ProductInfo> listForOrder(@RequestBody List<String> productIdList)

需要在订单服务里面添加ProductInfo类

这种方法存在的问题:
1.ProductInfo 是数据库对应的实体类,而上面将数据库映射的实体类直接暴露到外部了。
2.实体类重复定义了
3.Client 访问服务方 需要定义服务方接口的URL,如果是两组人开发 协商也是问题,解决方法应该是服务方自己定义接口然后暴露给Client

第二种方法继承特性

当使用Spring MVC的注解来绑定服务接口时,我们几乎完全可以从服务方的Controller中依靠复制操作,构建出相应的服务客户独端绑定接口。既然存在这么多复制操作,我们自然需要考虑这部分内容是否可以进一步抽象呢?在Spring Cloud Feign中 通过继承特性帮助我们解决这些复制操作,以减少代码量。

实现步骤:
1.创建服务端新的maven项目(api)。在该项目中 定义一个接口 这个接口提供客户端所使用的方法
在这里插入图片描述
2.服务端新增加对api项目的依赖
在这里插入图片描述
3然后实现controller ,该controller实现了api的接口
在这里插入图片描述
4.在客户端如同在服务端一样,新增对api的依赖
5.在客户端创建一个接口 ,并继承api的接口,然后添加@FeignClient注解来绑定服务
在这里插入图片描述
6.在客户端coltroller注入该service 然后调用服务
在这里插入图片描述
优缺点:
优点:可以将接口的定义从Controller中剥离,配合maven私有仓库可以轻易实现接口共享,实现在构建期的接口绑定,从而有效减少服务客户端的配置。
缺点:由于接口在构建期间就建立起来依赖,那么接口变动会对项目构成影响,如果服务提供方修改了一个接口定义,那么会直接导致客户端工程的构建失败。

第三种方法

1.服务端(商品服务)提供客户端(订单服务)接口
在这里插入图片描述
2.common为公用模块,修改客户端接口的出参入参,避免将数据库字段暴露
在这里插入图片描述
3.server为业务实现,修改好代码后,将项目打包安装到本地,方便客户端调用
在这里插入图片描述
4.客户端最外层pom文件 引入服务端的client模块
在这里插入图片描述
注意这个依赖并非jar包,这个是因为 Produce 服务的pom.xml文件是配置的pom不是jar:
<packaging>pom</packaging>

5.客户端要调用的项目也就是server中的pom 引入服务端client依赖
在这里插入图片描述在这里插入图片描述

6.在客户端server启动类中 添加注解,扫描服务端的client模块在这里插入图片描述
7.server 的service实现类中直接调用,注意返回值做了封装
在这里插入图片描述

全局配置和指定服务配置

由于Feign中的客户端负载均衡是通过Ribbon实现的,所以我们可以直接通过配置Ribbon客户端的方式来自定义各个服务客户端调用的参数。

全局配置:ribbon.key=value;比如修改客户端调用超时时间
ribbon.ConnectTimeout=500
ribbon.ReadTimeout=500

指定服务配置
在使用@FeignClient注解,在初始化过程中Feign会根据服务名创建一个同名的Ribbon客户端。既然如此,就可以使用@FeignClient注解中的值来设置对应的Ribbon参数,比如:
product.ribbon.ConnectTimeout=500
product.ribbon.ReadTimeout=500

区别:

使用RestTemplate时,URL参数是以编程方式构造的,数据被发送到其他服务。在更复杂的情况下,我们将不得不RestTemplate深入到更低级别的API提供的甚至是API 的细节。

Feign是Spring Cloud Netflix库,用于在基于REST的服务调用上提供更高级别的抽象。Spring Cloud Feign在声明性原则上工作。使用Feign时,我们在客户端编写声明式REST服务接口,并使用这些接口来编写客户端程序。开发人员不用担心这个接口的实现。这将在运行时由Spring动态配置。通过这种声明性的方法,开发人员不需要深入了解由HTTP提供的HTTP级别API的细节的RestTemplate。

总结

也就是说FeignClient简化了请求的编写,且通过动态负载进行选择要使用哪个服务进行消费,而这一切都由Spring动态配置实现,我们不用关心这些,只管使用方法即可。再说,就是简化了编写,RestTemplate还需要写上服务器IP这些信息等等,而FeignClient则不用。

不过话又再说回来,其实RestTemplate同样可以简化到使用FeignClient那样简单,无非就是自己封装多一层去实现而已,所以,我个人觉得没有太多绝对,只是看你的业务需求怎么定位这个选择而已。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值