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> 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 getForObject(String url, Class responseType, Object... uriVariables) throws RestClientException {
        RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
        HttpMessageConverterExtractor responseExtractor =
                new HttpMessageConverterExtractor<>(responseType, getMessageConverters(), logger);
        return execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables);
    }

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

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

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

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

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

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

    @Override
    public  ResponseEntity getForEntity(URI url, Class responseType) throws RestClientException {
        RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
        ResponseExtractor> 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 {

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

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

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

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

    //从给定的输入消息中读取给定类型的对象,并返回它。
    T read(Class 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 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 clientHttpRequestInitializers) {

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

    public List 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 {
    /**
     * 从给定的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 params=new HashMap<>();
        ResponseEntity result = restTemplate.postForEntity(url,params, String.class);
        System.out.println(result.getStatusCode().getReasonPhrase());
        System.out.println(result.getStatusCodeValue());
        System.out.println(result.getBody());
    }
RestTemplate相关博客推荐

源码分析:https://blog.csdn.net/zhawengan/article/details/121042628
所有请求用法分析:https://blog.csdn.net/weixin_38987366/article/details/109701339
上传文件:https://blog.csdn.net/weixin_39614177/article/details/113542058
下载文件:https://zzzgd.blog.csdn.net/article/details/88915818
相关博客专栏:https://blog.csdn.net/hanxiaotongtong/category_11999208.html

你可能感兴趣的:(Java中的HTTP客户端工具——RestTemplate)