使用Spring RestTemplate訪問Rest服務

簡介

RestTemplate是Spring3.0後開始提供的用於訪問 Rest 服務的輕量級客戶端,相較於傳統的HttpURLConnection、Apache HttpClient、OkHttp等框架,RestTemplate大大簡化了發起HTTP請求以及處理響應的過程。java

RestTemplate只是對其它Rest客戶端的一個封裝,自己並無本身的實現。
不少人都說Spring Boot 2.0以前RestTestTemplate的默認實現是HttpClient,2.+爲OKHttp3,其實這種說法並不徹底正確,若是沒有引入這些客戶端的jar包,其默認實現是HttpURLConnection(集成了URLConnection),這是JDK自帶的REST客戶端實現。web

引入依賴:

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.16.18</version>
    <scope>provided</scope>
</dependency>

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>3.11.0</version>
</dependency>

引入RestTemplate

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

/**
 * RestTemplate配置類
 */
@Configuration
public class RestTemplateConfig {

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

    @Bean
    public OkHttp3ClientHttpRequestFactory okHttp3ClientHttpRequestFactory(){
        OkHttp3ClientHttpRequestFactory factory = new OkHttp3ClientHttpRequestFactory();
        // 單位:毫秒
        factory.setConnectTimeout(10000);
        factory.setReadTimeout(10000);
        factory.setWriteTimeout(10000);
        return factory;
    }
}

注入RestTemplate

@Autowired
private RestTemplate restTemplate;

測試準備

新建User對象,用於下面不一樣請求方式的測試。
構建Http服務。spring

import lombok.Data;
@Data
public class User {
    private Long id;
    private String username;
    private Integer age;
}

import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/")
@Slf4j
public class DemoController {

    @GetMapping("demo/{id}/{userName}")
    public User get(@PathVariable Long id, @PathVariable String userName, Integer age){
        log.info("id:{}, userName:{}, age:{}", id, userName, age);
        User user = new User();
        user.setId(id);
        user.setUsername(userName);
        user.setAge(age);
        return user;
    }

    @PostMapping("demo")
    public User post(@RequestBody String json){
        log.info("json:{}", json);
        Gson gson = new Gson();
        User user = gson.fromJson(json, User.class);
        return user;
    }
}

GET請求

GET請求對應兩個方法,getForObject()和getForEntity(),每一個方法又對應有具體的三個重載方法。這二者的區別在於getForObject()返回的是一個簡單的對象,而getForEntity()響應的數據中,還額外包含有與HTTP相關的信息,如響應碼、響應頭等。json

//URL中的{id}佔位符最終將會用方法的id參數來填充
String url = "http://127.0.0.1:8083/demo/{id}/{userName}?age=18";
Long id = 1001L;
String userName = "Tom";

//重載1:最後一個參數是大小可變的參數列表,每一個參數都會按出現順序插入到指定URL的佔位符中
User user = restTemplate.getForObject(url, User.class, id, userName);
System.out.println("user = " + user);

//重載2:將id參數放到Map中,並以id做爲key,而後將這個Map做爲最後一個參數
Map<String, Object> urlParams = new HashMap<>();
urlParams.put("id", id);
urlParams.put("userName", userName);
User user2 = restTemplate.getForObject(url, User.class, urlParams);
System.out.println("user2 = " + user2);

//重載1:同getForObject(),只不過返回的類型是ResponseEntity
ResponseEntity<User> userResponseEntity = restTemplate.getForEntity(url, User.class, id, userName);
User user3 = userResponseEntity.getBody();
HttpStatus statusCode = userResponseEntity.getStatusCode();
int statusCodeValue = userResponseEntity.getStatusCodeValue();
HttpHeaders headers = userResponseEntity.getHeaders();
System.out.println("user = " + user3 + "; statusCode = " + statusCode + "; statusCodeValue = " + statusCodeValue + "; headers = " + headers);

//重載1:同getForObject(),只不過返回的類型是ResponseEntity
Map<String, Object> urlParams2 = new HashMap<>(1);
urlParams2.put("id", id);
urlParams2.put("userName", userName);
ResponseEntity<User> userResponseEntity2 = restTemplate.getForEntity(url, User.class, urlParams2);
System.out.println("userResponseEntity2 = " + userResponseEntity2);

POST請求

POST請求對應三個方法,postForObject()、postForEntity()和postForLocation(),每一個方法一樣對應有三個具體的重載方法。postForObject()、postForEntity()相似於getForObject()和postForEntity(),postForLocation()返回的是一個URI對象。segmentfault

String url = "http://localhost:8083/demo2";
//重載1 & 重載2
User user1 = new User();
user1.setId(12L);
user1.setAge(20);
user1.setUsername("張三");
//第4個參數能夠是Object... uriVariables 或者 Map<String, ?> uriVariables
User u1 = restTemplate.postForObject(url, user1, User.class);
System.out.println("user1 = " + u1);
//重載3
User user2 = new User();
user2.setId(12L);
user2.setAge(30);
user2.setUsername("李四");
User u2 = restTemplate.postForObject(URI.create(url), user2, User.class);
System.out.println("user2 = " + u2);
// 重載1 & 重載2
User user3 = new User();
user3.setAge(25);
user3.setUsername("王五");
// 第4個參數能夠是Object... uriVariables 或者 Map<String, ?> uriVariables
ResponseEntity<User> userResponseEntity = restTemplate.postForEntity(url, user3, User.class);
User userBody = userResponseEntity.getBody();
HttpStatus statusCode = userResponseEntity.getStatusCode();
int statusCodeValue = userResponseEntity.getStatusCodeValue();
HttpHeaders headers = userResponseEntity.getHeaders();
System.out.println("user = " + userBody + "; statusCode = " + statusCode + "; statusCodeValue = " + statusCodeValue + "; headers = " + headers);
// 重載3
User user4 = new User();
user4.setAge(35);
user4.setUsername("陸六");
ResponseEntity<User> userResponseEntity2 = restTemplate.postForEntity(URI.create(url), user4, User.class);
System.out.println("userResponseEntity2 = " + userResponseEntity2);

exchange通用請求

建議你們多使用exchange()。app

String getUrl = "http://127.0.0.1:8083/demo/{id}/{userName}?age=18";

//GET資源
//參數3是請求頭部分;參數4是響應數據要轉成對象;最後一個參數用於替換URL中的佔位符
ResponseEntity<User> userResponseEntity = restTemplate.exchange(getUrl, HttpMethod.GET, null, User.class, 1001L, "Tom");
System.out.println("exchange = " + userResponseEntity + "; response body = " + userResponseEntity.getBody());

String postUrl = "http://localhost:8083/demo2";

//POST資源
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
String jsonParams = "{\"username\":\"123\",\"age\":23}";
HttpEntity<User> httpEntity = new HttpEntity(jsonParams, headers);
ResponseEntity<User> responseEntity = restTemplate.exchange(postUrl, HttpMethod.POST, httpEntity, User.class);
System.out.println("exchange = " + responseEntity + "; response body = " + responseEntity.getBody());

POST請求,from-data傳參

String url = "http://localhost:8083/demo2";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
MultiValueMap map = new LinkedMultiValueMap();
map.add("id",1001L);
HttpEntity requestBody = new HttpEntity(map, headers);
ResponseEntity<User> responseEntity = restTemplate.postForEntity(url, requestBody, User.class);
System.out.println(responseEntity.getBody());

參考:
Spring RestTemplate中幾種常見的請求方式框架

相關文章
相關標籤/搜索