restTemplate配置及使用過(guò)程
1 場(chǎng)景
java開(kāi)發(fā)中,使用http連接,訪問(wèn)第三方網(wǎng)絡(luò)接口,通常使用的連接工具為HttpClient和OKHttp。
這兩種連接工具,使用起來(lái)比較復(fù)雜,新手容易出問(wèn)題。如果使用spring框架,可以使用restTemplate來(lái)進(jìn)行http連接請(qǐng)求。
restTemplate默認(rèn)的連接方式是java中的HttpConnection,可以使用ClientHttpRequestFactory指定不同的HTTP連接方式。
2 依賴
maven依賴如下:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.7</version>
</dependency>
3 配置
import org.apache.http.client.HttpClient;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
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;
@Configuration
public class RestTemplateConfig {
/**
* http連接管理器
* @return
*/
@Bean
public HttpClientConnectionManager poolingHttpClientConnectionManager() {
/*// 注冊(cè)http和https請(qǐng)求
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ù)(每個(gè)主機(jī)的并發(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è)置默認(rèn)請(qǐng)求頭
/*List<Header> headers = new ArrayList<>();
headers.add(new BasicHeader("Connection", "Keep-Alive"));
httpClientBuilder.setDefaultHeaders(headers);*/
return httpClientBuilder.build();
}
/**
* 請(qǐng)求連接池配置
* @param httpClient
* @return
*/
@Bean
public ClientHttpRequestFactory clientHttpRequestFactory(HttpClient httpClient) {
HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
// httpClient創(chuàng)建器
clientHttpRequestFactory.setHttpClient(httpClient);
// 連接超時(shí)時(shí)間/毫秒(連接上服務(wù)器(握手成功)的時(shí)間,超出拋出connect timeout)
clientHttpRequestFactory.setConnectTimeout(5 * 1000);
// 數(shù)據(jù)讀取超時(shí)時(shí)間(socketTimeout)/毫秒(務(wù)器返回?cái)?shù)據(jù)(response)的時(shí)間,超過(guò)拋出read timeout)
clientHttpRequestFactory.setReadTimeout(10 * 1000);
// 連接池獲取請(qǐng)求連接的超時(shí)時(shí)間,不宜過(guò)長(zhǎng),必須設(shè)置/毫秒(超時(shí)間未拿到可用連接,會(huì)拋出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();
// 配置請(qǐng)求工廠
restTemplate.setRequestFactory(clientHttpRequestFactory);
return restTemplate;
}
}
4 使用
使用到的實(shí)體類如下:
@Data
@ToString
public class TempUser implements Serializable {
private String userName;
private Integer age;
}
4.1 GET請(qǐng)求
后臺(tái)接口代碼:
@RequestMapping("getUser")
public TempUser getUser(TempUser form) {
TempUser tempUser = new TempUser();
tempUser.setUserName(form.getUserName());
tempUser.setAge(form.getAge());
return tempUser;
}
4.1.1 普通訪問(wèn)
TempUser result = restTemplate.getForObject("http://localhost:8080/cs-admin/rest/getUser?userName=張三&age=18", TempUser.class);
4.1.2 返回HTTP狀態(tài)
ResponseEntity<TempUser> responseEntity = restTemplate.getForEntity("http://localhost:8080/cs-admin/rest/getUser?userName=張三&age=18", TempUser.class);
// 獲取狀態(tài)對(duì)象
HttpStatus httpStatus = responseEntity.getStatusCode();
// 獲取狀態(tài)碼
int statusCodeValue = responseEntity.getStatusCodeValue();
// 獲取headers
HttpHeaders httpHeaders = responseEntity.getHeaders();
// 獲取body
TempUser result = responseEntity.getBody();
4.1.3 映射請(qǐng)求參數(shù)
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("userName", "張三");
paramMap.put("age", 18);
TempUser result = restTemplate.getForObject("http://localhost:8080/cs-admin/rest/getUser?userName={userName}&age={age}", TempUser.class, paramMap);
4.2 POST請(qǐng)求
4.2.1 普通訪問(wèn)
后臺(tái)接口代碼:
RequestMapping("getPostUser")
public TempUser getPostUser(@RequestBody TempUser form) {
TempUser tempUser = new TempUser();
tempUser.setUserName(form.getUserName());
tempUser.setAge(form.getAge());
return tempUser;
}
(1)普通訪問(wèn)接口
TempUser param = new TempUser();
param.setUserName("張三");
param.setAge(18);
TempUser result = restTemplate.postForObject("http://localhost:8080/cs-admin/rest/getPostUser", param, TempUser.class);
(2)帶HEAD訪問(wèn)接口
// 請(qǐng)求頭信息
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.valueOf("application/json;charset=UTF-8"));
//headers.add("headParam1", "headParamValue");
// 請(qǐng)求體內(nèi)容
TempUser param = new TempUser();
param.setUserName("張三");
param.setAge(18);
// 組裝請(qǐng)求信息
HttpEntity<TempUser> httpEntity=new HttpEntity<>(param,headers);
TempUser result = restTemplate.postForObject("http://localhost:8080/cs-admin/rest/getPostUser", httpEntity, TempUser.class);
4.2.2 無(wú)請(qǐng)求體的訪問(wèn)
僅method為post,傳參方式仍然為get的param方式
后臺(tái)接口代碼:
@RequestMapping("getPostUserNoBody")
public TempUser getPostUserNoBody(TempUser form) {
TempUser tempUser = new TempUser();
tempUser.setUserName(form.getUserName());
tempUser.setAge(form.getAge());
return tempUser;
}
訪問(wèn)方式:
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("userName", "張三");
paramMap.put("age", 18);
TempUser result = restTemplate.postForObject("http://localhost:8080/cs-admin/rest/getPostUserNoBody?userName={userName}&age={age}", null, TempUser.class, paramMap);
System.out.println(result);
4.3 上傳文件
后臺(tái)接口代碼:
@RequestMapping("uploadFile")
public TempUser uploadFile(HttpServletRequest request, TempUser form) {
MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest) request;
//獲取文件信息
MultipartFile multipartFile = multipartHttpServletRequest.getFile("file");
TempUser tempUser = new TempUser();
if (multipartFile != null) {
tempUser.setUserName(form.getUserName()+" "+multipartFile.getOriginalFilename());
}
if(form!=null){
tempUser.setAge(form.getAge());
}
return tempUser;
}
訪問(wèn)方式:
// 文件
FileSystemResource file=new FileSystemResource("D:\\Elasticsearch權(quán)威指南(中文版).pdf");
// 設(shè)置請(qǐng)求內(nèi)容
MultiValueMap<String, Object> param=new LinkedMultiValueMap<>();
param.add("file", file);
// 其他參數(shù)
param.add("userName", "張三");
param.add("age", 18);
// 組裝請(qǐng)求信息
HttpEntity<MultiValueMap<String, Object>> httpEntity=new HttpEntity<>(param);
// 發(fā)送請(qǐng)求
TempUser result = restTemplate.postForObject("http://localhost:8080/cs-admin/rest/uploadFile", httpEntity, TempUser.class);
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Spring Security源碼解析之權(quán)限訪問(wèn)控制是如何做到的
Spring Security 中對(duì)于權(quán)限控制默認(rèn)已經(jīng)提供了很多了,但是,一個(gè)優(yōu)秀的框架必須具備良好的擴(kuò)展性,下面小編給大家介紹Spring Security源碼解析之權(quán)限訪問(wèn)控制是如何做到的,感興趣的朋友跟隨小編一起看看吧2021-05-05
完美解決request請(qǐng)求流只能讀取一次的問(wèn)題
這篇文章主要介紹了完美解決request請(qǐng)求流只能讀取一次的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-08-08
Java鎖升級(jí)機(jī)制超詳細(xì)講解(附實(shí)例代碼)
Java中的synchronized鎖會(huì)經(jīng)歷一個(gè)從無(wú)鎖到偏向鎖,再到輕量級(jí)鎖,最后到重量級(jí)鎖的升級(jí)過(guò)程,這種優(yōu)化稱為鎖升級(jí)或鎖膨脹,這篇文章主要介紹了Java鎖升級(jí)機(jī)制超詳細(xì)講解的相關(guān)資料,需要的朋友可以參考下2025-06-06
使用Java實(shí)現(xiàn)價(jià)格加密與優(yōu)化功能
在現(xiàn)代軟件開(kāi)發(fā)中,數(shù)據(jù)加密是一個(gè)非常重要的環(huán)節(jié),尤其是在處理敏感信息(如價(jià)格、用戶數(shù)據(jù)等)時(shí),本文將詳細(xì)介紹如何使用?Java?實(shí)現(xiàn)價(jià)格加密,并對(duì)代碼進(jìn)行優(yōu)化,需要的朋友可以參考下2025-01-01
一文帶你掌握J(rèn)ava8強(qiáng)大的StreamAPI
Java8API添加了一個(gè)新的抽象稱為流Stream,可以讓你以一種聲明的方式處理數(shù)據(jù)。Stream 使用一種類似用SQL 語(yǔ)句從數(shù)據(jù)庫(kù)查詢數(shù)據(jù)的直觀方式來(lái)提供一種對(duì) Java 集合運(yùn)算和表達(dá)的高階抽象。Stream API可以極大提高Java程序員的生產(chǎn)力,讓程序員寫出高效率、干凈、簡(jiǎn)潔的代碼2021-10-10

