持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第15天,点击查看活动详情
配置
RestTemplate 使用 org.springframework.http.client.SimpleClientHttpRequestFactory建立 java.net.HttpURLConnection;后者采用 HttpURLConnection 的默认超时配置HttpURLConnection 超时属性。
@Configuration
public class RestTemplateConfiguration {
@Bean
public RestTemplate restTemplate() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
httpRequestFactory.setConnectionRequestTimeout(30 * 1000);
httpRequestFactory.setConnectTimeout(2 * 60 * 1000);
httpRequestFactory.setReadTimeout(10 * 60 * 1000);
return new RestTemplate(httpRequestFactory);
}
同时也可使用配置中心, 动态设置超时时间;高并发采用HttpClient连接池。
@Configuration
public class HttpRestTemplateConfig {
@Autowired
private HttpPoolProperties httpPoolProperties;//配置中心属性
@Bean
public RestTemplate restTemplate() {
return new RestTemplate(httpRequestFactory());
}
@Bean
public ClientHttpRequestFactory httpRequestFactory() {
return new HttpComponentsClientHttpRequestFactory(httpClient());
}
@Bean
public HttpClient httpClient() {
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", SSLConnectionSocketFactory.getSocketFactory())
.build();
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
connectionManager.setMaxTotal(httpPoolProperties.getMaxTotal());
connectionManager.setDefaultMaxPerRoute(httpPoolProperties.getMaxPerRoute());
connectionManager.setValidateAfterInactivity(httpPoolProperties.getInactivity());
RequestConfig requestConfig = RequestConfig.custom()
//服务器返回数据(response)的时间,超过抛出read timeout
.setSocketTimeout(httpPoolProperties.getSocketTimeout())
//连接上服务器(握手成功)的时间,超出抛出connect timeout
.setConnectTimeout(httpPoolProperties.getConnTimeOut())
//从连接池中获取连接的超时时间,超时间未拿到可用连接,会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool
.setConnectionRequestTimeout(httpPoolProperties.getConnReqTimeOut())
.build();
return HttpClientBuilder.create()
.setDefaultRequestConfig(requestConfig)
.setConnectionManager(connectionManager)
.build();
}
}
设置请求头
header(HttpHeaders.COOKIE,"key1=value1")//添加 cookie
HttpHeaders headers = new HttpHeaders(); // http请求头
headers.setContentType(MediaType.APPLICATION_JSON_UTF8); // 请求头设置属性
HttpEntity> requestEntity = new HttpEntity<>(userList,headers);//userList这个就是提交的数据List集合
String forObject = restTemplate.postForObject(url, requestEntity, String.class);//url 是提交的后台路径
发送请求
getForObject
optionsForAllow 分为一组,这类方法是常规的 Rest API(GET、POST、DELETE 等)方法调用;
//url 请求路径路径中可以添加参数 List.class标识返回数据类型
restTemplate.getForEntity(url, List.class);
通过 GET 方式调用,返回一个 String 值,还可以给 URL 变量设置值(也可通过 uriTemplateHandler 这个属性自定义)
Map<String, String> params = Collections.singletonMap("hotel", "42");
String result = restTemplate.getForObject(url, String.class, params);
//restTemplate 会根据 params 的具体类型,调用合适的 HttpMessageConvert 将请求参数写到请求体 body 中,并在请求头中添加合适的 content-type;
// 也会根据 responseType 的类型(本列子中是 JSONObject),设置 head 中的 accept 字段,当响应返回的时候再调用合适的 HttpMessageConvert 进行响应转换
ResponseEntity<JSONObject> responseEntity=restTemplate.postForEntity(url,params,JSONObject.class);
int statusCodeValue = responseEntity.getStatusCodeValue();
HttpHeaders headers = responseEntity.getHeaders();
JSONObject body = responseEntity.getBody();
JSONObject result = restTemplate.postForObject(scheduleUrl, reqEntity, JSONObject.class);
JSONArray obj = result.getJSONArray("dataList");
if (obj != null && obj.size() > 0) {
List<RmPersonInfoDto> personInfoDtos = JSONArray.parseArray(JSON.toJSONString(obj), RmPersonInfoDto.class);
log.debug("personInfoDtos = {}", personInfoDtos);
partnerScheduleDataService.syncEmployees(personInfoDtos);
}
execute:通过 callback 接口,可以对请求和返回做更加全面的自定义控制。
execute方法是RestTemplate的核心方法,含设置String类型请求地址url、HttpMethod类型的请求方法method、在请求发送前设置请求头部RequestCallback类型的requestCallback对象、响应接收处理ResponseExtractor类型的responseExtractor对象以及设置请求参数的各个Object类型的URIVariables对象。execute方法的核心是doExecute方法。
@Nullable
public <T> T execute(String url, HttpMethod method, @Nullable RequestCallback requestCallback, @Nullable ResponseExtractor<T> responseExtractor, Object... uriVariables) throws RestClientException {
URI expanded = this.getUriTemplateHandler().expand(url, uriVariables);
return this.doExecute(expanded, method, requestCallback, responseExtractor);
}
exchange
接收一个 RequestEntity 参数,可以自己设置 HTTP method,URL,headers 和 body,返回 ResponseEntity;
String bodyData = new String(JSON.toJSONString(req).getBytes("UTF-8"), "UTF-8");
HttpEntity<String> requestEntity = new HttpEntity<String>(bodyData, requestHeaders);
ResponseEntity<List<PartnerEmployee>> response = restTemplate.exchange(scheduleUrl, HttpMethod.POST, requestEntity, new ParameterizedTypeReference<List<PartnerEmployee>>() {});
List<PartnerEmployee> employeeList = response.getBody();
拦截器配置和ErrorHandler 配置
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate(httpRequestFactory());
List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();
interceptors.add(new MyInterceptor());
//设置拦截器
restTemplate.setInterceptors(interceptors);
//设置HttpMessageConverter
restTemplate.setErrorHandler(new MyErrorHander());
//设置HttpMessageConverter
restTemplate.setMessageConverters(new );
return restTemplate;
}
class MyErrorHander extends DefaultResponseErrorHandler{
public MyErrorHander() {
super();
}
@Override
public boolean hasError(ClientHttpResponse response) throws IOException {
return super.hasError(response);
}
@Override
public void handleError(ClientHttpResponse response) throws IOException {
HttpStatus statusCode = HttpStatus.resolve(response.getRawStatusCode());
if (statusCode == null) {
throw new UnknownHttpStatusCodeException(response.getRawStatusCode(), response.getStatusText(),
response.getHeaders(), getResponseBody(response), getCharset(response));
}
handleError(response, statusCode);
}
@Override
protected void handleError(ClientHttpResponse response, HttpStatus statusCode) throws IOException {
switch (statusCode.series()) {
case CLIENT_ERROR:
HttpClientErrorException exp1 = new HttpClientErrorException(statusCode, response.getStatusText(), response.getHeaders(), getResponseBody(response), getCharset(response));
log.error("客户端调用异常",exp1);
throw exp1;
case SERVER_ERROR:
HttpServerErrorException exp2 = new HttpServerErrorException(statusCode, response.getStatusText(),
response.getHeaders(), getResponseBody(response), getCharset(response));
log.error("服务端调用异常",exp2);
throw exp2;
default:
UnknownHttpStatusCodeException exp3 = new UnknownHttpStatusCodeException(statusCode.value(), response.getStatusText(),
response.getHeaders(), getResponseBody(response), getCharset(response));
log.error("网络调用未知异常");
throw exp3;
}
}
}
class MyInterceptor implements ClientHttpRequestInterceptor {
@Override
public ClientHttpResponse intercept(org.springframework.http.HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
log.info("enter interceptor...");
return execution.execute(request,body);
}
}