简介
RestTemplate是Spring3.0后开始提供的用于访问 Rest 服务的轻量级客户端,相较于传统的HttpURLConnection、Apache HttpClient、OkHttp等框架,RestTemplate大大简化了发起HTTP请求以及处理响应的过程。
RestTemplate只是对其它Rest客户端的一个封装,本身并没有自己的实现。
很多人都说Spring Boot 2.0之前RestTestTemplate的默认实现是HttpClient,2.+为OKHttp3,其实这种说法并不完全正确,如果没有引入这些客户端的jar包,其默认实现是HttpURLConnection(集成了URLConnection),这是JDK自带的REST客户端实现。
引入依赖:
<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;
}
}
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;
@Autowired
private RestTemplate restTemplate;
测试准备
新建User对象,用于下面不同请求方式的测试。
构建Http服务。
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;
}
}
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相关的信息,如响应码、响应头等。
//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);
//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对象。
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);
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()。
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());
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());
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中几种常见的请求方式