前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >聊聊HttpComponentsHttpInvokerRequestExecutor

聊聊HttpComponentsHttpInvokerRequestExecutor

作者头像
code4it
发布2023-10-06 14:25:45
1350
发布2023-10-06 14:25:45
举报
文章被收录于专栏:码匠的流水账码匠的流水账

本文主要研究一下HttpComponentsHttpInvokerRequestExecutor

HttpComponentsHttpInvokerRequestExecutor

org/springframework/remoting/httpinvoker/HttpComponentsHttpInvokerRequestExecutor.java

代码语言:javascript
复制
public class HttpComponentsHttpInvokerRequestExecutor extends AbstractHttpInvokerRequestExecutor {

	private static final int DEFAULT_MAX_TOTAL_CONNECTIONS = 100;

	private static final int DEFAULT_MAX_CONNECTIONS_PER_ROUTE = 5;

	private static final int DEFAULT_READ_TIMEOUT_MILLISECONDS = (60 * 1000);


	private HttpClient httpClient;

	@Nullable
	private RequestConfig requestConfig;


	/**
	 * Create a new instance of the HttpComponentsHttpInvokerRequestExecutor with a default
	 * {@link HttpClient} that uses a default {@code org.apache.http.impl.conn.PoolingClientConnectionManager}.
	 */
	public HttpComponentsHttpInvokerRequestExecutor() {
		this(createDefaultHttpClient(), RequestConfig.custom()
				.setSocketTimeout(DEFAULT_READ_TIMEOUT_MILLISECONDS).build());
	}

	private static HttpClient createDefaultHttpClient() {
		Registry<ConnectionSocketFactory> schemeRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
				.register("http", PlainConnectionSocketFactory.getSocketFactory())
				.register("https", SSLConnectionSocketFactory.getSocketFactory())
				.build();

		PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(schemeRegistry);
		connectionManager.setMaxTotal(DEFAULT_MAX_TOTAL_CONNECTIONS);
		connectionManager.setDefaultMaxPerRoute(DEFAULT_MAX_CONNECTIONS_PER_ROUTE);

		return HttpClientBuilder.create().setConnectionManager(connectionManager).build();
	}

	//......
}

HttpComponentsHttpInvokerRequestExecutor继承了AbstractHttpInvokerRequestExecutor,其构造器提供了createDefaultHttpClient方法,默认注册了http及https的socketFactory,然后创建了PoolingHttpClientConnectionManager,默认maxTotal为100,defaultMaxPerRoute为5,其requestConfig默认设置了socketTimeout为60s

doExecuteRequest

代码语言:javascript
复制
	protected RemoteInvocationResult doExecuteRequest(
			HttpInvokerClientConfiguration config, ByteArrayOutputStream baos)
			throws IOException, ClassNotFoundException {

		HttpPost postMethod = createHttpPost(config);
		setRequestBody(config, postMethod, baos);
		try {
			HttpResponse response = executeHttpPost(config, getHttpClient(), postMethod);
			validateResponse(config, response);
			InputStream responseBody = getResponseBody(config, response);
			return readRemoteInvocationResult(responseBody, config.getCodebaseUrl());
		}
		finally {
			postMethod.releaseConnection();
		}
	}

HttpComponentsHttpInvokerRequestExecutor实现了AbstractHttpInvokerRequestExecutor定义的doExecuteRequest方法,执行createHttpPost创建postMethod,然后设置requestBody,之后设置setRequestBody,接着执行executeHttpPost,验证response,读取responseBody,最后在finally里头执行postMethod.releaseConnection()

createHttpPost

代码语言:javascript
复制
	protected HttpPost createHttpPost(HttpInvokerClientConfiguration config) throws IOException {
		HttpPost httpPost = new HttpPost(config.getServiceUrl());

		RequestConfig requestConfig = createRequestConfig(config);
		if (requestConfig != null) {
			httpPost.setConfig(requestConfig);
		}

		LocaleContext localeContext = LocaleContextHolder.getLocaleContext();
		if (localeContext != null) {
			Locale locale = localeContext.getLocale();
			if (locale != null) {
				httpPost.addHeader(HTTP_HEADER_ACCEPT_LANGUAGE, locale.toLanguageTag());
			}
		}

		if (isAcceptGzipEncoding()) {
			httpPost.addHeader(HTTP_HEADER_ACCEPT_ENCODING, ENCODING_GZIP);
		}

		return httpPost;
	}

	protected RequestConfig createRequestConfig(HttpInvokerClientConfiguration config) {
		HttpClient client = getHttpClient();
		if (client instanceof Configurable) {
			RequestConfig clientRequestConfig = ((Configurable) client).getConfig();
			return mergeRequestConfig(clientRequestConfig);
		}
		return this.requestConfig;
	}

	private RequestConfig mergeRequestConfig(RequestConfig defaultRequestConfig) {
		if (this.requestConfig == null) {  // nothing to merge
			return defaultRequestConfig;
		}

		RequestConfig.Builder builder = RequestConfig.copy(defaultRequestConfig);
		int connectTimeout = this.requestConfig.getConnectTimeout();
		if (connectTimeout >= 0) {
			builder.setConnectTimeout(connectTimeout);
		}
		int connectionRequestTimeout = this.requestConfig.getConnectionRequestTimeout();
		if (connectionRequestTimeout >= 0) {
			builder.setConnectionRequestTimeout(connectionRequestTimeout);
		}
		int socketTimeout = this.requestConfig.getSocketTimeout();
		if (socketTimeout >= 0) {
			builder.setSocketTimeout(socketTimeout);
		}
		return builder.build();
	}

createHttpPost先是创建HttpPost,然后设置requestConfig,接着设置locale及gzipEncoding

setRequestBody

代码语言:javascript
复制
	protected void setRequestBody(
			HttpInvokerClientConfiguration config, HttpPost httpPost, ByteArrayOutputStream baos)
			throws IOException {

		ByteArrayEntity entity = new ByteArrayEntity(baos.toByteArray());
		entity.setContentType(getContentType());
		httpPost.setEntity(entity);
	}

setRequestBody方法这里创建ByteArrayEntity,设置contentType,然后赋值给httpPost

executeHttpPost

代码语言:javascript
复制
	protected HttpResponse executeHttpPost(
			HttpInvokerClientConfiguration config, HttpClient httpClient, HttpPost httpPost)
			throws IOException {

		return httpClient.execute(httpPost);
	}

executeHttpPost直接通过httpClient.execute方法执行post请求

getResponseBody

代码语言:javascript
复制
	protected InputStream getResponseBody(HttpInvokerClientConfiguration config, HttpResponse httpResponse)
			throws IOException {

		if (isGzipResponse(httpResponse)) {
			return new GZIPInputStream(httpResponse.getEntity().getContent());
		}
		else {
			return httpResponse.getEntity().getContent();
		}
	}

	protected boolean isGzipResponse(HttpResponse httpResponse) {
		Header encodingHeader = httpResponse.getFirstHeader(HTTP_HEADER_CONTENT_ENCODING);
		return (encodingHeader != null && encodingHeader.getValue() != null &&
				encodingHeader.getValue().toLowerCase().contains(ENCODING_GZIP));
	}

getResponseBody方法会先判断是否是gzip,是的话创建GZIPInputStream,否则直接取httpResponse.getEntity().getContent()

小结

HttpComponentsHttpInvokerRequestExecutor是org.springframework.remoting.httpinvoker包里头的,它继承了继承了AbstractHttpInvokerRequestExecutor,演示了httpclient的基本配置(默认maxTotal为100,defaultMaxPerRoute为5,其requestConfig默认设置了socketTimeout为60s)及其使用(创建request、设置entity、执行请求、解析response)。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2023-10-03 09:22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码匠的流水账 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • HttpComponentsHttpInvokerRequestExecutor
  • doExecuteRequest
  • createHttpPost
  • setRequestBody
  • executeHttpPost
  • getResponseBody
  • 小结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档