客戶端負(fù)載均衡:Spring Cloud Ribbon
Spring Cloud Ribbon是一個(gè)基于HTTP和TCP的客戶端負(fù)載均衡工具磁餐,它基于Netfilx Ribbon實(shí)現(xiàn)梳凛。通過(guò)Spring Cloud封裝,可以輕松地將面向服務(wù)的Rest模版請(qǐng)求自動(dòng)轉(zhuǎn)換為客戶端負(fù)載均衡的服務(wù)調(diào)用踏枣。
Spring cloud Ribbon雖然只是一個(gè)工具類框架,它不像服務(wù)注冊(cè)中心,配置中心责静,api網(wǎng)關(guān)那樣需要獨(dú)立部署墨缘,但是它幾乎存在于每一個(gè)Spring cloud構(gòu)建的微服務(wù)和基礎(chǔ)設(shè)施中星虹。因?yàn)槲⒎?wù)間的調(diào)用,API網(wǎng)關(guān)的請(qǐng)求轉(zhuǎn)發(fā)等內(nèi)容镊讼,實(shí)際上都是通過(guò)Ribbon來(lái)實(shí)現(xiàn)的宽涌,包括Feign也是基于Ribbon實(shí)現(xiàn)的工具。
客戶端負(fù)載均衡
負(fù)載均衡是對(duì)系統(tǒng)的高可用蝶棋,網(wǎng)絡(luò)壓力的緩解和處理能力擴(kuò)容的重要手段之一卸亮。我們通常所說(shuō)的負(fù)載均衡指的是服務(wù)端的負(fù)載均衡,其中分為硬件負(fù)載均衡和軟件負(fù)載均衡玩裙,硬件負(fù)載均衡主要通過(guò)在服務(wù)節(jié)點(diǎn)之間安裝專門的負(fù)載均衡設(shè)備兼贸,比如F5段直,而軟件的負(fù)載均衡則是通過(guò)在服務(wù)端安裝一些具有均衡負(fù)載功能或者模塊的軟件來(lái)完成請(qǐng)求的分發(fā)工作,比如Nginx溶诞。
硬件負(fù)載均衡的設(shè)備或是軟件負(fù)載均衡的軟件模塊都會(huì)維護(hù)一個(gè)下掛可用的服務(wù)端清單鸯檬,通過(guò)心跳檢測(cè)來(lái)剔除故障的服務(wù)端節(jié)點(diǎn)以保證清單中都是可以正常訪問(wèn)的服務(wù)端節(jié)點(diǎn)。當(dāng)客戶端發(fā)送請(qǐng)求到負(fù)載均衡設(shè)備的時(shí)候螺垢,該設(shè)備按某種算法(比如線性輪詢喧务,按權(quán)重負(fù)載,按流量負(fù)載等)從維護(hù)的可用服務(wù)清單中取出一臺(tái)服務(wù)端的地址甩苛,然后進(jìn)行轉(zhuǎn)發(fā)蹂楣。
客戶端負(fù)載均衡和服務(wù)端的負(fù)載均衡最大的不同點(diǎn)在于服務(wù)清單存儲(chǔ)的位置⊙镀眩客戶端負(fù)載均衡痊土,所有的客戶端節(jié)點(diǎn)都維護(hù)著自己要訪問(wèn)的服務(wù)端清單,這些清單來(lái)自于服務(wù)注冊(cè)中心墨林×拊停客戶端負(fù)載均衡也需要心跳去維護(hù)服務(wù)端清單的健康性,這個(gè)步驟需要配合注冊(cè)中心去完成旭等。在spring cloud 實(shí)現(xiàn)的服務(wù)治理框架中酌呆,默認(rèn)會(huì)創(chuàng)建對(duì)各個(gè)服務(wù)治理框架的Ribbon自動(dòng)化整合配置,比如Eureka中的org.springframework.cloud.netflix.ribbon.eureka.RibbonEurekaAutoConfiguration
搔耕,Consul中的org.springframework.cloud.consul.discovery.RibbonConsulAutoConfiguration
隙袁。在實(shí)際使用的時(shí)候,可以通過(guò)查看這兩個(gè)類的實(shí)現(xiàn)弃榨,以找到它們的配置詳情來(lái)幫助我們更好的使用它菩收。
通過(guò)spring cloud Ribbon
的封裝,客戶端的負(fù)載均衡只要完成以下二步:
- 服務(wù)提供者只需要啟動(dòng)多個(gè)服務(wù)實(shí)例并注冊(cè)到注冊(cè)中心
- 服務(wù)端直接通過(guò)在
RestTemplate
上使用@LoadBalanced
注解鲸睛。
RestTemplate類使用
官網(wǎng)對(duì)這個(gè)類的介紹:
Spring's central class for synchronous client-side HTTP access.It simplifies communication with HTTP servers, and enforces RESTful principles.It handles HTTP connections, leaving application code to provide URLs (with possible template variables) and extract results.
Spring
為了簡(jiǎn)化客戶端的Http訪問(wèn)的核心類娜饵。它簡(jiǎn)化了與Http服務(wù)端的通信,并且遵循了RESTful的原則官辈。處理了HTTP的連接箱舞,使得應(yīng)用簡(jiǎn)單的運(yùn)用提供的URLs(提供的模版參數(shù))運(yùn)行得到結(jié)果。
Note: by default the RestTemplate relies on standard JDK facilities to establish HTTP connections. You can switch to use a different HTTP library such as Apache HttpComponents, Netty, and OkHttp through the setRequestFactory
property.
注意:默認(rèn)情況下拳亿,RestTemplate類依賴默認(rèn)的JDK以便建立HTTP連接晴股。可以使用不同的HTTP庫(kù)肺魁,比如Apache HttpComponents队魏,Netty,OkHttp.
The main entry points of this template are the methods named after the six main HTTP methods:
這個(gè)模版主要有六種HTTP方法:
HTTP method RestTemplate methods:
DELETE: delete
GET: getForObject,getForEntity
HEAD: headForHeaders
OPTIONS: optionsForAllow
POST: postForLocation,postForObject
PUT: put
any:exchange,execute
In addition the exchange
and execute
methods are generalized versions of the above methods and can be used to support additional, less frequent combinations (e.g.HTTP PATCH, HTTP PUT with response body, etc.). Note however that the underlying HTTP library used must also support the desired combination.
此外万搔,exchange
和execute
方法支持附加的需求胡桨,較不頻繁的結(jié)合(egHTTP PATCH,具有響應(yīng)體等HTTP PUT等等)瞬雹。然而昧谊,注意,所用的底層HTTP庫(kù)必須也支持這些期望的結(jié)合酗捌。
For each HTTP method there are three variants: two accept a URI template string and URI variables (array or map) while a third accepts a URI
.
對(duì)于每一種HTTP方法都有三種重載的方法呢诬,一種是接收String模版的參數(shù),一種是接收(數(shù)組或者map)的URI類型胖缤,一種是接收URI尚镰。下面的講解會(huì)有說(shuō)明
Internally the template uses HttpMessageConverter
instances to convert HTTP messages to and from POJOs. Converters for the main mime types are registered by default but you can also register additional converters via setMessageConverters
.
template的內(nèi)部使用HttpMessageConverter
類的實(shí)例將HTTP消息的類型轉(zhuǎn)換成POJOs類型。一些默認(rèn)的轉(zhuǎn)換已經(jīng)被注冊(cè)支持并且你可以注冊(cè)額外的轉(zhuǎn)換器通過(guò)setMessageConverters
方法哪廓。
This template uses a org.springframework.http.client.SimpleClientHttpRequestFactory
and a DefaultResponseErrorHandler
as default strategies for creating HTTP connections or handling HTTP errors, respectively. These defaults can be overridden through setRequestFactory
and setErrorHandler
respectively.
這個(gè)template使用org.springframework.http.client.SimpleClientHttpRequestFactory
和DefaultResponseErrorHandler
作為其默認(rèn)策略去創(chuàng)建HTTP連接和處理HTTP錯(cuò)誤狗唉。這些默認(rèn)的策略可以分別被重寫通過(guò)setRequestFactory
和setErrorHandler
方法
Get請(qǐng)求
使用RestTemplate,對(duì)get請(qǐng)求可以通過(guò)如下下面的二種方法實(shí)現(xiàn):
getForEntity函數(shù)
該方法返回ResponseEntity涡真,該對(duì)象是Spring對(duì)Http請(qǐng)求響應(yīng)的封裝分俯,其中主要存儲(chǔ)了HTTP的幾個(gè)重要元素,比如說(shuō)HTTP請(qǐng)求碼的枚舉對(duì)象HttpStatus(404哆料,405缸剪,500等錯(cuò)誤碼),它的父類事HttpEntity中還存儲(chǔ)著HTTP請(qǐng)求的頭信息對(duì)象HttpHeaders以及泛型類型的請(qǐng)求體對(duì)象东亦。
getForEntity有三種重載的方法:
@Override
public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables)
throws RestClientException {
RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
return execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables);
}
該方法提供了三個(gè)參數(shù)杏节,url就是請(qǐng)求的地址,responseType返回的數(shù)據(jù)類型典阵,uriVariables為url中參數(shù)綁定奋渔。會(huì)順序?qū)?yīng)url中占位符定義的數(shù)字順序。
@Override
public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables)
throws RestClientException {
RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
return execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables);
}
url參數(shù)和responseType和上面一致萄喳,只有第三個(gè)參數(shù)uriVariables是不同的類型卒稳,這里使用了Map<String, ?>類型,所以使用該方法進(jìn)行參數(shù)綁定時(shí)需要在占位符中指定Map中參數(shù)的key值他巨,我們需要向map中put
一個(gè)key為id和name的值來(lái)對(duì)應(yīng){id}和{name}
@Override
public <T> ResponseEntity<T> getForEntity(URI url, Class<T> responseType) throws RestClientException {
RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
return execute(url, HttpMethod.GET, requestCallback, responseExtractor);
}
該方法使用URI對(duì)象來(lái)替代之前的url和urlVariables參數(shù)來(lái)指定訪問(wèn)地址和參數(shù)來(lái)指定訪問(wèn)地址和參數(shù)綁定充坑。URI是JDK java.net包下的一個(gè)類,它表示一個(gè)統(tǒng)一的資源標(biāo)識(shí)符引用.
demo如下染突,定義二個(gè)項(xiàng)目捻爷,一個(gè)User項(xiàng)目,一個(gè)Order項(xiàng)目份企,User項(xiàng)目使用localhost:8080來(lái)訪問(wèn)也榄,Order項(xiàng)目使用localhost:9090來(lái)訪問(wèn),
返回對(duì)象是String:
User項(xiàng)目定義一個(gè)get方法:
@GetMapping("/getNameById")
public String getNameById(@RequestParam int id,@RequestParam String name){
if(1 == id && "zhihao.miao".equals(name)){
return "name="+name+",age="+27;
}else {
return "name="+name;
}
}
訪問(wèn):
http://localhost:8080/getNameById?id=1&name=zhihao.miao
Order中使用RestTemplate進(jìn)行調(diào)用:
@GetMapping("/getNameById")
public String getNameById(@RequestParam int id,@RequestParam String name){
String username = restTemplate.getForEntity("http://localhost:8080/getNameById?id={1}&name={2}",String.class,new Object[]{id,name}).getBody();
logger.info(username);
return username;
}
http://localhost:9090/getNameById?id=1&name=zhihao.miao
返回參數(shù)是一個(gè)實(shí)體對(duì)象:
Use項(xiàng)目中定義:
@GetMapping("/getUserById")
public User getUserById(@RequestParam int id,@RequestParam String name){
User user = new User();
if(id == 1 && "zhihao.miao".equals(name)){
user.setId(1);
user.setUsername("zhihao.miao");
user.setAge(27);
}
if(id ==2 && "zhangsan".equals(name)){
user.setId(2);
user.setUsername("zhangsan");
user.setAge(24);
}
return user;
}
訪問(wèn):
http://localhost:8080/getUserById?id=2&name=zhangsan
Order服務(wù):
@GetMapping("/getUserById")
public User getUserById(@RequestParam int id,@RequestParam String name){
Map<String,Object> params = new HashMap<>();
params.put("id",id);
params.put("name",name);
User user = restTemplate.getForEntity("http://localhost:8080/getUserById?id={id}&name={name}",User.class,params).getBody();
return user;
}
訪問(wèn):
http://localhost:9090/getUserById?id=1&name=zhihao.miao
使用URI類:
User服務(wù)定義一接口:
@GetMapping("/getUserByname")
public String getUserByname(@RequestParam String name){
if("zhihao.miao".equals(name)){
return "嗯嗯";
}else{
return "哈哈";
}
}
http://localhost:8080/getUserByname?name=zhihao.miao
Order中調(diào)用:
@GetMapping("/getUserByname")
public String getUserByname(@RequestParam String name){
UriComponents uriComponents = UriComponentsBuilder.fromUriString("http://localhost:8080/getUserByname?name={name}").build().expand(name).encode();
URI uri = uriComponents.toUri();
String response = restTemplate.getForEntity(uri,String.class).getBody();
return response;
}
http://localhost:9090/getUserByname?name=chenlong
getForObject函數(shù)
該方法可以理解對(duì)getForEntity的進(jìn)一步封裝,它通過(guò)HttpMessageConverterExtractor對(duì)http的請(qǐng)求響應(yīng)體body內(nèi)容進(jìn)行對(duì)象轉(zhuǎn)換甜紫,實(shí)現(xiàn)請(qǐng)求直接返回包裝好的對(duì)象內(nèi)容降宅。
@Override
public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables) throws RestClientException {
RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
HttpMessageConverterExtractor<T> responseExtractor =
new HttpMessageConverterExtractor<T>(responseType, getMessageConverters(), logger);
return execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables);
}
@Override
public <T> T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException {
RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
HttpMessageConverterExtractor<T> responseExtractor =
new HttpMessageConverterExtractor<T>(responseType, getMessageConverters(), logger);
return execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables);
}
@Override
public <T> T getForObject(URI url, Class<T> responseType) throws RestClientException {
RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
HttpMessageConverterExtractor<T> responseExtractor =
new HttpMessageConverterExtractor<T>(responseType, getMessageConverters(), logger);
return execute(url, HttpMethod.GET, requestCallback, responseExtractor);
}
demo如下:
User項(xiàng)目定義一接口:
@GetMapping("/getNameById")
public String getNameById(@RequestParam int id,@RequestParam String name){
if(1 == id && "zhihao.miao".equals(name)){
return "name="+name+",age="+27;
}else {
return "name="+name;
}
}
訪問(wèn):
http://localhost:8080/getNameById?id=1&name=zhihao.miao
Order項(xiàng)目中實(shí)現(xiàn):
@Autowired
private RestTemplate restTemplate;
@GetMapping("/getNameById2")
public String getNameById(@RequestParam int id, @RequestParam String name){
String username = restTemplate.getForObject("http://localhost:8080/getNameById?id={1}&name={2}",String.class,new Object[]{id,name});
logger.info(username);
return username;
}
http://localhost:9090/getNameById2?id=1&name=zhihao.miao
Order類中實(shí)現(xiàn):
@GetMapping("/getUserById2")
public User getUserById(@RequestParam int id, @RequestParam String name){
Map<String,Object> params = new HashMap<>();
params.put("id",id);
params.put("name",name);
User user = restTemplate.getForObject("http://localhost:8080/getUserById?id={id}&name={name}",User.class,params);
return user;
}
訪問(wèn):
http://localhost:9090/getUserById2?id=1&name=zhihao.miao
@GetMapping("/getUserByname2")
public String getUserByname(@RequestParam String name){
UriComponents uriComponents = UriComponentsBuilder.fromUriString("http://localhost:8080/getUserByname?name={name}").build().expand(name).encode();
URI uri = uriComponents.toUri();
String response = restTemplate.getForObject(uri,String.class);
return response;
}
http://localhost:9090/getUserByname2?name=chenlong
post請(qǐng)求
在RestTemplate中,對(duì)post請(qǐng)求時(shí)可以通過(guò)如下三個(gè)方法進(jìn)行調(diào)用實(shí)現(xiàn):
第一種:postForEntity函數(shù)
其包含三種重載的方法囚霸。第一個(gè)重載方法和第二個(gè)重載函數(shù)的uriVariables參數(shù)都用來(lái)對(duì)url中的參數(shù)進(jìn)行綁定使用腰根,responseType是返回對(duì)象的類型定義。增加的request參數(shù)拓型,該參數(shù)可以是一個(gè)普通對(duì)象额嘿,也可以是一個(gè)HttpEntity對(duì)象。如果是一個(gè)普通對(duì)象劣挫,而非HttpEntity對(duì)象的時(shí)候册养,RestTemplate會(huì)將普通對(duì)象轉(zhuǎn)換成HttpEntity對(duì)象。其中Object中不僅包含了body內(nèi)容压固,也包含了header的內(nèi)容球拦。
@Override
public <T> ResponseEntity<T> postForEntity(String url, Object request, Class<T> responseType, Object... uriVariables)
throws RestClientException {
RequestCallback requestCallback = httpEntityCallback(request, responseType);
ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
return execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables);
}
@Override
public <T> ResponseEntity<T> postForEntity(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables)
throws RestClientException {
RequestCallback requestCallback = httpEntityCallback(request, responseType);
ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
return execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables);
}
@Override
public <T> ResponseEntity<T> postForEntity(URI url, Object request, Class<T> responseType) throws RestClientException {
RequestCallback requestCallback = httpEntityCallback(request, responseType);
ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
return execute(url, HttpMethod.POST, requestCallback, responseExtractor);
}
User定義一接口:
@PostMapping("/queryLoginPrivilegeByUser")
public List<String> queryLoginPrivilegeByUser(@RequestBody User user){
int id = user.getId();
if(id ==1 ){
return Arrays.asList("臺(tái)賬查詢,用戶設(shè)置".split(","));
}else{
return Arrays.asList("購(gòu)物車設(shè)置,積分后臺(tái)查詢".split(","));
}
}
Order的實(shí)現(xiàn):
//post請(qǐng)求
@PostMapping("/queryLoginPrivilegeByUser")
public List<String> queryLoginPrivilegeByUser(@RequestBody User user){
List<String> menulist = restTemplate.postForEntity("http://localhost:8080/queryLoginPrivilegeByUser",user,List.class).getBody();
return menulist;
}
@PostMapping("/queryLoginPrivilegeByUser2")
public List<String> queryLoginPrivilegeByUser2(@RequestBody User user){
UriComponents uriComponents = UriComponentsBuilder.fromUriString("http://localhost:8080/queryLoginPrivilegeByUser").build();
URI uri = uriComponents.toUri();
List<String> menulist = restTemplate.postForEntity(uri,user,List.class).getBody();
return menulist;
}
User定義一接口:
@PostMapping("/queryUserPrivilegeById")
public String queryUserPrivilegeById(@RequestParam int id,@RequestParam String name){
if(1 ==id){
return "user is "+name;
}
return "user is not exist";
}
@PostMapping("/queryUserPrivilegeById")
public String queryUserPrivilegeById(@RequestParam int id,@RequestParam String name){
HttpHeaders headers = new HttpHeaders();
MultiValueMap<String, Object> parammap = new LinkedMultiValueMap<>();
parammap.add("id",id);
parammap.add("name",name);
HttpEntity<Map> entity = new HttpEntity<>(parammap,headers);
String result = restTemplate.postForEntity("http://localhost:8080/queryUserPrivilegeById",entity,String.class).getBody();
return result;
}
第二種:getForObject函數(shù)
該方法可以理解為對(duì)getForEntity的進(jìn)一步封裝,它通過(guò)org.springframework.web.client.HttpMessageConverterExtractor對(duì)HTTP的請(qǐng)求響應(yīng)體body內(nèi)容進(jìn)行對(duì)象轉(zhuǎn)換邓夕,實(shí)現(xiàn)請(qǐng)求直接返回包裝好的對(duì)象內(nèi)容刘莹。
@PostMapping("/queryUserByPrivilege")
public User queryUserByPrivilege(@RequestParam String privilege){
HttpHeaders headers = new HttpHeaders();
MultiValueMap<String, Object> parammap = new LinkedMultiValueMap<>();
parammap.add("privilege",privilege);
HttpEntity<Map> entity = new HttpEntity<>(parammap,headers);
User user = restTemplate.postForObject(userService+"/queryUserByPrivilege",entity,User.class);
return user;
}
postForObject函數(shù)也提供了三個(gè)重載的方法
@Override
public <T> T postForObject(String url, Object request, Class<T> responseType, Object... uriVariables)
throws RestClientException {
RequestCallback requestCallback = httpEntityCallback(request, responseType);
HttpMessageConverterExtractor<T> responseExtractor =
new HttpMessageConverterExtractor<T>(responseType, getMessageConverters(), logger);
return execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables);
}
@Override
public <T> T postForObject(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables)
throws RestClientException {
RequestCallback requestCallback = httpEntityCallback(request, responseType);
HttpMessageConverterExtractor<T> responseExtractor =
new HttpMessageConverterExtractor<T>(responseType, getMessageConverters(), logger);
return execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables);
}
@Override
public <T> T postForObject(URI url, Object request, Class<T> responseType) throws RestClientException {
RequestCallback requestCallback = httpEntityCallback(request, responseType);
HttpMessageConverterExtractor<T> responseExtractor =
new HttpMessageConverterExtractor<T>(responseType, getMessageConverters());
return execute(url, HttpMethod.POST, requestCallback, responseExtractor);
}
第三種使用postForLocation函數(shù)
該方法實(shí)現(xiàn)了以post提交資源,返回新資源的URI焚刚。
@PostMapping("/queryLoginPrivilegeByUser3")
public void queryLoginPrivilegeByUser3(@RequestBody User user){
URI uri = restTemplate.postForLocation("http://localhost:8080/queryLoginPrivilegeByUser",user);
System.out.println("uri=="+uri);
}
postForLocation函數(shù)也提供了三種不同的重載方法
@Override
public URI postForLocation(String url, Object request, Object... uriVariables) throws RestClientException {
RequestCallback requestCallback = httpEntityCallback(request);
HttpHeaders headers = execute(url, HttpMethod.POST, requestCallback, headersExtractor(), uriVariables);
return headers.getLocation();
}
@Override
public URI postForLocation(String url, Object request, Map<String, ?> uriVariables) throws RestClientException {
RequestCallback requestCallback = httpEntityCallback(request);
HttpHeaders headers = execute(url, HttpMethod.POST, requestCallback, headersExtractor(), uriVariables);
return headers.getLocation();
}
@Override
public URI postForLocation(URI url, Object request) throws RestClientException {
RequestCallback requestCallback = httpEntityCallback(request);
HttpHeaders headers = execute(url, HttpMethod.POST, requestCallback, headersExtractor());
return headers.getLocation();
}
PUT請(qǐng)求
put函數(shù)也實(shí)現(xiàn)了三種不同的重載方法:
@Override
public void put(String url, Object request, Object... uriVariables) throws RestClientException {
RequestCallback requestCallback = httpEntityCallback(request);
execute(url, HttpMethod.PUT, requestCallback, null, uriVariables);
}
@Override
public void put(String url, Object request, Map<String, ?> uriVariables) throws RestClientException {
RequestCallback requestCallback = httpEntityCallback(request);
execute(url, HttpMethod.PUT, requestCallback, null, uriVariables);
}
@Override
public void put(URI url, Object request) throws RestClientException {
RequestCallback requestCallback = httpEntityCallback(request);
execute(url, HttpMethod.PUT, requestCallback, null);
}
put函數(shù)為void類型点弯,所以沒(méi)有返回內(nèi)容,也就沒(méi)有其他函數(shù)定義的responseType參數(shù)矿咕。
DELETE請(qǐng)求
User項(xiàng)目中定義:
@DeleteMapping("/deleteUserById/{id}")
public void deleteUserById(@PathVariable int id){
logger.info(id+"");
}
localhost:8080/deleteUserById/1
Order項(xiàng)目中調(diào)用
@DeleteMapping("/deleteUserById/{id}")
public void deleteUserById(@PathVariable int id){
restTemplate.delete(userService+"/deleteUserById/{1}",id);
}
localhost:9090/deleteUserById/1
delete函數(shù)也有三種不同的重載方法:
@Override
public void delete(String url, Object... uriVariables) throws RestClientException {
execute(url, HttpMethod.DELETE, null, null, uriVariables);
}
@Override
public void delete(String url, Map<String, ?> uriVariables) throws RestClientException {
execute(url, HttpMethod.DELETE, null, null, uriVariables);
}
@Override
public void delete(URI url) throws RestClientException {
execute(url, HttpMethod.DELETE, null, null);
}