欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解RestTemplate?用法

 更新時間:2022年07月20日 11:29:26   作者:怪?咖@  
RestTemplate?是從?Spring3.0?開始支持的一個?HTTP?請求工具,也有的稱之為網(wǎng)絡(luò)框架,說白了就是Java版本的一個postman,這篇文章主要介紹了詳解RestTemplate?用法,需要的朋友可以參考下

一、簡言

RestTemplate 是從 Spring3.0 開始支持的一個 HTTP 請求工具,也有的稱之為網(wǎng)絡(luò)框架,說白了就是Java版本的一個postman。專門用于在Java當中服務(wù)與服務(wù)之間遠程調(diào)用接口的時候用。

舉例A服務(wù),需要從B服務(wù)獲取到數(shù)據(jù),假如不經(jīng)過前端頁面只是后端A服務(wù)獲取B服務(wù)的數(shù)據(jù)的話,這時候就需要通過Java的HTTP請求工具來遠程調(diào)用。

類似的還有Apache 的 HttpClient 以及OKHttp3,都是Java當中常用的HTTP 請求工具。

關(guān)于HttpClient用法:http://www.dbjr.com.cn/article/256131.htm

RestTemplate優(yōu)點:

  • RestTemplate屬于spring的,假如springboot項目的話,完全不用引入任何其他依賴,直接可以用。
  • RestTemplate可以和cloud當中的ribbon進行配合使用,只需要一個注解就可以完成負載均衡調(diào)用。

官網(wǎng)api:https://docs.spring.io/spring-framework/docs/5.0.9.RELEASE/javadoc-api/

二、注入容器

既然是遠程調(diào)用,那么我們系統(tǒng)肯定不會只調(diào)用一次,通常情況我們會將RestTemplate注入到容器當中,讓他保持單例,當我們哪個類要使用的時候直接從容器里面獲取即可。這樣可以避免每調(diào)用一次創(chuàng)建一個RestTemplate對象。

2.1、普通配置

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class ApplicationContextBean {

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

使用的時候直接通過容器注入即可。

@Autowired
private RestTemplate restTemplate;

2.2、詳細配置

對于一個請求來說,連接超時時間,請求超時時間等都是可以設(shè)置的參數(shù),為了更好的適應業(yè)務(wù)需求,所以可以自己修改restTemplate的配置。如下利用@Bean注解的參數(shù)特性,形成了一個實例化鏈條。(我實際開發(fā)當中一般沒有詳細設(shè)置過,包括我涉及到的項目也是,一般都是直接像上面的簡單配置一下就開始使用了)

@Bean注解修飾的方法,假如帶有參數(shù),其實就是代表@Bean所標注的對象的實例化依賴于參數(shù)中的類,需要先將參數(shù)中的類實例化,才能實例化@Bean所標注的對象。

import org.apache.http.Header;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeader;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.List;

@Configuration
public class RestTemplateConfig {

    /**
     * http連接管理器
     *
     * @return
     */
    @Bean
    public HttpClientConnectionManager poolingHttpClientConnectionManager() {
        /* 注冊http和https請求
        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.getSocketFactory())
                .register("https", SSLConnectionSocketFactory.getSocketFactory())
                .build();
        PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(registry);*/

        PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager();
        // 最大連接數(shù)
        poolingHttpClientConnectionManager.setMaxTotal(500);
        // 同路由并發(fā)數(shù)(每個主機的并發(fā))
        poolingHttpClientConnectionManager.setDefaultMaxPerRoute(100);
        return poolingHttpClientConnectionManager;
    }

    /**
     * HttpClient
     *
     * @param poolingHttpClientConnectionManager
     * @return
     */
    @Bean
    public HttpClient httpClient(HttpClientConnectionManager poolingHttpClientConnectionManager) {
        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
        // 設(shè)置http連接管理器
        httpClientBuilder.setConnectionManager(poolingHttpClientConnectionManager);

        // 設(shè)置重試次數(shù)
        httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(3, true));

        // 設(shè)置默認請求頭(具體可根據(jù)自己業(yè)務(wù)場景進行設(shè)置)
        List<Header> headers = new ArrayList<>();
        headers.add(new BasicHeader("atoken", "WAKJDWAJLDKWAKDLKWALKDALKW"));
        httpClientBuilder.setDefaultHeaders(headers);

        return httpClientBuilder.build();
    }

    /**
     * 請求連接池配置
     *
     * @param httpClient
     * @return
     */
    @Bean
    public ClientHttpRequestFactory clientHttpRequestFactory(HttpClient httpClient) {
        HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
        // httpClient創(chuàng)建器
        clientHttpRequestFactory.setHttpClient(httpClient);
        // 連接超時時間/毫秒(連接上服務(wù)器(握手成功)的時間,超出拋出connect timeout)
        clientHttpRequestFactory.setConnectTimeout(5 * 1000);
        // 數(shù)據(jù)讀取超時時間(socketTimeout)/毫秒(務(wù)器返回數(shù)據(jù)(response)的時間,超過拋出read timeout)
        clientHttpRequestFactory.setReadTimeout(10 * 1000);
        // 連接池獲取請求連接的超時時間,不宜過長,必須設(shè)置/毫秒(超時間未拿到可用連接,會拋出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool)
        clientHttpRequestFactory.setConnectionRequestTimeout(10 * 1000);
        return clientHttpRequestFactory;
    }

    /**
     * rest模板
     *
     * @return
     */
    @Bean
    public RestTemplate restTemplate(ClientHttpRequestFactory clientHttpRequestFactory) {
        // boot中可使用RestTemplateBuilder.build創(chuàng)建
        RestTemplate restTemplate = new RestTemplate();
        // 配置請求工廠
        restTemplate.setRequestFactory(clientHttpRequestFactory);
        
        // 添加攔截器(這塊可以通過攔截器來實現(xiàn)日志打印,既然是攔截器,那肯定會丟失一定的性能,所以可根據(jù)情況使用,如果計劃在攔截器當中打印request當中的日志,一定要注意request是流,不能讀兩次,這塊要做的話,需要想辦法將流取出然后再替換一個新的流)
//        List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();
//        interceptors.add(restTemplateLog);
//        restTemplate.setInterceptors(interceptors);
        return restTemplate;
    }

}

三、GET請求

這里的方法一共有兩類,getForEntitygetForObject,每一類有三個重載方法,下面我們分別予以介紹,首先我們先了解一下傳參:

  • String url:請求接口地址
  • URI url:使用 Uri 對象時,參數(shù)可以直接拼接在地址中
  • Class<T> responseType:返回的response當中body的對象類型,相當于只要這塊寫好了,我們就不用將返回值 再進行序列化成對象了。
  • Map<String,?> uriVariables:map類型的key value參數(shù),這個key需要和地址當中的key相對應的
  • Object... uriVariables:這是一個可變長參數(shù),地址欄當中可以用1,2數(shù)字占位符當中參數(shù),傳參的時候,只要這塊的可變長參數(shù)能按順序和占位符 一 一對上即可。

3.1、getForEntity

把這個接口當做要遠程調(diào)用的接口:

@GetMapping("/getTest2")
public String getTest2(String name) {
    return "hello " + name + " !";
}

這種寫法實際是就相當于是這樣的:http://localhost:8006/getTest2?name=222

那么遠程調(diào)用怎么調(diào)用呢?下面一共提供了三種寫法!

@GetMapping("/test")
public void test() throws UnsupportedEncodingException {
    // 第一種方案(這種方案有點類似hibernate占位符取值,getForEntity第三個參數(shù)就是一個可變長參數(shù),當get請求有多個參數(shù)的時候也是可以用這種方式的)
    String url1 = "http://127.0.0.1:8006/getTest2?name={1}";
    // 這塊的String.class就是ResponseEntity當中的body要序列化成的java對象類型
    ResponseEntity<String> responseEntity1 = restTemplate.getForEntity(url1, String.class, "aaa");
    System.out.println(responseEntity1.getStatusCode());
    System.out.println(responseEntity1.getBody());
    System.out.println(responseEntity1.getHeaders());

    // 第二種方案,將參數(shù)放入到一個 map 中。map 中的 key 和占位符的 key 相對應,map 中的 value 就是參數(shù)的具體值
    Map<String, Object> map = new HashMap<>();
    String url2 = "http://127.0.0.1:8006/getTest2?name={name}";
    map.put("name", "bbb");
    ResponseEntity<String> responseEntity2 = restTemplate.getForEntity(url2, String.class, map);
    System.out.println(responseEntity2.getStatusCode());
    System.out.println(responseEntity2.getBody());
    System.out.println(responseEntity2.getHeaders());

    // 第三種方案,使用 Uri 對象時,參數(shù)可以直接拼接在地址中
    String url = "http://127.0.0.1:8006/getTest2?name=" + URLEncoder.encode("ccc", "UTF-8");
    URI uri = URI.create(url);
    ResponseEntity<String> responseEntity3 = restTemplate.getForEntity(uri, String.class);
    System.out.println(responseEntity3.getStatusCode());
    System.out.println(responseEntity3.getBody());
    System.out.println(responseEntity3.getHeaders());
}

RestTemplate 發(fā)送的是 HTTP 請求,那么在響應的數(shù)據(jù)中必然也有響應頭,如果開發(fā)者需要獲取響應頭的話,那么就需要使用 getForEntity 來發(fā)送 HTTP 請求,此時返回的對象是一個 ResponseEntity 的實例。通過ResponseEntity我們可以獲取請求的響應詳細信息,例如:body請求體,header請求頭,status狀態(tài)碼

ResponseEntity對象,他實際上就是包含了例如網(wǎng)頁訪問時候的響應信息。

3.2、getForObject

getForObject 方法和 getForEntity 方法類似,getForObject 方法也有三個重載的方法,參數(shù)和 getForEntity 一樣,因此這里我就不重復介紹參數(shù)了,這里主要說下 getForObjectgetForEntity 的差異,這兩個的差異主要體現(xiàn)在返回值的差異上, getForObject 的返回值就是服務(wù)提供者返回的數(shù)據(jù),使用 getForObject 無法獲取到響應頭。

把下面接口當做要遠程調(diào)用的接口:

// 沒有參數(shù)的時候調(diào)用
@GetMapping("/getTest1")
public String getTest1() {
    return "getTest1";
}

// ?拼接的參數(shù)
@GetMapping("/getTest2")
public String getTest2(String name) {
    return "hello " + name + " !";
}

// 斜杠地址欄/ 拼接的參數(shù)
@GetMapping("/getTest3/{name}")
public String getTest3(@PathVariable(value = "name") String name) {
    return "hello " + name + " !";
}

那么遠程調(diào)用怎么調(diào)用呢?下面提供多個示例供參考!

@GetMapping("/test1")
public void test1() throws UnsupportedEncodingException {
    // 無參調(diào)用
    String result = restTemplate.getForObject("http://127.0.0.1:8006/getTest1", String.class);
    System.out.println(result);

    String url2 = "http://127.0.0.1:8006/getTest2?name={1}";
    String result1 = restTemplate.getForObject(url2, String.class, "aaa");
    System.out.println(result1);

    // 第一種方案 調(diào)用地址欄/拼接
    String url3 = "http://127.0.0.1:8006/getTest3/{1}";
    String result2 = restTemplate.getForObject(url3, String.class, "bbb");
    System.out.println(result2);

    // 第二種方案 調(diào)用地址欄/拼接
    String url4 = "http://127.0.0.1:8006/getTest3/" + URLEncoder.encode("ccc", "UTF-8");
    URI uri = URI.create(url4);
    String result3 = restTemplate.getForObject(uri, String.class);
    System.out.println(result3);

    // 第三種方案 調(diào)用地址欄/拼接
    Map<String, Object> map = new HashMap<>();
    String url5 = "http://127.0.0.1:8006/getTest3/{name}";
    map.put("name", "ddd");
    String result4 = restTemplate.getForObject(url5, String.class, map);
    System.out.println(result4);
}

通過以上練習后會發(fā)現(xiàn)一個致命問題,提供的get請求的API當中并沒有header傳參這一項,假如請求的別的服務(wù)接口有認證,那我們該怎么辦呢?

我們可以使用RestTemplate 當中的 exchange自定義請求。

四、POST 請求

可以看到,post 請求的方法類型除了 postForEntitypostForObject 之外,還有一個 postForLocation。這里的方法類型雖然有三種,但是這三種方法重載的參數(shù)基本是一樣的。其余參數(shù)都和get一樣,就多了一個request參數(shù),如下:

Object request: 該參數(shù)可以是一個普通對象, 也可以是一個HttpEntity對象。

  • 如果是一個普通對象, 而非HttpEntity對象的時候, RestTemplate會將請求對象轉(zhuǎn)換為一個HttpEntity對象來處理, 其中Object就是 request請求體(body)的類型, request內(nèi)容會被視作完整的body來處理;
  • 如果 request 是一個HttpEntity對象, 那么就會被當作一個完成的HTTP請求對象來處理, 這個 request 中不僅包含了body的內(nèi)容, 也包含了header的內(nèi)容。

如下源碼是對request參數(shù)進行轉(zhuǎn)換調(diào)用的:

什么情況下要使用HttpEntity?

假如我們遠程調(diào)用的接口是有token認證的,我們請求的時候就需要在header請求頭當中添加token,這時候我們就需要通過HttpEntity對象來攜帶請求頭。

4.1、postForEntity

示例一:下面接口是JSON傳參,然后還獲取token了,把它當做要遠程調(diào)用的接口:

@PostMapping("/postTest2")
public User test2(HttpServletRequest request, @RequestBody User user1) {
    System.out.println("接受的參數(shù):" + user1);
    // 正常情況我們是需要通過攔截器來攔截request獲取請求頭當中的token來進行認證,這塊只是演示
    System.out.println("接受的請求頭:" + request.getHeader("token"));
    User user = new User();
    user.setId(1);
    user.setName("張三");
    user.setSex("男性");
    return user;
}

那么遠程調(diào)用怎么調(diào)用呢?下面示例供參考!

示例使用的是如下圖API,request 可以是一個普通對象,也可以是HttpEntity。

@GetMapping("/hello2")
public User hello5() {
    String url = "http://127.0.0.1:8006/postTest2";

    // 請求示例一:攜帶token請求頭
    // 請求體
    User user = new User();
    user.setId(1);
    user.setName("李四");
    user.setSex("女性");
    // 請求頭(這里有一點需要注意,HttpHeaders和HttpEntity都是引入的spring的包)
    HttpHeaders headers = new HttpHeaders();
    headers.add("token", "WDWADAWDWADAWSAXZCXZCXZEDF");
    // 請求
    HttpEntity<User> requst = new HttpEntity<>(user, headers);

    ResponseEntity<User> responseEntity = restTemplate.postForEntity(url, requst, User.class);
    System.out.println("響應的結(jié)果:" + responseEntity.getBody());

    // 請求示例二:不攜帶請求頭,直接傳普通對象,這里直接傳的user,map也是可以的,他都可以轉(zhuǎn)換成json,切記不能使用LinkedMultiValueMap,使用他不會轉(zhuǎn)換成json
    ResponseEntity<User> responseEntity1 = restTemplate.postForEntity(url, user, User.class);
    System.out.println("響應的結(jié)果:" + responseEntity1.getBody());

    return responseEntity1.getBody();
}

調(diào)用結(jié)果:

示例二:下面接口是key/value傳參,然后還獲取token了,把它當做要遠程調(diào)用的接口:

@PostMapping("/postTest1")
public String test1(HttpServletRequest request, String name) {
    System.out.println("接受的參數(shù):" + name);
    System.out.println("接受的請求頭:" + request.getHeader("token"));
    return "Hello " + name + " !";
}

那么遠程調(diào)用怎么調(diào)用呢?下面示例供參考!

下面每個示例都使用了request參數(shù),正常情況下,假如第三方接口沒有token認證,我們是不需要使用request參數(shù)的,直接傳null即可。

@GetMapping("/hello1")
public void hello1() throws UnsupportedEncodingException {

    // 請求頭(這里有一點需要注意,HttpHeaders和HttpEntity都是引入的spring的包)
    HttpHeaders headers = new HttpHeaders();
    headers.add("token", "WDWADAWDWADAWSAXZCXZCXZEDF");
    HttpEntity<Map> requst = new HttpEntity<>(null, headers);

    // 調(diào)用方式一,通過map傳參
    String url1 = "http://127.0.0.1:8006/postTest1?name={name}";
    Map<String, String> param = new HashMap<>(16);
    param.put("name", "李四");
    ResponseEntity<String> responseEntity1 = restTemplate.postForEntity(url1, requst, String.class, param);
    System.out.println(responseEntity1.getBody());

    // 調(diào)用方式二,通過占位符和可變長參數(shù)傳參
    String url2 = "http://127.0.0.1:8006/postTest1?name={1}";
    ResponseEntity<String> responseEntity2 = restTemplate.postForEntity(url2, requst, String.class, "牛牛");
    System.out.println(responseEntity2.getBody());

    // 調(diào)用方式三,正常這塊其實都不需要URI對象了,根據(jù)地址直接訪問就可以。
    String url3 = "http://127.0.0.1:8006/postTest1?name=" + URLEncoder.encode("ccc", "UTF-8");
    URI uri = URI.create(url3);
    ResponseEntity<String> responseEntity3 = restTemplate.postForEntity(uri, requst, String.class);
    System.out.println(responseEntity3.getBody());

	// 調(diào)用方式四:這種方式是沒有使用請求頭的,使用LinkedMultiValueMap,切記不能使用hashmap和java實體類,不然就轉(zhuǎn)換成json了,將LinkedMultiValueMap放到HttpEntity的body當中其實也是可以的,然后就可以攜帶token了。
    String url4 = "http://127.0.0.1:8006/postTest1";
    MultiValueMap map = new LinkedMultiValueMap();
    map.add("name", "薩瓦迪卡");
    ResponseEntity<String> responseEntity4 = restTemplate.postForEntity(url4, map, String.class);
    System.out.println(responseEntity4.getBody());
}

調(diào)用示例:

前三種方式都是攜帶了header,最后一種沒有帶。

4.2、postForObject

postForObject 和 postForEntity 基本一致,就是返回類型不同而已,這里不再贅述。

4.3、postForLocation

postForLocation 方法的返回值是一個 Uri 對象,因為 POST 請求一般用來添加數(shù)據(jù),有的時候需要將剛剛添加成功的數(shù)據(jù)的 URL 返回來,此時就可以使用這個方法,一個常見的使用場景如用戶注冊功能,用戶注冊成功之后,可能就自動跳轉(zhuǎn)到登錄頁面了,此時就可以使用該方法。例如在 provider 中提供一個用戶注冊接口,再提供一個用戶登錄接口,如下:

@RequestMapping("/register")
public String register(User user) throws UnsupportedEncodingException {
    return "redirect:/loginPage?username=" + URLEncoder.encode(user.getUsername(),"UTF-8") + "&address=" + URLEncoder.encode(user.getAddress(),"UTF-8");
}
@GetMapping("/loginPage")
@ResponseBody
public String loginPage(User user) {
    return "loginPage:" + user.getUsername() + ":" + user.getAddress();
}

這里一個注冊接口,一個是登錄頁面,不過這里的登錄頁面我就簡單用一個字符串代替了。然后在 consumer 中來調(diào)用注冊接口,如下:

@GetMapping("/hello8")
public String hello8() {
    List<ServiceInstance> list = discoveryClient.getInstances("provider");
    ServiceInstance instance = list.get(0);
    String host = instance.getHost();
    int port = instance.getPort();
    String url = "http://" + host + ":" + port + "/register";
    MultiValueMap map = new LinkedMultiValueMap();
    map.add("username", "牧碼小子");
    map.add("address", "深圳");
    URI uri = restTemplate.postForLocation(url, map);
    String s = restTemplate.getForObject(uri, String.class);
    return s;
}

注意: postForLocation 方法返回的 Uri 實際上是指響應頭的 Location 字段,所以,provider 中 register 接口的響應頭必須要有 Location 字段(即請求的接口實際上是一個重定向的接口),否則 postForLocation 方法的返回值為null,初學者很容易犯這個錯誤。

五、PUT請求

PUT 請求和POST請求傳參基本上一模一樣,他也有request參數(shù),唯一區(qū)別就是PUT請求是沒有返回值的,PUT 請求本身方法也比較少,只有三個,如下:

六、DELETE請求

DELETE 請求和GET請求傳參基本上一模一樣,同樣都沒有request參數(shù),唯一區(qū)別就是DELETE 請求是沒有返回值的,DELETE 請求本身方法也比較少,只有三個,如下:

七、LinkedMultiValueMap源碼分析

1、項目中在使用RestTemplate進行http請求時,會用到LinkedMultiValueMap,現(xiàn)在簡單分析一下LinkedMultiValueMap的數(shù)據(jù)結(jié)構(gòu)。

2、打開LinkedMultiValueMap的源碼,可以看到里面封裝的是一個Map,再看構(gòu)造方法,最終創(chuàng)建的是一個LinkedHashMap。這個Map的value有點特別,他不能放任何值,必須是一個List。
其實LinkedMultiValueMap可以看作是一個表單,在表單中,一個name可以對應很多值,比如根據(jù)id批量刪除,一個key需要對應很多需要刪除的id

3、add、put、set

public static void main(String[] args) {
    MultiValueMap params = new LinkedMultiValueMap();

    params.add("username", "張三");
    params.add("username", "李四");
    System.out.println(params);

    params.put("password", Arrays.asList("1234"));
    System.out.println(params);

    params.set("username", "王五");
    System.out.println(params);
}

運行結(jié)果:

4、通過源碼分析

add是把值放到list中,若map中沒有key對應的list,先new一個LinkedList。

put直接接收list

set不管原來怎么樣,都會重新new一個LinkedList,再把值放進去

5、什么時候使用LinkedMultiValueMap,答案就是模擬普通的表單提交時。

HttpEntity的body里面使用LinkedMultiValueMap,那么就是key/value傳參,如果是其他的bean類型,就會格式化成json。

八、通用方法 exchange

為什么說它通用呢?因為這個方法需要你在調(diào)用的時候去指定請求類型,即它既能做 GET 請求,也能做 POST 請求,也能做其它各種類型的請求。如果開發(fā)者需要對請求進行封裝,使用它再合適不過了。這個方法重載的方法非常多,其中參數(shù)也多了很多個,如下:

  • HttpMethod method:請求的方法(GET、POST、PUT等)
  • HttpEntity<?> requestEntity:HttpEntity對象,封裝了請求頭和請求體,在上面post的時候應該掌握的差不多了。

8.1、用法示例

使用如下API演示兩個示例:

  • post的key/value傳參
  • post的json傳參

示例一:post的key/value傳參

@PostMapping("/exchangeTest1")
public String test1(HttpServletRequest request, String name) {
    System.out.println("接受的參數(shù):" + name);
    System.out.println("接受的請求頭:" + request.getHeader("token"));
    return "Hello " + name + " !";
}

調(diào)用示例:

@GetMapping("/exchange1")
public void hello1() {
    String url = "http://127.0.0.1:8006/exchangeTest1";

    // 請求體,一定要用LinkedMultiValueMap,用hashmap或者javabean會直接轉(zhuǎn)換成json的
    MultiValueMap map = new LinkedMultiValueMap();
    map.add("name", "薩瓦迪卡");
    // 請求頭(這里有一點需要注意,HttpHeaders和HttpEntity都是引入的spring的包)
    HttpHeaders headers = new HttpHeaders();
    headers.add("token", "WDWADAWDWADAWSAXZCXZCXZEDF");
    // 請求
    HttpEntity<Map> requst = new HttpEntity<>(map, headers);
    ResponseEntity<String> exchange = restTemplate.exchange(url, HttpMethod.POST, requst, String.class);
    System.out.println("響應的結(jié)果:" + exchange.getBody());
}

調(diào)用結(jié)果:

示例二:post的json傳參

@PostMapping("/postTest2")
public User test2(HttpServletRequest request, @RequestBody User user1) {
    System.out.println("接受的參數(shù):" + user1);
    System.out.println("接受的請求頭:" + request.getHeader("token"));
    User user = new User();
    user.setId(1);
    user.setName("張三");
    user.setSex("男性");
    return user;
}

調(diào)用示例:

@GetMapping("/exchange2")
public void hello2() {
    String url = "http://127.0.0.1:8006/postTest2";

    // 請求體,不要用LinkedMultiValueMap,否則會變成key/value傳參
    User user = new User();
    user.setId(1);
    user.setName("李四");
    user.setSex("女性");
    // 請求頭(這里有一點需要注意,HttpHeaders和HttpEntity都是引入的spring的包)
    HttpHeaders headers = new HttpHeaders();
    headers.add("token", "WDWADAWDWADAWSAXZCXZCXZEDF");
    // 請求
    HttpEntity<User> requst = new HttpEntity<>(user, headers);
    ResponseEntity<User> exchange = restTemplate.exchange(url, HttpMethod.POST, requst, User.class);
    System.out.println("響應的結(jié)果:" + exchange.getBody());
}

調(diào)用結(jié)果:

8.2、封裝通用util

可以寫一個通用的工具類,根據(jù)傳入的參數(shù)來確定請求的路徑和內(nèi)容。工具類肯定是想通過靜態(tài)方式來直接調(diào)用,而不是通過new Util()的方式來使用。但是靜態(tài)變量/類變量不是對象的屬性,而是一個類的屬性,spring則是基于對象層面上的依賴注入。所以我們不能@Autowired或者@resource一個靜態(tài)變量。但是靜態(tài)方法又不能調(diào)用非靜態(tài)的屬性,那么我們該怎么辦呢?

@PostContruct是Java自帶的注解,在方法上加該注解會在項目啟動的時候執(zhí)行該方法,也可以理解為在spring容器初始化的時候執(zhí)行該方法。

@Component
public class HttpUtil {

    private static Logger logger = LoggerFactory.getLogger(HttpUtil.class);

    @Resource
    private RestTemplate restTemplate;

    private static HttpUtil httpUtil;

    @PostConstruct
    public void init(){
        httpUtil = this;
        httpUtil.restTemplate = this.restTemplate;
    }

    public static <T> String httpRequest(String url, HttpMethod method, HttpEntity<T> entity,Class<T> responseType){
        try {
            //發(fā)起一個POST請求
            ResponseEntity<String> result = httpUtil.restTemplate.exchange(url, method, entity, responseType);
           return result.getBody();
        } catch (Exception e) {
            logger.error("請求失敗: " + e.getMessage());
        }
        return null;
    }

}

這個時候我們就需要維護一個工具類的靜態(tài)實例,初始化的時候把restTemplate傳進來,這樣就可以直接調(diào)用HttpUtil.httpRequest()方法。

到此這篇關(guān)于詳解RestTemplate 用法的文章就介紹到這了,更多相關(guān)RestTemplate 用法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 基于JavaMail的Java郵件發(fā)送

    基于JavaMail的Java郵件發(fā)送

    電子郵件的應用非常廣泛,例如在某網(wǎng)站注冊了一個賬戶,自動發(fā)送一封歡迎郵件,通過郵件找回密碼,自動批量發(fā)送活動信息等。本文將簡單介紹如何通過 Java 代碼來創(chuàng)建電子郵件,并連接郵件服務(wù)器發(fā)送郵件
    2021-10-10
  • 一篇文章帶你了解Java Stream流

    一篇文章帶你了解Java Stream流

    Stream流是數(shù)據(jù)渠道,用于操作數(shù)據(jù)源(集合、數(shù)組等)所生成的元素序列。這篇文章主要介紹了Java8新特性Stream流的相關(guān)資料,需要的朋友參考下吧
    2021-08-08
  • win7下安裝 JDK 基本流程

    win7下安裝 JDK 基本流程

    這篇文章主要介紹了win7下安裝 JDK 基本流程,需要的朋友可以參考下
    2014-05-05
  • Java實現(xiàn)非阻塞式服務(wù)器的示例代碼

    Java實現(xiàn)非阻塞式服務(wù)器的示例代碼

    這篇文章主要為大家詳細介紹了如何利用Java實現(xiàn)一個簡單的非阻塞式服務(wù)器,文中的示例代碼講解詳細,具有一定的學習價值,需要的可以參考一下
    2023-05-05
  • SpringBoot實戰(zhàn):Spring如何找到對應轉(zhuǎn)換器優(yōu)雅使用枚舉參數(shù)

    SpringBoot實戰(zhàn):Spring如何找到對應轉(zhuǎn)換器優(yōu)雅使用枚舉參數(shù)

    這篇文章主要介紹了SpringBoot實戰(zhàn)中Spring是如何找到對應轉(zhuǎn)換器優(yōu)雅的使用枚舉參數(shù),文中附有詳細的實例代碼有需要的朋友可以參考下,希望可以有所幫助
    2021-08-08
  • Netty分布式高性能工具類同線程下回收對象解析

    Netty分布式高性能工具類同線程下回收對象解析

    這篇文章主要為大家介紹了Netty分布式高性能工具類同線程下回收對象解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-03-03
  • java使用ftp上傳文件示例分享

    java使用ftp上傳文件示例分享

    這篇文章主要介紹了java使用ftp上傳文件示例,需要的朋友可以參考下
    2014-02-02
  • Java工廠模式定義與用法實例分析

    Java工廠模式定義與用法實例分析

    這篇文章主要介紹了Java工廠模式定義與用法,結(jié)合具體實例形式分析了java工廠模式定義、使用相關(guān)操作技巧,并總結(jié)了類圖原理,需要的朋友可以參考下
    2019-07-07
  • 超全面的SpringBoot面試題含答案

    超全面的SpringBoot面試題含答案

    這篇文章主要收錄了44道面試中經(jīng)常被問的SpringBoot問題,不管你是正在求職的新手還是已經(jīng)工作很久的高手,這篇關(guān)于SpringBoot的面試題總結(jié)一定會讓你有新的理解,讓我們一起來看看吧
    2023-03-03
  • Spring動態(tài)注冊多數(shù)據(jù)源的實現(xiàn)方法

    Spring動態(tài)注冊多數(shù)據(jù)源的實現(xiàn)方法

    這篇文章主要介紹了Spring動態(tài)注冊多數(shù)據(jù)源的實現(xiàn)方法,小編覺的挺不錯的,現(xiàn)分享到腳本之家平臺,需要的朋友可以參考下
    2018-01-01

最新評論