一、引言:
我们在开发中经常会遇到与第三方服务交互的需求,Spring RestTemplate 是 Spring 提供的用于访问 Rest 服务的客户端,RestTemplate 提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率,所以很多客户端都使用RestTemplate请求restful接口服务。本文将结合具体代码详细介绍Spring RestTemplate开发。
二、设置:
2.1 setBufferRequestBody 是否是否缓冲流来存储请求体,默认true
2.2 setProxy 设置代理对象
2.3 setChunkSize 设置每次传输字节长度,与 setBufferRequestBody(false) 结合使用
2.4 setConnectTimeout 设置连接超时时间,默认 -1
2.5 setReadTimeout 设置读取内容超时时间,默认 -1
2.6 setOutputStreaming 设置Connection是否设置输出流程
2.7 setTaskExecutor 设置异步回调执行器
三、原理:
RestTemplate内部通过调用doExecute方法,获取ClientHttpRequest,ClientHttpRequestFactory实现了ClientHttpRequest,同时实现方法。通过ClientHttpRequest的createRequest方法选择工厂类创建对象,接着执行requestCallback.doWithRequest(request)方法,RequestCallback封装了请求体和请求头对象,也就是说在该对象里面可以拿到我们需要的请求参数。接着执行 response = request.execute()方法发送请求,最后解析response。
四、RestTemplate创建HTTP请求方法介绍:
RestTemplate类中通过不同的方法实现创建HTTP请求。
4.1、GET请求方法有:
4.2、POST请求方法有:
4.3、PUT、PATCH、DELETE、OPTIONS请求方法有:
4.4、exchange请求方法有:
五、不同请求方法的区别:
5.1、getForEntity/postForEntity/exchange与getForObject/postForObject最大的区别就在于返回内容不一样:getForEntity/postForEntity/exchange返回的是一个ResponseEntity,返回http全部信息。而getForObject只返回http的body部份。
getForObject/postForObject response: {"code":0,"message":"success","object”:{xxx}}
getForEntity/postForEntity/exchange response: <200,{"code":0,"message":"success","object”:{xxx}},[Connection:"keep-alive", Content-Type:"application/json", Date:"Mon, 21 Jun 2021 15:44:32 GMT", Keep-Alive:"timeout=60", Transfer-Encoding:"chunked"]>
5.2、对于post方法来说,可以比get方法多传一个request对象,请求参数可以放到请求url里面(uriVariables),也可以放到http的body里面,当然一般来说post的数据放到body里面比较正规,也比较好,因为这样数据相对不会暴露。
5.3、exchange方法可以发多种类型的HTTP请求,并且需要传request对象。
5.4、请求参数中常用的url一般都是String, 所以url参数类型是URL的用的少,可以不管。
六、源码:
废话不多说,举个栗子。
6.1、配置文件application.yml:
com:
http:
link: http://127.0.0.1:8081/user
connect-timeout: 10000
read-timeout: 60000
6.2、定义HttpServiceConfig:
@Configuration
public class HttpServiceConfig {
public static final Logger log = LoggerFactory.getLogger(HttpServiceConfig.class);
@Value("${com.http.link:}")
private String httpUrl;
@Value("${com.http.connect-timeout:}")
private int connectTimeout;
@Value("${com.http.read-timeout:}")
private int readTimeout;
//Use restTemplateBuilder prepared by Spring Boot
@Bean
public HttpServiceClient httpServiceClient(final RestTemplateBuilder restTemplateBuilder){
RestTemplate restTemplate = restTemplateBuilder.rootUri(this.httpUrl)
.setReadTimeout(Duration.ofMillis(this.readTimeout))
.setConnectTimeout(Duration.ofMillis(this.connectTimeout))
.build();
HttpServiceClient httpServiceClient = new HttpServiceClient();
httpServiceClient.setRestTemplate(restTemplate);
return httpServiceClient;
}
}
6.3、Http客户端实现类HttpServiceClient:
public class HttpServiceClient {
public static final Logger log = LoggerFactory.getLogger(HttpServiceClient.class);
public static final String GET_HTTP_RESOURCE_PATH = "/queryUserById/{userid}";
public static final String GET_HTTP_RESOURCE_PATH1 = "/queryUserList?pageNow={pageNow}&pageSize={pageSize}";
public static final String GET_HTTP_RESOURCE_PATH2 = "/updateUser/{id}";
public static final String GET_HTTP_RESOURCE_PATH3 = "/createUser";
public static final String GET_HTTP_RESOURCE_PATH4 = "/deleteUser/{id}";
private RestTemplate restTemplate;
public String getUserById(int userid) throws IOException {
String response = null;
response = this.restTemplate.getForObject(HttpServiceClient.GET_HTTP_RESOURCE_PATH,String.class,userid);
log.info("response: "+ response);
JSONObject responseBody = JSON.parseObject(response);
log.info("responseBody: "+responseBody);
String message = responseBody.getString("message");
log.info("message: "+message);
String user = responseBody.getString("object");
log.info("user: "+user);
log.info("Test boolean: "+StringUtils.isNotBlank(user));
String username = null;
if(StringUtils.isNotBlank(user)) {
JSONObject jsonuser = JSON.parseObject(user);
log.info("jsonuser: " + jsonuser);
username = jsonuser.getString("username");
}
return username;
}
public String getUserList(int pageNow, int pageSize) throws IOException{
ResponseEntity<String> response = null;
// 方法1:使用getForEntity方法
response = this.restTemplate.getForEntity(HttpServiceClient.GET_HTTP_RESOURCE_PATH1,String.class,pageNow,pageSize);
// 方法2:使用exchange方法
// HttpEntity<String> requestEntity = null;
// response = this.restTemplate.exchange(HttpServiceClient.GET_HTTP_RESOURCE_PATH1,HttpMethod.GET,requestEntity,String.class,pageNow,pageSize);
log.info("response: "+ response);
JSONObject responseBody = JSON.parseObject(response.getBody());
log.info("responseBody: "+responseBody);
String message = responseBody.getString("message");
log.info("message: "+message);
String user = responseBody.getString("object");
log.info("user: "+user);
return user;
}
public String updateUser(int id, String token, User user) throws IOException{
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "application/json;charset=UTF-8");
headers.add("token",token);
String body = JSON.toJSONString(user);
log.info("body:"+body);
HttpEntity<String> requestEntity = new HttpEntity<>(body,headers);
ResponseEntity<String> response = null;
// 方法1:使用postForEntity方法
response = this.restTemplate.postForEntity(HttpServiceClient.GET_HTTP_RESOURCE_PATH2,requestEntity,String.class,id);
// 方法2:使用exchange方法
// response = this.restTemplate.exchange(HttpServiceClient.GET_HTTP_RESOURCE_PATH2,HttpMethod.POST,requestEntity,String.class,id);
log.info("response: "+ response);
JSONObject responseBody = JSON.parseObject(response.getBody());
log.info("responseBody: "+responseBody);
String message = responseBody.getString("message");
log.info("message: "+message);
String result = responseBody.getString("object");
log.info("result: "+result);
return result;
}
public String createUser(User user) throws IOException{
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "application/json;charset=UTF-8");
String body = JSON.toJSONString(user);
log.info("body:"+body);
HttpEntity<String> requestEntity = new HttpEntity<>(body,headers);
// 方法1:使用postForObject方法
String response = null;
response = this.restTemplate.postForObject(HttpServiceClient.GET_HTTP_RESOURCE_PATH3,requestEntity,String.class);
log.info("response: "+ response);
JSONObject responseBody = JSON.parseObject(response);
// 方法2:使用exchange方法
// ResponseEntity<String> response = null;
// response = this.restTemplate.exchange(HttpServiceClient.GET_HTTP_RESOURCE_PATH3,HttpMethod.POST,requestEntity,String.class);
// log.info("response: "+ response);
// JSONObject responseBody = JSON.parseObject(response.getBody());
// log.info("responseBody: "+responseBody);
String message = responseBody.getString("message");
log.info("message: "+message);
String result = responseBody.getString("object");
log.info("result: "+result);
return result;
}
public String deleteUser(int id) throws IOException{
HttpEntity<String> requestEntity = null;
ResponseEntity<String> response = null;
response = this.restTemplate.exchange(HttpServiceClient.GET_HTTP_RESOURCE_PATH4,HttpMethod.DELETE,requestEntity,String.class,id);
log.info("response: "+ response);
JSONObject responseBody = JSON.parseObject(response.getBody());
log.info("responseBody: "+responseBody);
String message = responseBody.getString("message");
log.info("message: "+message);
String result = responseBody.getString("object");
log.info("result: "+result);
return result;
}
/**
* @Description: The restTemplate to set
* @param restTemplate
*/
public void setRestTemplate(final RestTemplate restTemplate){this.restTemplate = restTemplate;}
}