RestTemplate
1.1 简介
常见的的Http调用工具:JDK的HttpURLConnection、Square的OkHttp、Apache的HttpClient。由于这些工具使用起来,相对复杂,并且需要手动回收资源,因此Spring提供了一个Http调用工具RestTemplate。RestTemplate 是Spring3.0 开始支持的HTTP 请求工具,提供了常见的 REST请求方案的模板,例如 GET、POST 请求、PUT 请求、DELETE 请求以及一些通用的请求执行方法 exchange 以及execute。RestTemplate实现RestOperations 接口,RestOptions定义了基本的 RESTful 操作,这些操作在 RestTemplate 中都得到了实现。
1.2 特性
①简化HTTP请求:RestTemplate通过提供简单且易用的API,使得发送GET、POST、PUT、DELETE等HTTP请求变得简单。
②支持多种数据格式:能够处理不同的数据格式,如JSON、XML等,这使得RestTemplate在处理各种数据交换场景时具有高度的灵活性。
③请求定制化扩展支持:提供责任链的拦截机制,自定义请求扩展;提供三方外调工具的支持,支持集成HttpClient和OkHttp满足复杂的请求场景需求。
④复用连接,减少连接损耗:由于HTTP 1.1不支持多路复用,RestTemplate通过连接池技术,减少了频繁建立连接所带来的性能损耗。
1.3 使用示例
1.3.1 GET请求
通过RestTemplate发送GET协议请求,Spring提供了一下3种方式:getForObject - 获取协议响应体、getForEntity - 获取完整响应报文、exchange - 通用的http调用API 。
(1)发送不带请求参数的GET请求
public void testGet1() {
String baseUrl = "http://exmaple.com/context/path";
String result = restTemplate.getForObject(baseUrl, String.class);
log.info(result);
ResponseEntity<String> responseHttpEntity = restTemplate.getForEntity(baseUrl, String.class);
log.info(responseHttpEntity.getBody());
ResponseEntity<String> responseHttpEntity1 = restTemplate.exchange(baseUrl, HttpMethod.GET, new HttpEntity<Void>((Void) null), String.class);
log.info(responseHttpEntity.getBody());
}
(2)发送带路径参数的GET请求
public void testGet2() {
String url1 = UriComponentsBuilder.fromHttpUrl("http://exmaple.com/context/path").pathSegment("pathVar1", "pathVar2", "pathVar3").build().toUriString();
String forObject = restTemplate.getForObject(url1, String.class);
log.info(forObject);
String url2 = "http://exmaple.com/context/path";
ResponseEntity<String> responseHttpEntity = restTemplate.getForEntity(url2, String.class, "pathVar1", "pathVar2", "pathVar3");
log.info(responseHttpEntity.getBody());
String url3 = UriComponentsBuilder.newInstance().scheme("http").host("exmaple.com").port(80).path("/context/path").pathSegment("pathVar1", "pathVar2", "pathVar3").build().toUriString();
ResponseEntity<String> responseHttpEntity1 = restTemplate.exchange(url3, HttpMethod.GET, new HttpEntity<Void>((Void) null), String.class);
log.info(responseHttpEntity.getBody());
}
(3)发送带请求参数的GET请求
public void testGet3() {
String url1 = UriComponentsBuilder.fromHttpUrl("http://exmaple.com/context/path").queryParam("paramVar1", "param1").queryParam("paramVar2", "param2").queryParam("paramVar3", "param3").build().toUriString();
String forObject = restTemplate.getForObject(url1, String.class);
log.info(forObject);
String url2 = "http://exmaple.com/context/path?paramVar1=param1¶mVar2=param2¶mVar3=param3";
ResponseEntity<String> responseHttpEntity = restTemplate.getForEntity(url2, String.class);
log.info(responseHttpEntity.getBody());
String url3 = UriComponentsBuilder.newInstance().scheme("http").host("exmaple.com").port(80).path("/context/path").queryParam("paramVar1", "param1").queryParam("paramVar2", "param2").queryParam("paramVar3", "param3").build().toUriString();
ResponseEntity<String> responseHttpEntity1 = restTemplate.exchange(url3, HttpMethod.GET, new HttpEntity<Void>((Void) null), String.class);
log.info(responseHttpEntity.getBody());
}
1.3.2 POST请求
(1)字符串/复杂对象
public void testPost() {
String url = "http://exmaple.com/context/path";
HttpHeaders headers = new HttpHeaders();
headers.set("Content-Type", "application/json");
CustomRequestBody requestBody = new CustomRequestBody("xuyuan", 25);
HttpEntity<CustomRequestBody> requestEntity = new HttpEntity<>(requestBody, headers);
String result = restTemplate.postForObject(url, requestEntity, String.class);
log.info(result);
ResponseEntity<String> responseHttpEntity1 = restTemplate.postForEntity(url, requestEntity, String.class);
log.info(responseHttpEntity1.getBody());
ResponseEntity<String> responseHttpEntity2 = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
log.info(responseHttpEntity2.getBody());
}
(2)表单
public void testPost2() {
String url = "http://exmaple.com/context/path";
HttpHeaders headers = new HttpHeaders();
headers.set("Content-Type", "application/json");
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("name", "xuyuan");
map.add("age", "25");
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(map, headers);
String result = restTemplate.postForObject(url, requestEntity, String.class);
log.info(result);
ResponseEntity<String> responseHttpEntity1 = restTemplate.postForEntity(url, requestEntity, String.class);
log.info(responseHttpEntity1.getBody());
ResponseEntity<String> responseHttpEntity2 = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
log.info(responseHttpEntity2.getBody());
}
(3)文件上传
public void testPost3() {
String url = "http://exmaple.com/context/path";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
File file = new File("/upload/file.txt");
Resource resource = new FileSystemResource(file);
MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
map.add("file", resource);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(map, headers);
String result = restTemplate.postForObject(url, requestEntity, String.class);
log.info(result);
ResponseEntity<String> responseHttpEntity1 = restTemplate.postForEntity(url, requestEntity, String.class);
log.info(responseHttpEntity1.getBody());
ResponseEntity<String> responseHttpEntity2 = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
log.info(responseHttpEntity2.getBody());
}
1.3.3 添加报文头
RestTemplate添加协议头通过HttpHeaders实现。示例如下:
public void addHeader() {
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "application/json");
headers.add("Accept", "application/json");
headers.add("Accept-Encoding", "gzip, deflate");
headers.add("Accept-Language", "zh-CN,zh;q=0.9");
headers.add("Connection", "keep-alive");
HttpEntity<String> requestHttpEntity = new HttpEntity<>("test", headers);
}
1.3.4 定制化请求
RestTemplate支持多种Http客户端工具。
(1)基于JDK的HttpURLConnection创建定制化的RestTemplate
@Bean("httpURLConnectionRestTemplate")
public RestTemplate customRestTemmplateConfig1() {
SimpleClientHttpRequestFactory simpleClientHttpRequestFactory = new SimpleClientHttpRequestFactory();
simpleClientHttpRequestFactory.setConnectTimeout(3000);
simpleClientHttpRequestFactory.setReadTimeout(3000);
RestTemplate restTemplate1 = new RestTemplate(simpleClientHttpRequestFactory);
restTemplate.getMessageConverters().add(null); // 添加自定义的报文序列化转换器
List<ClientHttpRequestInterceptor> interceptors = restTemplate.getInterceptors();
interceptors.add((request, body, execution) -> {
log.info("请求前处理");
ClientHttpResponse response = execution.execute(request, body);
log.info("请求后处理");
return response;
});// 拦截责任链添加自定义拦截逻辑
return restTemplate1;
}
(2)基于Apache HttpClient创建定制化的RestTemplate
@Bean("httpClientRestTemplate")
public RestTemplate customRestTemmplateConfig2() {
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", SSLConnectionSocketFactory.getSocketFactory()).build();
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
connectionManager.setMaxTotal(100);
connectionManager.setDefaultMaxPerRoute(20);
connectionManager.setValidateAfterInactivity(100000);
RequestConfig customRequestConfig = RequestConfig.custom().setConnectionRequestTimeout(3000).setSocketTimeout(3000).setConnectTimeout(1000).build();
CloseableHttpClient client = HttpClients.custom().setDefaultRequestConfig(customRequestConfig).setConnectionManager(connectionManager).build();
ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(client);
return new RestTemplate(requestFactory);
}
(3)基于Square的OkHttp创建定制化的RestTemplate
@Bean("okHttpRestTemplate")
public RestTemplate customRestTemmplateConfig3() {
OkHttpClient okHttpClient = new OkHttpClient.Builder().readTimeout(3, TimeUnit.SECONDS) // 读超时时间
.writeTimeout(3, TimeUnit.SECONDS) // 写超时时间
.connectTimeout(1, TimeUnit.SECONDS) // 连接超时时间
.callTimeout(5, TimeUnit.SECONDS) // 响应超时时间
.addInterceptor(new OKHttpExample.CustomInterceptor()) // 自定义拦截器
.cache(new Cache(new File(""), 1024 * 1024 * 100)) // 自定义缓存,CacheInterceptor会使用
.cookieJar(new OKHttpExample.CustomCookieJar()) // 自定义Cookie,BridgeInterceptor会使用
.followRedirects(true) // 支持RetryAndFollowUpInterceptor的重定向
.followSslRedirects(true) // 支持SSL重定向
.retryOnConnectionFailure(true) // 支持RetryAndFollowUpInterceptor的重试
.connectionPool(new ConnectionPool(10, 600, TimeUnit.SECONDS)).build();
ClientHttpRequestFactory okHttp3ClientHttpRequestFactory = new OkHttp3ClientHttpRequestFactory(okHttpClient);
return new RestTemplate(okHttp3ClientHttpRequestFactory);
}