使用Ribbon+RestTemplate来实现微服务间的调用

一、Ribbon

        Ribbon是Spring Cloud下的一个组件,是一个基于HTTP和TCP的客户端负载均衡工具,是一个负载均衡框架,是基于Netflix实现。我们可以通过Ribbon来实现服务间的调用,同时还可以实现各客户端服务间的负载均衡。

1.现有2个服务,一个为expense,另一个为payment服务,准备使用ribbon实现服务间的调用,payment服务调expense

expense服务为服务的提供方,代码如下:

 

@RestController 
@RequestMapping("/api/report") 
public class ReportController { 

 @GetMapping("/get/info/by/id") 
  public String getInfo(){
   return "success"; 
 } 
}

 

payment服务为服务的消费方:

 

@RestController 
@RequestMapping("/api/wallet") 
public class DataContoller { 
  @Autowired WalletService walletService;
    @GetMapping("/hello") public String sayHello(){ 
     return walletService.sayHello(); 
   }
 }

 

service类代码:

@Service 
public class WalletService { 

 @Autowired RestTemplate restTemplate;

 public String sayHello() { 
   String str=restTemplate.getForObject("http://localhost:9096/api/report/get/info/by/id",String.class); 
  System.out.println(str); 
  return "expense服务下的:"+str; 
 } 
}

 

可以发现:我们使用了RestTemplate 类,此处需要写一个Bean,该Bean为:

@Bean
@LoadBalanced 
RestTemplate restTemplate(){ 
  return new RestTemplate(); 
}

 

springboot启动的时候,将该Bean装载到spring容器里。

 

记一下在学习ribbon中遇到的问题:

 

 

 

 

第一次调用出现如上错误。

服务的代码为:

String str= restTemplate.getForObject("/api/report/get/info/by/id",String.class);

 

把它修改为:

 

还是出错

 

加上http,将url修改为:

String str= restTemplate.getForObject("http://expense/api/report/get/info/by/id",String.class);

再次访问:

 

调用成功!

 

接着我们去掉@LoadBalanced注解,不用@LoadBalanced注解,就可以使用使用ip地址来获取expense服务。

 

@Bean RestTemplate restTemplate(){ return new RestTemplate(); }

 

String str= restTemplate.getForObject("http://localhost:9096/api/report/get/info/by/id",String.class);

访问如下url, 同样调用成功!

这是为什么呢?

问题是: 当有@LoadBalanced注解时,RestTemplate会根据eureka服务上的应用名去寻找主机。因此调用的时候需要加上eureka上面的应用名。

 

请求的url为:

String str= restTemplate.getForObject("http://expense/api/report/get/info/by/id",String.class);

这样就能调用成功了!结果如上

2. 怎么请求带有参数的url?

比如我们要传一个id的get请求。

 

报错:

被调用方:

Resolved [org.springframework.web.bind.MissingServletRequestParameterException: Required Long parameter 'id' is not present]

调用方:

org.springframework.web.client.HttpClientErrorException$BadRequest: 400 null

 

查看源码后,发现getForObject方法的第三个参数需要传一个map,修改代码如下:

此处的RestTemplate没有加上@LoadBalanced注解,如果加的话,url的host需要修改为应用名。

package com.example.hand.wallet.service; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Service; 
import org.springframework.web.client.RestTemplate; 
import java.util.HashMap; 
import java.util.Map; 

@Service 
public class WalletService { 
  @Autowired RestTemplate restTemplate; 
  public String sayHello() { 
     Long id=1L; 
    Map<String,Integer> map=new HashMap<>();
    map.put("id",1); String str= 
  restTemplate.getForObject("http://localhost:9096/api/report/get/info/by/id?id= {id}",String.class,map); 
  System.out.println(str); 
return "expense服务下的:"+str; } }

 

再次访问:

 

看一下RestTemplate类的源码:

可以找到常用的GET请求和POST请求对应的方法:

GET请求:

 

 

 

public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables)

public <T> T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables);

public <T> T getForObject(URI url, Class<T> responseType) ;

 

POST 请求:

 

 

public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables) ;

public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables);

public <T> ResponseEntity<T> getForEntity(URI url, Class<T> responseType);

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乌托邦钢铁侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值