作用
用于http请求,且封装了不同http框架,
1.jdk api //默认
2.httpclient //1.连接池2.超时
3.okhttp //异步
RestTemplate,本身不实现http请求,http请求的底层实现是其他框架,RestTemplate的核心有两个
1.更方便http请求
2.且可以切换不同http框架
不同http框架,提供的功能不完全一样
应用层-使用
步骤
1.获取模板
2.调用模板的方法
List<AuditResult> auditResultList = null; //响应数据
try {
auditResultList = HttpClientUtil.getTemplate().postForObject(url,
audits //入参数据的类型一般是map/list, List.class //响应数据的数据类型);
} catch (Throwable e) {
log.error(msg + " 调用风控系统超时!" + e.getMessage());
return;
}
切换默认jdk api为httpclient
默认是jdk api,为什么要切换?
因为有更多的配置项,比如
1.连接池
2.超时
如何切换?
需要简单封装一下,
1.用httpclient的客户端请求类CloseableHttpClient覆盖默认的
2.配置连接池
3.配置超时
package xxx.util;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.client.RestTemplate;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
public class HttpClientUtil {
//连接池配置项
private static int POOLSIZE = 150;// 连接池
private static PoolingHttpClientConnectionManager connMgr = null;
//超时配置项
private final static int SOCKETTIMEOUT = 1000;// 读取响应超时时间
private final static int CONNECTIONREQUESTTIMEOUT = 3000; // 从连接池获取连接超时时间
private final static int CONNECTTIMEOUT = 2000;// 连接超时时间
public static RestTemplate getTemplate() {
CloseableHttpClient httpClient = getConnection();
RestTemplate template = new RestTemplate(
new HttpComponentsClientHttpRequestFactory(httpClient)); //用httpclient的客户端请求类CloseableHttpClient覆盖默认的
List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
// 采用fastjson进行数据转换
FastJsonHttpMessageConverter fastjson = new FastJsonHttpMessageConverter();
fastjson.setFeatures(SerializerFeature.WriteClassName,
SerializerFeature.BrowserCompatible,
SerializerFeature.DisableCircularReferenceDetect);
converters.add(fastjson);
template.setMessageConverters(converters);
return template;
}
private static CloseableHttpClient getConnection() {
if (connMgr == null) {
// 创建链接池。连接池可以并发请求100个连接
connMgr = new PoolingHttpClientConnectionManager();
connMgr.setMaxTotal(POOLSIZE + 1);
connMgr.setDefaultMaxPerRoute(POOLSIZE);
}
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(CONNECTIONREQUESTTIMEOUT)
.setConnectTimeout(CONNECTTIMEOUT)
.setSocketTimeout(SOCKETTIMEOUT).build(); //配置超时
CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(connMgr) //配置连接池
.setDefaultRequestConfig(requestConfig).build();
return httpClient;
}
}
源码
流程是
1.获取客户端
2.请求服务器
不管是哪一种http框架,流程都是一样。核心步骤就是这两个。
public class RestTemplate extends InterceptingHttpAccessor implements RestOperations {
protected <T> T doExecute(URI url, HttpMethod method, RequestCallback requestCallback, ResponseExtractor<T> responseExtractor) throws RestClientException {
Assert.notNull(url, "'url' must not be null");
Assert.notNull(method, "'method' must not be null");
ClientHttpResponse response = null;
Object var7;
try {
ClientHttpRequest request = this.createRequest(url, method); //获取http请求客户端
if (requestCallback != null) {
requestCallback.doWithRequest(request);
}
response = request.execute(); //请求服务器
if (!this.getErrorHandler().hasError(response)) {
this.logResponseStatus(method, url, response);
} else {
this.handleResponseError(method, url, response);
}
if (responseExtractor == null) {
var7 = null;
return var7;
}
var7 = responseExtractor.extractData(response);
} catch (IOException var11) {
throw new ResourceAccessException("I/O error on " + method.name() + " request for \"" + url + "\":" + var11.getMessage(), var11);
} finally {
if (response != null) {
response.close();
}
}
return var7;
}
由于切换了http框架,客户端类现在是CloseableHttpClient(httpclient框架的客户端类)。其实就是两个步骤,
1.封装的时候,用httpclient的客户端请求类CloseableHttpClient覆盖默认的
2.底层请求服务器的时候,就使用切换之后的客户端
设计模式
看名字是模板模式,spring里还有其他的类似名字,JdbcTemplate(mybatis/hibernate等dao框架)、RedisTemplate。
RestTemplate也是不同http框架(jdk api/httpclient/okhttp)的封装。
slf也是对不同日志框架(log4j等)的封装,叫门面模式。
不管模式名字叫什么,本质是
1.自己不实现,只是封装其他框架
底层实现是框架
2.可以切换不同框架
不同框架,提供的功能不完全一样
准确的说,模式名字应该叫切换模式,即
1.封装了不同框架
2.然后,实现了对不同框架的切换
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。