一. 什么是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";@Resourcepublic 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层的类
@Configurationpublic class ApplicationContextConfig {@Bean@LoadBalancedpublic 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**/@Componentpublic class MyLB implements LoadBalancer {/** 1、请求的次数 % 根据服务的个数= 求余数,获取轮询的服务的内容serviceInstance* 2、自旋,CAS进行获取,请求的次数* */// 用原子数据类型;初始化0private AtomicInteger atomicInteger = new AtomicInteger(0);/*** 请求的次数 % 根据服务的个数= 求余数 0 或 1** @author xingMeiLing* @param serviceInstanceList 获取轮询的服务的内容serviceInstance* @return*/@Overridepublic 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类:
@Resourcepublic RestTemplate restTemplate;@Resourceprivate DiscoveryClient discoveryClient;@Resourceprivate 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);}