spring cloud ribbon學(xué)習(xí)一:RestTemplate類使用詳解

客戶端負(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.
此外万搔,exchangeexecute方法支持附加的需求胡桨,較不頻繁的結(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.SimpleClientHttpRequestFactoryDefaultResponseErrorHandler作為其默認(rèn)策略去創(chuàng)建HTTP連接和處理HTTP錯(cuò)誤狗唉。這些默認(rèn)的策略可以分別被重寫通過(guò)setRequestFactorysetErrorHandler方法

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);
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末抢肛,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子碳柱,更是在濱河造成了極大的恐慌捡絮,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,884評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件莲镣,死亡現(xiàn)場(chǎng)離奇詭異福稳,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)瑞侮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門的圆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人半火,你說(shuō)我怎么就攤上這事越妈。” “怎么了钮糖?”我有些...
    開(kāi)封第一講書人閱讀 158,369評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵梅掠,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng)阎抒,這世上最難降的妖魔是什么酪我? 我笑而不...
    開(kāi)封第一講書人閱讀 56,799評(píng)論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮挠蛉,結(jié)果婚禮上祭示,老公的妹妹穿的比我還像新娘。我一直安慰自己谴古,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,910評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布稠歉。 她就那樣靜靜地躺著掰担,像睡著了一般。 火紅的嫁衣襯著肌膚如雪怒炸。 梳的紋絲不亂的頭發(fā)上带饱,一...
    開(kāi)封第一講書人閱讀 50,096評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音阅羹,去河邊找鬼勺疼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛捏鱼,可吹牛的內(nèi)容都是我干的执庐。 我是一名探鬼主播,決...
    沈念sama閱讀 39,159評(píng)論 3 411
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼导梆,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼轨淌!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起看尼,我...
    開(kāi)封第一講書人閱讀 37,917評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤递鹉,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后藏斩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體躏结,經(jīng)...
    沈念sama閱讀 44,360評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,673評(píng)論 2 327
  • 正文 我和宋清朗相戀三年狰域,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了媳拴。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,814評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡北专,死狀恐怖禀挫,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情拓颓,我是刑警寧澤语婴,帶...
    沈念sama閱讀 34,509評(píng)論 4 334
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響砰左,放射性物質(zhì)發(fā)生泄漏匿醒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,156評(píng)論 3 317
  • 文/蒙蒙 一缠导、第九天 我趴在偏房一處隱蔽的房頂上張望廉羔。 院中可真熱鬧,春花似錦僻造、人聲如沸憋他。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)竹挡。三九已至,卻和暖如春立膛,著一層夾襖步出監(jiān)牢的瞬間揪罕,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,123評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工宝泵, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留好啰,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,641評(píng)論 2 362
  • 正文 我出身青樓儿奶,卻偏偏與公主長(zhǎng)得像框往,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子廓握,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,728評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容