RestTemplate是由Spring框架提供的一个可用于应用中调用rest服务的类它简化了与http服务的通信方式。
统一了RESTFul的标准,封装了http连接,只需要传入url及其返回值类型即可。相较于之前常用的HttpClient,RestTemplate是一种更为优雅的调用RESTFul服务的方式。RestTemplate类的设计原则与许多其他Spring的模板类(例如JdbcTemplate)相同,为执行复杂任务提供了一种具有默认行为的简化方法。

RestTemplate类结构图

RestTemplate类结构图

RestOperations:定义了RestTemplate对GET、POST、PUT、DELETE、OPTIONS方法的封装和适配,还有通用的exchange、execute方法。
HttpAccessor:定义了ClientHttpRequestFactory对象的get、set方法。
InterceptingHttpAccessor:定义了一个接口ClientHttpRequestInterceptor,用于做请求拦截。

RestTemplate源码
构造方法

	public RestTemplate() {
		this.messageConverters.add(new ByteArrayHttpMessageConverter());
		this.messageConverters.add(new StringHttpMessageConverter());
		this.messageConverters.add(new ResourceHttpMessageConverter(false));
		if (!shouldIgnoreXml) {
			try {
				this.messageConverters.add(new SourceHttpMessageConverter<>());
			}
			catch (Error err) {
				// Ignore when no TransformerFactory implementation is available
			}
		}
		this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());

		if (romePresent) {
			this.messageConverters.add(new AtomFeedHttpMessageConverter());
			this.messageConverters.add(new RssChannelHttpMessageConverter());
		}

		if (!shouldIgnoreXml) {
			if (jackson2XmlPresent) {
				this.messageConverters.add(new MappingJackson2XmlHttpMessageConverter());
			}
			else if (jaxb2Present) {
				this.messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
			}
		}

		if (jackson2Present) {
			this.messageConverters.add(new MappingJackson2HttpMessageConverter());
		}
		else if (gsonPresent) {
			this.messageConverters.add(new GsonHttpMessageConverter());
		}
		else if (jsonbPresent) {
			this.messageConverters.add(new JsonbHttpMessageConverter());
		}
		else if (kotlinSerializationJsonPresent) {
			this.messageConverters.add(new KotlinSerializationJsonHttpMessageConverter());
		}

		if (jackson2SmilePresent) {
			this.messageConverters.add(new MappingJackson2SmileHttpMessageConverter());
		}
		if (jackson2CborPresent) {
			this.messageConverters.add(new MappingJackson2CborHttpMessageConverter());
		}

		this.uriTemplateHandler = initUriTemplateHandler();
	}

	public RestTemplate(ClientHttpRequestFactory requestFactory) {
		this();
		setRequestFactory(requestFactory);
	}

	public RestTemplate(List<HttpMessageConverter<?>> messageConverters) {
		validateConverters(messageConverters);
		this.messageConverters.addAll(messageConverters);
		this.uriTemplateHandler = initUriTemplateHandler();
	}

RestTemplate的构造过程:
1.添加了多个HttpMessageConverter后续用于http请求响应的数据转换
2.初始化Uri模板的处理器,用于处理uri相关的东西
3.HttpAccessor默认创建了一个ClientHttpRequestFactory的成员实例(SimpleClientHttpRequestFactory,默认使用HttpURLConnection),用于创建请求对象。

RestTemplate类中常用的请求方法

官方支持:GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE
Get请求相关源码

@Override
	@Nullable
	public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables) throws RestClientException {
		RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
		HttpMessageConverterExtractor<T> responseExtractor =
				new HttpMessageConverterExtractor<>(responseType, getMessageConverters(), logger);
		return execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables);
	}

	@Override
	@Nullable
	public <T> T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException {
		RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
		HttpMessageConverterExtractor<T> responseExtractor =
				new HttpMessageConverterExtractor<>(responseType, getMessageConverters(), logger);
		return execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables);
	}

	@Override
	@Nullable
	public <T> T getForObject(URI url, Class<T> responseType) throws RestClientException {
		RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
		HttpMessageConverterExtractor<T> responseExtractor =
				new HttpMessageConverterExtractor<>(responseType, getMessageConverters(), logger);
		return execute(url, HttpMethod.GET, requestCallback, responseExtractor);
	}

	@Override
	public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables)
			throws RestClientException {

		RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
		ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
		return nonNull(execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables));
	}

	@Override
	public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables)
			throws RestClientException {

		RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
		ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
		return nonNull(execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables));
	}

	@Override
	public <T> ResponseEntity<T> getForEntity(URI url, Class<T> responseType) throws RestClientException {
		RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
		ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
		return nonNull(execute(url, HttpMethod.GET, requestCallback, responseExtractor));
	}

getForObject:返回值直接是响应体内容转为的 JSON 对象
getForEntity:返回值的封装包含有响应头, 响应状态码的 ResponseEntity对象

url:请求路径
requestEntity:HttpEntity对象,封装了请求头和请求体
responseType:返回数据类型
uriVariables:支持PathVariable类型的数据。

RestTemplate的核心组件

HttpMessageConverter:转换http请求响应过程中的消息数据

用于在 HTTP 请求和响应之间进行转换的策略接口。
需要对web接口的输入输出需要做自定义扩展或格式化时,都会考虑通过实现自定义的HttpMessageConverter来实现。

public interface HttpMessageConverter<T> {

	//指示此转换器是否可以读取给定的类。
	boolean canRead(Class<?> clazz, @Nullable MediaType mediaType);

	//指示此转换器是否可以编写给定的类。
	boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType);

	//返回此转换器支持的媒体类型列表。
	List<MediaType> getSupportedMediaTypes();

	//返回此转换器支持的给定类的媒体类型列表。
	default List<MediaType> getSupportedMediaTypes(Class<?> clazz) {
		return (canRead(clazz, null) || canWrite(clazz, null) ?
				getSupportedMediaTypes() : Collections.emptyList());
	}

	//从给定的输入消息中读取给定类型的对象,并返回它。
	T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
			throws IOException, HttpMessageNotReadableException;

	//将给定对象写入给定的输出消息。
	void write(T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage)
			throws IOException, HttpMessageNotWritableException;

}
1.AbstractJackson2HttpMessageConverter:Jackson 转换器

AbstractJackson2HttpMessageConverter类结构图

具体实现类:
MappingJackson2CborHttpMessageConverter:读取和写入CBOR 数据格式。
MappingJackson2HttpMessageConverter:ObjectMapper读写 JSON。
MappingJackson2SmileHttpMessageConverter:读取和写入 Smile 数据格式(“二进制 JSON”)。
MappingJackson2XmlHttpMessageConverter:读取和写入 XML 编码数据。

2.AbstractJsonHttpMessageConverter:JSON 转换器

AbstractJsonHttpMessageConverter类结构图

具体实现类:
GsonHttpMessageConverter:使用Google Gson 库读写 JSON。
JsonbHttpMessageConverter:使用JSON Binding API 读写 JSON。

3.AbstractXmlHttpMessageConverter:XML 转换器

AbstractXmlHttpMessageConverter类结构图
具体实现类:
Jaxb2CollectionHttpMessageConverter:读取包含使用XmlRootElement和XmlType注释的类的集合。请注意,此转换器不支持写入。
Jaxb2RootElementHttpMessageConverter:读取使用XmlRootElement和XmlType注释的类,并编写使用XmlRootElement注释的类或其子类。
MarshallingHttpMessageConverter:读取使用XmlRootElement和XmlType注释的类,并编写使用XmlRootElement注释的类或其子类。

4.AbstractWireFeedHttpMessageConverter:Atom 和 RSS Feed 消息转换器

AbstractWireFeedHttpMessageConverter类结构图
具体实现类:
AtomFeedHttpMessageConverter:可以读写 Atom 提要。具体来说,这个转换器可以处理来自ROME 项目的Feed对象。
RssChannelHttpMessageConverter:可以读写 RSS 提要。具体来说,这个转换器可以处理来自ROME 项目的Channel对象。

ClientHttpRequestFactory:用于根据URI和HttpMethod创建出一个ClientHttpRequest来发送请求

源码很简单,一个工厂接口,定义了生成ClientHttpRequest的方法。

public interface ClientHttpRequestFactory {
	ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException;
}

具体实现类:
SimpleClientHttpRequestFactory:使用标准 JDK 工具创建请求。(默认)
HttpComponentsClientHttpRequestFactory:使用HttpClient 创建请求。
OkHttp3ClientHttpRequestFactory:使用OkHttp 3.x 创建请求。
BufferingClientHttpRequestFactory:在内存中缓冲所有传出和传入流。使用此包装器允许多次读取响应正文。
InterceptingClientHttpRequestFactory:支持ClientHttpRequestInterceptors的包装器。

SimpleClientHttpRequestFactory为什么是默认?
HttpAccessor抽象类源码

public abstract class HttpAccessor {
	protected final Log logger = HttpLogging.forLogName(getClass());

	private ClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();

	private final List<ClientHttpRequestInitializer> clientHttpRequestInitializers = new ArrayList<>();

	public void setRequestFactory(ClientHttpRequestFactory requestFactory) {
		Assert.notNull(requestFactory, "ClientHttpRequestFactory must not be null");
		this.requestFactory = requestFactory;
	}

	public ClientHttpRequestFactory getRequestFactory() {
		return this.requestFactory;
	}

	public void setClientHttpRequestInitializers(
			List<ClientHttpRequestInitializer> clientHttpRequestInitializers) {

		if (this.clientHttpRequestInitializers != clientHttpRequestInitializers) {
			this.clientHttpRequestInitializers.clear();
			this.clientHttpRequestInitializers.addAll(clientHttpRequestInitializers);
			AnnotationAwareOrderComparator.sort(this.clientHttpRequestInitializers);
		}
	}

	public List<ClientHttpRequestInitializer> getClientHttpRequestInitializers() {
		return this.clientHttpRequestInitializers;
	}

	protected ClientHttpRequest createRequest(URI url, HttpMethod method) throws IOException {
		ClientHttpRequest request = getRequestFactory().createRequest(url, method);
		initialize(request);
		if (logger.isDebugEnabled()) {
			logger.debug("HTTP " + method.name() + " " + url);
		}
		return request;
	}

	private void initialize(ClientHttpRequest request) {
		this.clientHttpRequestInitializers.forEach(initializer -> initializer.initialize(request));
	}

}
UriTemplateHandler:组装uri的模板处理器

默认实现类是DefaultUriBuilderFactory

public class DefaultUriBuilderFactory implements UriBuilderFactory
public interface UriBuilderFactory extends UriTemplateHandler

####RequestCallback:回调接口

@FunctionalInterface
public interface RequestCallback {
	/**
	 * 通过打开的ClientHttpRequest由RestTemplate.execute调用。
	 * 不需要关心关闭请求或处理错误:这都将由RestTemplate处理。
	 */
	void doWithRequest(ClientHttpRequest request) throws IOException;
}
ResponseErrorHandler:用于确定特定响应是否有错误的策略接口。
public interface ResponseErrorHandler {

	/**
	 * 指示给定的响应是否有任何错误。
	 * 实现通常会检查响应的HttpStatus 。
	 */
	boolean hasError(ClientHttpResponse response) throws IOException;

	/**
	 * 处理给定响应中的错误。
	 * 仅当hasError(ClientHttpResponse)返回true时才调用此方法。
	 */
	void handleError(ClientHttpResponse response) throws IOException;

	/**
	 * 替代handleError(ClientHttpResponse)提供对请求 URL 和 HTTP 方法的访问的额外信息
	 */
	default void handleError(URI url, HttpMethod method, ClientHttpResponse response) throws IOException {
		handleError(response);
	}
}
ResponseExtractor:提取返回数据,但无需担心异常处理或关闭资源。
@FunctionalInterface
public interface ResponseExtractor<T> {
	/**
	 * 从给定的ClientHttpResponse中提取数据并返回。
	 */
	@Nullable
	T extractData(ClientHttpResponse response) throws IOException;
}

RestTemplate请求示例

GET请求例子

    public static void main(String[] args) {
        RestTemplate restTemplate = new RestTemplate();
        //三种方式请求
        String url = "https://restapi.amap.com/v3/weather/weatherInfo?city=110101&key=3ff9482454cb60bcb73f65c8c48d4209](https://restapi.amap.com/v3/weather/weatherInfo?city=110101&key=3ff9482454cb60bcb73f65c8c48d4209)";
        String result = restTemplate.getForObject(url, String.class);
        System.out.println(result);
    }

POST请求例子

    public static void main(String[] args) {
        RestTemplate restTemplate = new RestTemplate();
        //三种方式请求
        String url = "https://restapi.amap.com/v3/weather/weatherInfo?city=110101&key=3ff9482454cb60bcb73f65c8c48d4209](https://restapi.amap.com/v3/weather/weatherInfo?city=110101&key=3ff9482454cb60bcb73f65c8c48d4209)";
        Map<String,Object> params=new HashMap<>();
        ResponseEntity<String> result = restTemplate.postForEntity(url,params, String.class);
        System.out.println(result.getStatusCode().getReasonPhrase());
        System.out.println(result.getStatusCodeValue());
        System.out.println(result.getBody());
    }

RestTemplate相关博客推荐

RestTemplate源码分析
RestTemplate所有请求用法分析
RestTemplate上传文件
RestTemplate下载文件
RestTemplate相关博客专栏

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐