下面总结一下SpringBoot项目使用RestTemplate发送网络请求
一、介绍
RestTemple是Spring提供的用于访问Http请求的客户端,RestTemple提供了多种简洁的远程访问服务的方法,省去了很多无用的代码。RestTemplate提供更高等级的符合HTTP的六种主要方法,可以很简单的调用RESTful服务。
二、使用
1:创建RestTemplate
默认配置
@Configuration
public class RestTempleConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
简单配置
@Bean(name = "restTemplate")
public RestTemplate restTemplate(@Qualifier("simpleClientHttpRequestFactory") HttpComponentsClientHttpRequestFactory factory) {
RestTemplate restTemplate = new RestTemplate(factory);
// 使用 utf-8 编码集的 conver 替换默认的 conver(默认的 string conver 的编码集为"ISO-8859-1")
List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
Iterator<HttpMessageConverter<?>> iterator = messageConverters.iterator();
while (iterator.hasNext()) {
HttpMessageConverter<?> converter = iterator.next();
if (converter instanceof StringHttpMessageConverter) {
iterator.remove();
}
}
messageConverters.add(new StringHttpMessageConverter(StandardCharsets.UTF_8));
// 默认的 RestTemplate 有个机制是请求状态码非200 就抛出异常,会中断接下来的操作。如果不想中断对结果数据得解析,可以通过覆盖默认的 ResponseErrorHandler
restTemplate.setErrorHandler(new ResponseErrorHandler() {
@Override
public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
return !clientHttpResponse.getStatusCode().is2xxSuccessful();
}
@Override
public void handleError(ClientHttpResponse clientHttpResponse) throws IOException {
}
});
return restTemplate;
}
@Bean(name = "simpleClientHttpRequestFactory")
public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
// 建立连接所用的时间
factory.setReadTimeout(12000);//单位为ms
// 建立连接后从服务器读取到可用资源所用的时间
factory.setConnectTimeout(12000);//单位为ms
// 设置代理
// setProxy(new java.net.Proxy(java.net.Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 8888)));
return factory;
}
配置支持https
@Bean(name = "restTemplate")
public RestTemplate restTemplate(@Qualifier("httpsFactory") HttpComponentsClientHttpRequestFactory factory) {
RestTemplate restTemplate = new RestTemplate(factory);
// 使用 utf-8 编码集的 conver 替换默认的 conver(默认的 string conver 的编码集为"ISO-8859-1")
List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
Iterator<HttpMessageConverter<?>> iterator = messageConverters.iterator();
while (iterator.hasNext()) {
HttpMessageConverter<?> converter = iterator.next();
if (converter instanceof StringHttpMessageConverter) {
iterator.remove();
}
}
messageConverters.add(new StringHttpMessageConverter(StandardCharsets.UTF_8));
// 默认的 RestTemplate 有个机制是请求状态码非200 就抛出异常,会中断接下来的操作。如果不想中断对结果数据得解析,可以通过覆盖默认的 ResponseErrorHandler
restTemplate.setErrorHandler(new ResponseErrorHandler() {
@Override
public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
return !clientHttpResponse.getStatusCode().is2xxSuccessful();
}
@Override
public void handleError(ClientHttpResponse clientHttpResponse) throws IOException {
}
});
return restTemplate;
}
@Bean(name = "httpsFactory")
public HttpComponentsClientHttpRequestFactory httpComponentsClientHttpRequestFactory() {
try {
CloseableHttpClient httpClient = HttpClientUtils.acceptsUntrustedCertsHttpClient();
HttpComponentsClientHttpRequestFactory httpsFactory =
new HttpComponentsClientHttpRequestFactory(httpClient);
httpsFactory.setReadTimeout(20000); // 建立连接所用的时间
httpsFactory.setConnectTimeout(20000);// 建立连接后从服务器读取到可用资源所用的时间
return httpsFactory;
} catch (Exception e) {
log.info(e.getMessage());
return null;
}
}
// HttpClientUtils类
public static CloseableHttpClient acceptsUntrustedCertsHttpClient() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
// 异常重试次数3次
HttpClientBuilder b = HttpClientBuilder.create().setRetryHandler(new DefaultHttpRequestRetryHandler(3, false));
// HttpClientBuilder b = HttpClientBuilder.create();
// 设置允许所有证书的信任策略
SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
@Override
public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
return true;
}
}).build();
b.setSSLContext(sslContext);
// 忽略主机名检查
// use SSLConnectionSocketFactory.getDefaultHostnameVerifier(), if you don't want to weaken
HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
// 以下是特殊部分:
// 需要创建SSL套接字工厂,用我们弱化的“信任策略”;并创建一个注册表,来注册它。
SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", sslSocketFactory)
.build();
// 现在,我们使用注册表创建连接管理器。
// 允许多线程使用
PoolingHttpClientConnectionManager connMgr = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
connMgr.setMaxTotal(200);// 连接池最大连接数
connMgr.setDefaultMaxPerRoute(100);// 每个主机的并发
b.setConnectionManager(connMgr);
// b.setProxy(new HttpHost("127.0.0.1", 8888));
// 最后,构建HttpClient;
CloseableHttpClient client = b.build();
return client;
}
2:使用
常用方法
getForEntity() 发送一个HTTP GET请求,返回的ResponseEntity包含了响应体所映射成的对象
getForObject() 发送一个HTTP GET请求,返回的请求体将映射为一个对象
postForEntity() POST 数据到一个URL,返回包含一个对象的ResponseEntity,这个对象是从响应体中映射得
到的
postForObject() POST 数据到一个URL,返回根据响应体匹配形成的对象
delete() 在特定的URL上对资源执行HTTP DELETE操作
exchange() 在URL上执行特定的HTTP方法,返回包含对象的ResponseEntity,这个对象是从响应体中
映射得到的
execute() 在URL上执行特定的HTTP方法,返回一个从响应体映射得到的对象
headForHeaders() 发送HTTP HEAD请求,返回包含特定资源URL的HTTP头
optionsForAllow() 发送HTTP OPTIONS请求,返回对特定URL的Allow头信息
postForLocation() POST 数据到一个URL,返回新创建资源的URL
put() PUT 资源到特定的URL
// GET请求
ResponseEntity<List> responseEntity = restTemplate.getForEntity("http://localhost/getAll", List.class)
ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://localhost/get/{id}", String.class, id)
// GET带参数请求
HashMap<String, String> map = new HashMap<>();
map.put("id",id);
ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://localhost/get/{id}", String.class, map)
// POST请求
ResponseEntity<String> responseEntity = restTemplate.postForEntity("http://localhost/save", entity, String.class);
// POST带参数
ResponseEntity<String> responseEntity = restTemplate.postForEntity("http://localhost/saveByType/{type}", entity, String.class, type);
// POST多参数
HashMap<String, String> map = new HashMap<>();
map.put("type", type);
ResponseEntity<String> responseEntity = restTemplate.postForEntity("http://localhost/saveByType/{type}", entity, String.class,map);
发送带请求头的请求
// GET
HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity(null);
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("http://xxxx");
for (Map.Entry<String, Object> entry : paramMap.entrySet()) {
builder.queryParam(entry.getKey(), entry.getValue());
}
// url地址中有特殊的转义字符,如果使用resttemplate的方法的话,其默认会进行转义%=>%25使用builder.build(true).toUri()可以使其不被转义
ResponseEntity<XxxDTO> re = restTemplate.exchange(builder.build(true).toUri(), HttpMethod.GET, request, XxxDTO.class);
// POST form
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); // 默认方式可不设置
MultiValueMap<String, Object> requestMap = new LinkedMultiValueMap<String, Object>();
for (Map.Entry<String, Object> entry : paramMap.entrySet()) {
requestMap.add(entry.getKey(), entry.getValue());
}
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<MultiValueMap<String, Object>>(requestMap, headers);
ResponseEntity<XxxDTO> re = restTemplate.postForEntity("http://xxx", requestEntity, XxxDTO.class);
// POST JSON
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
HashMap<String, Object> params = new HashMap<>();
// String jsonStr = JSONUtil.toJsonStr(paramDTO);
// HttpEntity<String> requestEntity= new HttpEntity<String>(jsonStr , headers);
// JSONObject json = new JSONObject();
// json.put("key", "");
// HttpEntity<String> requestEntity = new HttpEntity<String>(json.toString(), headers);
params.put("name", name);
HttpEntity requestEntity= new HttpEntity<>(params, headers);
ResponseEntity<XxxDTO> re = restTemplate.postForEntity("http://xxx", requestEntity, XxxDTO.class);