Spring RestTemplate高性能配置

本文介绍了如何在Spring框架中使用RestTemplate进行网络请求,强调了其默认配置可能导致的性能问题,尤其是在高并发场景。同时提到了检查输出格式和定位性能瓶颈的重要性。
摘要由CSDN通过智能技术生成

一、简单使用

这里没有涉及任何连接方面的配置,直接使用,需要看源码才知道RestTemplate是如何进行网络连接的。

根据经验,我们知道,发起网络通信,通常是有需要有网络连接工具类的,我们熟知的有:
1、JDK自带的java.net.URLConnection
2、org.apache.http.client.HttpClient
3、其他一些http工具类
RestTemplate也不例外。

package com.wang.pub.util;

import com.alibaba.fastjson2.JSON;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;

import java.util.Collections;
import java.util.Map;

/**
 * @author cheng
 * @date 2024/3/19 21:58
 * description
 */
public class RestTemplateUtil2 {

    public static final RestTemplate REST_TEMPLATE = new RestTemplate();

    public static String postJson(String url, Object param) {
        return exchange(url, HttpMethod.POST, param);
    }

    private static String exchange(String url, HttpMethod method, Object param) {
        return exchange(url, method, genJsonHeaders(null), param);
    }

    private static String exchange(String url, HttpMethod method, HttpHeaders headers, Object param) {
        String jsonParam = JSON.toJSONString(param);
        headers = headers != null ? headers : genJsonHeaders(null);
        HttpEntity<String> requestEntity = new HttpEntity<>(jsonParam, headers);
        ResponseEntity<String> responseEntity = REST_TEMPLATE.exchange(url, method, requestEntity, String.class);
        return responseEntity.getBody();
    }

    public static HttpHeaders genJsonHeaders(Map<String, String> headerMap) {
        HttpHeaders headers = new HttpHeaders();
        headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
        headers.setContentType(MediaType.APPLICATION_JSON);
        buildHeaders(headers, headerMap);
        return headers;
    }

    private static void buildHeaders(HttpHeaders httpHeaders, Map<String, String> headerMap) {
        if (!CollectionUtils.isEmpty(headerMap)) {
            headerMap.forEach(httpHeaders::add);
        }
    }
}

这里的createRequest()就调用到父类HttpAccessor了。 

public class RestTemplate extends InterceptingHttpAccessor implements RestOperations {

	@Override
	@Nullable
	public <T> T execute(String url, HttpMethod method, @Nullable RequestCallback requestCallback,
			@Nullable ResponseExtractor<T> responseExtractor, Object... uriVariables) throws RestClientException {

		URI expanded = getUriTemplateHandler().expand(url, uriVariables);
		return doExecute(expanded, method, requestCallback, responseExtractor);
	}

	@Nullable
	protected <T> T doExecute(URI url, @Nullable HttpMethod method, @Nullable RequestCallback requestCallback,
			@Nullable ResponseExtractor<T> responseExtractor) throws RestClientException {

		Assert.notNull(url, "URI is required");
		Assert.notNull(method, "HttpMethod is required");
		ClientHttpResponse response = null;
		try {
			ClientHttpRequest request = createRequest(url, method);
			if (requestCallback != null) {
				requestCallback.doWithRequest(request);
			}
			response = request.execute();
			handleResponse(url, method, response);
			return (responseExtractor != null ? responseExtractor.extractData(response) : null);
		}
		catch (IOException ex) {
			String resource = url.toString();
			String query = url.getRawQuery();
			resource = (query != null ? resource.substring(0, resource.indexOf('?')) : resource);
			throw new ResourceAccessException("I/O error on " + method.name() +
					" request for \"" + resource + "\": " + ex.getMessage(), ex);
		}
		finally {
			if (response != null) {
				response.close();
			}
		}
	}


}

RestTemplate的有关继承关系如下,上面是父类,下面是子类

org.springframework.http.client.support.HttpAccessor

org.springframework.http.client.support.InterceptingHttpAccessor

org.springframework.web.client.RestTemplate

RestTemplate把发送请求的功能封装到
org.springframework.http.client.ClientHttpRequest
把制造ClientHttpRequest的功能封装工厂
org.springframework.http.client.ClientHttpRequestFactory
默认的请求制造工厂是
org.springframework.http.client.SimpleClientHttpRequestFactory

public abstract class HttpAccessor {

	/** Logger available to subclasses. */
	protected final Log logger = HttpLogging.forLogName(getClass());

	private ClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();

}
public class SimpleClientHttpRequestFactory implements ClientHttpRequestFactory, AsyncClientHttpRequestFactory {

	@Override
	public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {
		HttpURLConnection connection = openConnection(uri.toURL(), this.proxy);
		prepareConnection(connection, httpMethod.name());

		if (this.bufferRequestBody) {
			return new SimpleBufferingClientHttpRequest(connection, this.outputStreaming);
		}
		else {
			return new SimpleStreamingClientHttpRequest(connection, this.chunkSize, this.outputStreaming);
		}
	}
}

二、简单使用的弊端

最大的弊端是配置都是默认的,不能适应应用各自环境,最明显的问题就是在高并发下会有性能问题,这个是生产实际出现的问题,不用怀疑。

三、优化版

想要进行优化,先要找到性能瓶颈在哪里。

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值