Java中的HTTP客户端工具——RestTemplate


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相关博客专栏

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java 调用第三方接口通常会使用工具RestTemplateRestTemplate 是 Spring 框架提供的一个用于进行 HTTP 请求的工具类。它封装了 HTTP 请求的细节,提供了简单的 API 来发送 GET、POST、PUT 和 DELETE 请求,并能够方便地处理返回的响应结果。 使用 RestTemplate 需要先导入相关的依赖包,然后在代码创建 RestTemplate 的实例。可以通过 RestTemplate 的各种方法来构建不同类型的 HTTP 请求,比如 getForObject、postForObject 等。在方法的参数需要指定目标接口的 URL 地址,以及可能需要传递的请求参数。 在调用三方接口时,有时需要进行身份验证,可以在请求头添加认证信息。RestTemplate 的方法可以通过 HttpHeaders 对象来设置请求头的相关信息。另外,还可以设置请求体的内容格式,比如 JSON、XML 等。 调用接口后,可以通过 RestTemplate 的方法获取响应结果。比如,getForObject 和 postForObject 方法会返回代表响应结果的对象(可以是字符串、对象等)。另外,还可以通过 getForEntity 和 postForEntity 方法获取完整的响应对象,包括响应头、响应体等信息。 在使用 RestTemplate 调用接口时需要注意异常处理。如果调用接口出现异常,可以通过捕获 RestTemplateException 异常来处理。另外,还可以通过设置错误处理器来处理不同类型的错误响应。 总之,RestTemplate 是一个非常实用的工具类,可以方便地进行 Java 对第三方接口的调用。通过它,我们可以发送 HTTP 请求,处理响应结果,并且简化了请求的编写和异常处理的过程。使用 RestTemplate 可以提高开发效率,并且可以与不同的第三方接口进行灵活的集成。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值