SpringBoot26 利用 Ribbon + RestTemplate 调用远程服务资源

 

1 RestTemplate扫盲

  借助 RestTemplate,Spring应用能够方便地使用REST资源   

 

2 准备

  创建三个springCloud项目

    》Eureaka : 服务注册中心

    》Product 商品服务

    》Order 订单服务

  技巧01:Eureaka 项目需要引入 spring-cloud-starter-netflix-eureka-server 依赖;其余两个项目需要引入 spring-cloud-starter-netflix-eureka-client 依赖

  技巧02:order 服务需要调用 product 项目中的资源数据【请求url为:http://127.0.0.1:8080/msg】,我们可以利用  RestTemplate 来实现

  坑01:所有的 springCloud项目中设置  eureka.instance.hostname 配置时需要注意,因为这个配置必须是IP地址或者域名;因为利用LoadBalancerClient根据应用名获取到的数据就是这个配置

  坑02:直接利用RestTemplate实现时是古老的方式实现,而且如果远程服务是集群部署时需要自己实现负载均衡的逻辑

 

3 RestTemplate的三种使用方式

  3.1 直接将url写死

    》创建 RestTemplate 实例 restTemplate

    》调用 restTemplate  的 getForObject 方法获取数据

    技巧01:getForObject 第一个参数接受一个string类型的url,例如:http://127.0.0.1:8080/msg;第二个参数指定响应数据类型

    技巧02:这是古老的方式实现,需要自己实现负载均衡和远程服务的信息配置

RestTemplate restTemplate = new RestTemplate();
        String response = restTemplate.getForObject("http://127.0.0.1:8080/msg", String.class);
View Code

  3.2 利用 LoadBalancerClient 获取引用IP和应用端口

    技巧02:利用ribbon获取远程服务信息,而且ribbon还实现了负载均衡功能

    》依赖注入 LoadBalancerClient  实例 loadBalancerClient

    @Autowired
    private LoadBalancerClient loadBalancerClient;
View Code

    》调用 loadBalancerClient   的  choose 方法获取应用服务实例 serviceInstance

    》调用 serviceInstance 的 getHost 方法获取应用服务IP

      【技巧01:如果应用服务设置了eureka.instance.hostname,那么getHost 方法返回就是eureka.instance.hostname的配置值】

    》调用 serviceInstance 的 getPort 方法获取应用服务端口

    》将获取到的IP和端口以及请求路径拼接成请求资源的url即可,例如:http://127.0.0.1:8080/msg

    》在调用 RestTemplate 实例的 getForObject  方法

  3.3 通过配置实现

    利用了@LoadBalanced,可以在restTemplate中使用应用名

    》创建一个配置类

package cn.xiangxu.order.config;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

/**
 * @author 王杨帅
 * @create 2018-07-24 21:37
 * @desc RestConfig配置类
 **/
@Component
public class RestTemplateConfig {

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

}
View Code

    》依赖注入 RestTemplate 实例 restTemplate

    @Autowired
    private RestTemplate restTemplate;
View Code

    》调用 restTemplate  的 getForObject 方法获取数据

      【技巧01:这时候可以直接利用应用服务名称来代替应用IP和应用端口信息,例如:"http://PRODUCT/msg"】

  3.4 代码汇总

package cn.xiangxu.product.controller;

import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Select;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author 王杨帅
 * @create 2018-07-24 20:45
 * @desc 服务端控制层
 **/
@RestController
@Slf4j
public class ServerController {

    @GetMapping(value = "/msg")
    public String msg() {
        String result = "商品微服务中的信息";
        log.info(result);
        return result;
    }

}
服务提供者
package cn.xiangxu.order.config;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

/**
 * @author 王杨帅
 * @create 2018-07-24 21:37
 * @desc RestConfig配置类
 **/
@Component
public class RestTemplateConfig {

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

}
服务调用者配置类
package cn.xiangxu.order.controller;

import cn.xiangxu.order.config.RestTemplateConfig;
import com.netflix.discovery.converters.Auto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * @author 王杨帅
 * @create 2018-07-24 20:51
 * @desc 客户端控制层
 **/
@RestController
@Slf4j
public class ClientController {

//    @Autowired
//    private LoadBalancerClient loadBalancerClient;

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/getProductMsg")
    public String getProductMsg() {
        // 方式01 直接将url写死
//        RestTemplate restTemplate = new RestTemplate();
//        String response = restTemplate.getForObject("http://127.0.0.1:8080/msg", String.class);

        // 方式02:利用LoadBalancerClient获取应用名(IP)和端口,在组装成url
//        RestTemplate restTemplate = new RestTemplate();
//        ServiceInstance serviceInstance = loadBalancerClient.choose("PRODUCT");
//        log.info(serviceInstance.getHost());
//        log.info(serviceInstance.getPort() + "");
//        String url = String.format("http://%s:%s", serviceInstance.getHost(), serviceInstance.getPort() + "/msg");
//        String response = restTemplate.getForObject(url, String.class);

        // 方式03:通过配置实现,利用了@LoadBalanced,可以在restTemplate中使用应用名
        String response = restTemplate.getForObject("http://PRODUCT/msg", String.class);

        log.info(response);
        return response;
//        return null;
    }

}
服务调用者

 

  

  

posted @ 2018-07-24 22:26  寻渝记  阅读(858)  评论(0编辑  收藏  举报