当前位置: 代码迷 >> 综合 >> RestTemplate--SpringCloud 二:
  详细解决方案

RestTemplate--SpringCloud 二:

热度:31   发布时间:2024-02-08 22:41:17.0

一. 什么是RestTemplate

优雅的HTTP请求:
传统情况下在java代码里访问restful服务,一般使用Apache的HttpClient。不过此种方法使用起来太过繁琐。
spring提供了一种简单便捷的模板类来进行操作,这就是RestTemplate。

二.一个简单的例子。

定义一个简单的restful接口
@RestControllerpublic class TestController
{
    @RequestMapping(value = "testPost", method = RequestMethod.POST)
    public ResponseBean testPost(@RequestBody RequestBean requestBean)
    {
        ResponseBean responseBean = new ResponseBean();
        responseBean.setRetCode("0000");
        responseBean.setRetMsg("succ");
        return responseBean;
    }}
 
使用RestTemplate访问该服务
//请求地址
        String url = "http://localhost:8080/testPost";
        //入参
        RequestBean requestBean = new RequestBean();
        requestBean.setTest1("1");
        requestBean.setTest2("2");
        requestBean.setTest3("3");
        RestTemplate restTemplate = new RestTemplate();
        ResponseBean responseBean = restTemplate.postForObject(url, requestBean, ResponseBean.class);
 
 
从这个例子可以看出,使用restTemplate访问restful接口非常的 简单粗暴无脑。(url, requestMap, ResponseBean.class)这三个参数分别代表 请求地址、请求参数、HTTP响应转换被转换成的对象类型。
RestTemplate方法的名称遵循命名约定,第一部分指出正在调用什么HTTP方法,第二部分指示返回的内容。本例中调用了restTemplate.postForObject方法,post指调用了HTTP的post方法,Object指将HTTP响应转换为您选择的 对象类型。还有其他很多类似的方法,有兴趣的同学可以参考官方api。
以上demo作者:白驹过隙_忽然而已
链接:https://www.jianshu.com/p/90ec27b3b518
 

三、SpringCloud中RestTemplate的用法:

 
继续上篇:Eureka
 
现有两个服务提供端:8001;8002 ,服务名字都是CLOUD_PAYMENT_SERVICE
服务调用端在调用的时候,需要进行负载均衡,通过轮询,随机等方式对服务提供方进行调用
80Controller层
 
// 直接服务提供方的服务的名字
public static final String PAY_URL="http://CLOUD-PAYMENT-SERVICE";
@Resource
public RestTemplate restTemplate;
 
 
@GetMapping("/consumer/payment/get/{id}")
public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id){
    return restTemplate.getForObject(PAY_URL+"/payment/get/"+id,CommonResult.class);
}
PS:下段代码需要参考Springbean注入、配置方式
工具类: RestTemplate定义为bean;这样在@Resource的时候才能注入Controller层的类
@Configuration
public class ApplicationContextConfig {
    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate(){
      return  new RestTemplate();
    }
}
SpringCloud-common包提供的注解 : @LoadBalanced 可以实现轮序调用不同的服务提供服务
模拟轮询的底层实现:
通过原子类+CAS实现
public interface LoadBalancer {
    /*
     * 1、自旋,CAS进行获取,请求的次数
    * 2、请求的次数 % 根据服务的个数= 求余数,获取轮询的服务的内容serviceInstance
    * */
 
   ServiceInstance instance(List<ServiceInstance> serviceInstanceList);
 
 
}
/**
* @introduce: 轮询
* @author: xingMeiLing
* @DATE: 2020/6/29
**/
@Component
public class MyLB implements LoadBalancer {
/*
* 1、请求的次数 % 根据服务的个数= 求余数,获取轮询的服务的内容serviceInstance
* 2、自旋,CAS进行获取,请求的次数
* */
 
// 用原子数据类型;初始化0
private AtomicInteger atomicInteger = new AtomicInteger(0);
 
 
/**
* 请求的次数 % 根据服务的个数= 求余数 0 或 1
*
* @author xingMeiLing
* @param serviceInstanceList 获取轮询的服务的内容serviceInstance
* @return
*/
@Override
public ServiceInstance instance(List<ServiceInstance> serviceInstanceList) {
int index = this.getAndInCrement() % serviceInstanceList.size();
return serviceInstanceList.get(index);
}
/**
* 自旋,CAS进行获取,请求的次数
*
* @author xingMeiLing
* @return next 请求的次数
*/
public final int getAndInCrement(){
int current;
int next;
do{
current = this. atomicInteger.get();
next = current >= 2147483647 ? 0: current +1;
}while (!this.atomicInteger.compareAndSet(current,next));
System.out.println("次数" + next);
return next;
}
}
 
80主启动类上:
@SpringBootApplication
@EnableEurekaClient
@RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration = MySelfRule.class)
public class OrderMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderMain80.class,args);
    }
}
RibbonClient注解是Eureka实现的
服务发现的注解@EnableDiscoverClient (在启动类上配置)
80Controller类:
@Resource
public RestTemplate restTemplate;
@Resource
private DiscoveryClient discoveryClient;
@Resource
private LoadBalancer loadBalancer;
@GetMapping("/consumer/payment/lb")
public String getPaymentLB(){
      //  获取服务提供方;服务发现类: DiscoveryClient 是springcloud-common包下的用来查询服务的类
    List<ServiceInstance> serviceInstances  = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
    if(serviceInstances == null || serviceInstances.size() <=0){
        return null;
    }
    ServiceInstance serviceInstance = loadBalancer.instance(serviceInstances);
    URI uri = serviceInstance.getUri();
    return restTemplate.getForObject(uri+"/payment/lb",String.class);
}
 
  相关解决方案