一. 什麼是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做者:白駒過隙_突然而已
3、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 {/** 一、自旋,CAS進行獲取,請求的次數* 二、請求的次數 % 根據服務的個數= 求餘數,獲取輪詢的服務的內容serviceInstance* */ServiceInstance instance(List<ServiceInstance> serviceInstanceList);}/*** @introduce: 輪詢* @author: xingMeiLing* @DATE: 2020/6/29**/@Componentpublic class MyLB implements LoadBalancer {/** 一、請求的次數 % 根據服務的個數= 求餘數,獲取輪詢的服務的內容serviceInstance* 二、自旋,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);}