当前位置: 代码网 > it编程>编程语言>Java > HttpClient、OKhttp、RestTemplate接口调用对比( Java HTTP 客户端)

HttpClient、OKhttp、RestTemplate接口调用对比( Java HTTP 客户端)

2024年08月02日 Java 我要评论
HttpClient、OKhttp、RestTemplate接口调用对比HttpClient、OkHttp 和 RestTemplate 是三种常用的 Java HTTP 客户端库,它们都可以用于发送 HTTP 请求和接收 HTTP 响应,但在一些方面有所不同。下面是它们之间的一些对比:HttpClient:Apache HttpClient:○ 成熟稳定: Apache HttpClient 是 Apache 软件基金会的一个项目,经过多年的发展,已经非常成熟和稳定。○ 灵活性: 提供了丰富的

httpclient、okhttp、resttemplate接口调用对比

httpclient、okhttp 和 resttemplate 是三种常用的 java http 客户端库,它们都可以用于发送 http 请求和接收 http 响应,但在一些方面有所不同。
对比总结:
● 性能和效率: okhttp 在性能和效率上通常优于 apache httpclient 和 resttemplate,特别是在并发场景和对性能要求较高的情况下。
● 功能和灵活性: apache httpclient 提供了更丰富的功能和灵活的配置选项,适用于需要定制化的场景;而 okhttp 和 resttemplate 则更加简洁易用。
● 异步支持: okhttp 提供了异步调用的支持,而 apache httpclient 和 resttemplate 需要通过额外的工作来实现异步调用。
● 与框架集成: resttemplate 与 spring 框架集成度高,更适合于 spring 项目;而 apache httpclient 和 okhttp 可以在各种项目中独立使用。
● 更新维护: okhttp 是 square 公司维护的开源项目,更新迭代较为活跃;apache httpclient 在过去曾有一段时间的停滞,但也在持续维护;而 resttemplate 在新项目中可能会被 webclient 替代,不再是 spring 官方推荐的首选。
综上所述,选择合适的 http 客户端库取决于项目需求、性能要求、对框架集成的需求以及个人偏好等因素。

httpclient:

  1. apache httpclient:
    ○ 成熟稳定: apache httpclient 是 apache 软件基金会的一个项目,经过多年的发展,已经非常成熟和稳定。
    ○ 灵活性: 提供了丰富的配置选项和扩展点,可以灵活地定制和扩展功能。
    ○ 线程安全: httpclient 的实例是线程安全的,可以在多线程环境中共享使用。
    ○ 相对庞大: 相对于其他库来说,apache httpclient 的体积较大,可能会增加应用程序的大小。

okhttp:

  1. square okhttp:
    ○ 高性能: okhttp 是一个现代化的 http 客户端,具有优秀的性能和效率。
    ○ 简洁易用: 提供了简洁的 api 设计,易于学习和使用。
    ○ 支持 http/2: 支持 http/2,可以实现多路复用,提高并发性能。
    ○ 轻量级: okhttp 的体积相对较小,对应用程序的大小影响较小。

resttemplate:

  1. spring resttemplate:
    ○ 与 spring 集成: resttemplate 是 spring 框架提供的一个 http 客户端,与 spring 生态集成度高。
    ○ 便捷的 restful 支持: 提供了便捷的 restful 风格的 api 调用支持,如 http 方法映射、请求和响应消息转换等。
    ○ 同步阻塞: resttemplate 是一个同步阻塞的 http 客户端,对于高并发场景可能性能较差。
    ○ 可能过时: 随着 spring 5 推出的 webclient,resttemplate 在新项目中可能会逐渐被 webclient 替代。

httpclient

apache httpclient 是一个用于执行 http 请求的开源 java 库。它提供了丰富的功能和灵活的接口,可以用来发送 http 请求并处理 http 响应。
httpclient 是apache的一个三方网络框架,网络请求做了完善的封装,api众多,用起来比较方便,开发快
功能特点:

  1. 支持多种 http 方法: apache httpclient 支持 get、post、put、delete 等常见的 http 方法,以及任意自定义的 http 方法。
  2. 支持 https: httpclient 支持使用 ssl/tls 加密协议进行 https 请求,并可以自定义 ssl/tls 配置。
  3. 连接管理: httpclient 提供了连接池管理机制,可以有效地管理 http 连接,减少连接建立的开销。
  4. 请求和响应拦截器: httpclient 允许用户定义请求和响应的拦截器,可以在请求发送前或响应返回后对请求和响应进行处理。
  5. 自定义请求头和请求参数: httpclient 允许用户自定义请求头和请求参数,可以灵活地设置 http 请求的各种参数。
  6. 重定向处理: httpclient 可以自动处理 http 请求的重定向,并且允许用户配置重定向策略。
  7. cookie 管理: httpclient 支持自动管理 http cookie,可以处理 cookie 的存储、发送和接收。
  8. 代理支持: httpclient 可以配置使用代理服务器进行 http 请求。
  9. 认证机制: httpclient 支持多种认证机制,包括基本认证、摘要认证、oauth 等。
    核心组件:
  10. httpclient: httpclient 类是 apache httpclient 的核心类,用于执行 http 请求并处理 http 响应。
  11. httprequest: httprequest 接口表示一个 http 请求,包括请求方法、请求头、请求参数等信息。
  12. httpresponse: httpresponse 接口表示一个 http 响应,包括状态码、响应头、响应体等信息。
  13. httpclientbuilder: httpclientbuilder 是用于创建 httpclient 实例的构建器,可以配置 httpclient 的各种参数。
  14. httpentity: httpentity 接口表示一个 http 实体,包括请求体、响应体等信息。
  15. httpclientcontext: httpclientcontext 类表示一个 http 执行上下文,包括请求的上下文信息、连接状态等。

httpclient 是apache的一个三方网络框架,网络请求做了完善的封装,api众多,用起来比较方便,开发快。

package org.example;

import lombok.sneakythrows;
import lombok.extern.slf4j.slf4j;
import org.apache.http.header;
import org.apache.http.httpentity;
import org.apache.http.httpresponse;
import org.apache.http.namevaluepair;
import org.apache.http.client.config.requestconfig;
import org.apache.http.client.entity.urlencodedformentity;
import org.apache.http.client.methods.closeablehttpresponse;
import org.apache.http.client.methods.httpget;
import org.apache.http.client.methods.httppost;
import org.apache.http.client.methods.httprequestbase;
import org.apache.http.client.utils.uribuilder;
import org.apache.http.concurrent.futurecallback;
import org.apache.http.entity.bytearrayentity;
import org.apache.http.entity.contenttype;
import org.apache.http.entity.stringentity;
import org.apache.http.entity.mime.multipartentitybuilder;
import org.apache.http.impl.client.closeablehttpclient;
import org.apache.http.impl.client.defaulthttprequestretryhandler;
import org.apache.http.impl.client.httpclientbuilder;
import org.apache.http.impl.nio.client.closeablehttpasyncclient;
import org.apache.http.impl.nio.client.httpasyncclients;
import org.apache.http.message.basicnamevaluepair;
import org.apache.http.util.entityutils;

import java.io.*;
import java.net.uri;
import java.net.urlencoder;
import java.nio.charset.standardcharsets;
import java.util.arraylist;
import java.util.hashmap;
import java.util.list;
import java.util.map;
import java.util.zip.gzipinputstream;
import java.util.zip.gzipoutputstream;

/**
 * @desc httpclient工具类
 * @author liangliang
 * @date 2019/3/11 13:23
 */

@slf4j
public class httpclientutil {
    /**
     * httpclient基础配置信息
     */
    private static final requestconfig requestconfig = requestconfig.custom()
            // 设置连接超时时间(单位毫秒)
            .setconnecttimeout(2000)
            // 设置请求超时时间(单位毫秒)
            .setconnectionrequesttimeout(2000)
            // socket读写超时时间(单位毫秒)
            .setsockettimeout(1000)
            // 设置是否允许重定向(默认为true)
            .setredirectsenabled(true)
            //是否启用内容压缩,默认true
            .setcontentcompressionenabled(true)
            .build();
    /**
     * 获得http客户端
     */
    private static final closeablehttpclient http_client = httpclientbuilder.create()
            .setretryhandler(new defaulthttprequestretryhandler()) //失败重试,默认3次
            .build();

    /**
     * 异步http客户端
     */
    private static final closeablehttpasyncclient http_async_client = httpasyncclients.custom()
            .setdefaultrequestconfig(requestconfig)
            .build();


    /**
     * @desc 异步请求
     * @param httprequestbase
     * @author liangliang
     * @date 2019/3/11 13:23
     */
    private static void executeasync(httprequestbase httprequestbase) {
        http_async_client.start();
        http_async_client.execute(httprequestbase, new futurecallback<httpresponse>() {
            @sneakythrows
            @override
            public void completed(httpresponse httpresponse) {
                log.info("thread id is : {}" ,thread.currentthread().getid());

                stringbuffer stringbuffer = new stringbuffer();
                for (header header : httprequestbase.getallheaders()) {
                    stringbuffer.append(header.tostring()).append(",");
                }
                log.info("请求头信息: {}", stringbuffer.tostring());


                string responseresult = null;
                httpentity responseentity = httpresponse.getentity();
                log.info("响应状态为:{}", httpresponse.getstatusline());
                if (responseentity != null) {
                    responseresult = entityutils.tostring(responseentity, standardcharsets.utf_8);
                    log.info("响应内容为:{}",responseresult);

                }

                stringbuffer = new stringbuffer();
                for (header header : httpresponse.getallheaders()) {
                    stringbuffer.append(header.tostring()).append(",");
                }
                log.info("响应头信息: {}", stringbuffer.tostring()));


            }

            @override
            public void failed(exception e) {
                log.info("thread id is : {}",thread.currentthread().getid());
                log.error("exception responseresult:{}", e);
                e.printstacktrace();
            }

            @override
            public void cancelled() {
                log.info(httprequestbase.getrequestline() + " cancelled");
            }
        });
    }

     /**
     * @desc string请求
     * @param httprequestbase
     * @return string
     * @author liangliang
     * @date 2019/3/11 13:23
     */
    private static string execute(httprequestbase httprequestbase) {
        log.info("请求地址: {},请求类型: {}", httprequestbase.geturi().tostring(,httprequestbase.getmethod()));

        stringbuffer stringbuffer = new stringbuffer();
        for (header header : httprequestbase.getallheaders()) {
            stringbuffer.append(header.tostring()).append(",");
        }
        log.info("请求头信息: {}", stringbuffer.tostring());


        log.info("请求参数: {}", httprequestbase.geturi().getquery());

        string responseresult = null;
        // 响应模型
        closeablehttpresponse response = null;
        try {
            // 将上面的配置信息 运用到这个get请求里
            httprequestbase.setconfig(requestconfig);
            long t1 = system.nanotime();//请求发起的时间
            response = http_client.execute(httprequestbase);
            // 从响应模型中获取响应实体
            httpentity responseentity = response.getentity();
            log.info("响应状态为:{}",response.getstatusline());
            long t2 = system.nanotime();//收到响应的时间
            if (responseentity != null) {

                responseresult = entityutils.tostring(responseentity, standardcharsets.utf_8);

                log.info("响应内容为:{}",responseresult);

            }

            stringbuffer = new stringbuffer();
            for (header header : response.getallheaders()) {
                stringbuffer.append(header.tostring()).append(",");
            }
            log.info("响应头信息: {}", stringbuffer.tostring());

            log.info("执行时间: {}", (t2 - t1));

        } catch (exception e) {
            log.error("exception responseresult:{}", e.getmassage());
            e.printstacktrace();
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
            } catch (ioexception e) {
            	log.error("exception responseresult:{}", e.getmassage());
                e.printstacktrace();
            }

        }
        return responseresult;

    }
    
     /**
     * @desc byte[]请求
     * @param httprequestbase
     * @return byte[]
     * @author liangliang
     * @date 2019/3/11 13:23
     */
    private static byte[] executebytes(httprequestbase httprequestbase) {
        log.info("请求地址: {},请求类型: {}", httprequestbase.geturi().tostring(,httprequestbase.getmethod()));
        stringbuffer stringbuffer = new stringbuffer();
        for (header header : httprequestbase.getallheaders()) {
            stringbuffer.append(header.tostring()).append(",");
        }
        log.info("请求头信息: {}", stringbuffer.tostring());


        log.info("请求参数: {}", httprequestbase.geturi().getquery());

        byte[] bytes = null;
        // 响应模型
        closeablehttpresponse response = null;
        try {
            // 将上面的配置信息 运用到这个get请求里
            httprequestbase.setconfig(requestconfig);
            long t1 = system.nanotime();//请求发起的时间
            response = http_client.execute(httprequestbase);
            // 从响应模型中获取响应实体
            httpentity responseentity = response.getentity();
            log.info("响应状态为:{}", response.getstatusline());
            long t2 = system.nanotime();//收到响应的时间
            if (responseentity != null) {
                bytes = entityutils.tobytearray(responseentity);

                //判断是否需要解压,即服务器返回是否经过了gzip压缩--start
                header responseheader = response.getfirstheader("content-encoding");
                if (responseheader != null && responseheader.getvalue().contains("gzip")) {
                    gzipinputstream gzipinputstream = null;
                    bytearrayoutputstream out = null;
                    try {
                        gzipinputstream = new gzipinputstream(new bytearrayinputstream(bytes));
                        out = new bytearrayoutputstream();
                        byte[] buffer = new byte[1024];
                        int offset = -1;
                        while ((offset = gzipinputstream.read(buffer)) != -1) {
                            out.write(buffer, 0, offset);
                        }
                        bytes = out.tobytearray();

                    } catch (ioexception e) {
                    	log.error("exception responseresult:{}", e.getmassage());
                        e.printstacktrace();
                    } finally {
                        try {
                            gzipinputstream.close();
                            out.close();
                        } catch (ioexception e) {
                            e.printstacktrace();
                        }
                    }
                }
                //判断是否需要解压,即服务器返回是否经过了gzip压缩--end

                log.info("响应byte长度:{}", bytes.length);
            }

            stringbuffer = new stringbuffer();
            for (header header : response.getallheaders()) {
                stringbuffer.append(header.tostring()).append(",");
            }
            log.info("响应头信息: {}", stringbuffer.tostring());

            log.info("执行时间: {}", (t2 - t1));

        } catch (exception e) {
            log.error("exception responseresult:{}", e.getmassage());
            e.printstacktrace();
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
            } catch (ioexception e) {
                e.printstacktrace();
            }

        }
        return bytes;

    }

     /**
     * @desc get请求
     * @param url
     * @return tring
     * @author liangliang
     * @date 2019/3/11 13:23
     */
    public static string get(string url) {
        return get(url, new hashmap<>());
    }

     /**
     * @desc get请求
     * @param url, params
     * @return tring
     * @author mal
     * @date 2019/3/11 13:23
     */
    public static string get(string url, map<string, object> params) {
        httpget httpget = null;
        list<namevaluepair> list = new arraylist<>();
        for (string key : params.keyset()) {
            list.add(new basicnamevaluepair(key, params.get(key).tostring()));
        }

        // 由客户端执行(发送)get请求
        try {
            uri uri = new uribuilder(url).addparameters(list).build();
            // 创建get请求
            httpget = new httpget(uri);

        } catch (exception e) {
            log.error("exception responseresult:{}", e.getmassage());
            e.printstacktrace();
        }
        return execute(httpget);
    }

     /**
     * @desc get请求
     * @param url, params
     * @return byte[]
     * @author liangliang
     * @date 2019/3/11 13:23
     */
    public static byte[] getbytes(string url, map<string, object> params) {
        httpget httpget = null;
        list<namevaluepair> list = new arraylist<>();
        for (string key : params.keyset()) {
            list.add(new basicnamevaluepair(key, params.get(key).tostring()));
        }

        // 由客户端执行(发送)get请求
        try {
            uri uri = new uribuilder(url).addparameters(list).build();
            // 创建get请求
            httpget = new httpget(uri);

        } catch (exception e) {
            log.error("exception responseresult:{}", e.getmassage());
            e.printstacktrace();
        }
        return executebytes(httpget);
    }

     /**
     * @desc post请求
     * @param url
     * @return string
     * @author liangliang
     * @date 2019/3/11 13:23
     */
    public static string post(string url) {
        return post(url, new hashmap<>());
    }
     /**
     * @desc post请求
     * @param url, params
     * @return string
     * @author liangliang
     * @date 2019/3/11 13:23
     */
    public static string post(string url, map<string, object> params) {
        httppost httppost = null;
        list<namevaluepair> list = new arraylist<>();
        for (string key : params.keyset()) {
            list.add(new basicnamevaluepair(key, params.get(key).tostring()));
        }

        try {
            uri uri = new uribuilder(url).addparameters(list).build();
            httppost = new httppost(uri);
        } catch (exception e) {
            log.error("exception responseresult:{}", e.getmassage());
            e.printstacktrace();
        }

        return execute(httppost);
    }

     /**
     * @desc post请求
     * @param url, params
     * @return byte[]
     * @author liangliang
     * @date 2019/3/11 13:23
     */
    public static byte[] postbytes(string url, map<string, object> params) {
        httppost httppost = null;
        list<namevaluepair> list = new arraylist<>();
        for (string key : params.keyset()) {
            list.add(new basicnamevaluepair(key, params.get(key).tostring()));
        }

        try {
            uri uri = new uribuilder(url).addparameters(list).build();
            httppost = new httppost(uri);
        } catch (exception e) {
        	log.error("exception responseresult:{}", e.getmassage());
            e.printstacktrace();
        }

        return executebytes(httppost);
    }

     /**
     * @desc post请求
     * @param url, json
     * @return string
     * @author liangliang
     * @date 2019/3/11 13:23
     */
    public static string postjson(string url, string json) {
        return postjson(url, json, false);
    }

     /**
     * @desc post请求
     * @param url, json, gzip
     * @return string
     * @author liangliang
     * @date 2019/3/11 13:23
     */
    public static string postjson(string url, string json, boolean gzip) {
        httppost httppost = null;
        try {
            uri uri = new uribuilder(url).build();
            httppost = new httppost(uri);

            // post请求是将参数放在请求体里面传过去的,这里将entity放入post请求体中

            httppost.setheader("content-type", "application/json;charset=utf8");

            if (gzip) {
                httppost.setheader("content-encoding", "gzip");
                bytearrayoutputstream originalcontent = new bytearrayoutputstream();
                originalcontent.write(json.getbytes(standardcharsets.utf_8));
                bytearrayoutputstream baos = new bytearrayoutputstream();
                gzipoutputstream gzipout = new gzipoutputstream(baos);
                originalcontent.writeto(gzipout);
                gzipout.finish();
                httppost.setentity(new bytearrayentity(baos
                        .tobytearray(), contenttype.create("text/plain", "utf-8")));
            } else {
                stringentity entity = new stringentity(json, "utf-8");
                httppost.setentity(entity);

            }

        } catch (exception e) {
            log.error("exception responseresult:{}", e.getmassage());
            e.printstacktrace();
        }
        return execute(httppost);
    }
    
     /**
     * @desc post请求byte流
     * @param url, bytes
     * @return string
     * @author liangliang
     * @date 2019/3/11 13:23
     */
    public static string postinputbytes(string url, byte[] bytes) {
        return postinputbytes(url, bytes, false);
    }

     /**
     * @desc post请求byte流
     * @param url, bytes, gzip
     * @return string
     * @author liangliang
     * @date 2019/3/11 13:23
     */
    public static string postinputbytes(string url, byte[] bytes, boolean gzip) {
        httppost httppost = null;
        try {
            uri uri = new uribuilder(url).build();
            httppost = new httppost(uri);

            // post请求是将参数放在请求体里面传过去的,这里将entity放入post请求体中
            if (gzip) {
                httppost.setheader("content-encoding", "gzip");
                bytearrayoutputstream originalcontent = new bytearrayoutputstream();
                originalcontent.write(bytes);
                bytearrayoutputstream baos = new bytearrayoutputstream();
                gzipoutputstream gzipout = new gzipoutputstream(baos);
                originalcontent.writeto(gzipout);
                gzipout.finish();
                httppost.setentity(new bytearrayentity(baos
                        .tobytearray(), contenttype.create("text/plain", "utf-8")));
            } else {
                bytearrayentity entity = new bytearrayentity(bytes, contenttype.create("text/plain", "utf-8"));
                httppost.setentity(entity);
            }

        } catch (exception e) {
            log.error("exception responseresult:{}", e.getmassage());
            e.printstacktrace();
        }

        return execute(httppost);
    }
    
     /**
     * @desc post请求流
     * @param url, is
     * @return string
     * @author liangliang
     * @date 2019/3/11 13:23
     */
    public static string postinputstream(string url, inputstream is) {
        return postinputstream(url, is, false);
    }

     /**
     * @desc post请求流
     * @param url, is, gzip
     * @return string
     * @author liangliang
     * @date 2019/3/11 13:23
     */
    public static string postinputstream(string url, inputstream is, boolean gzip) {
        bytearrayoutputstream bytearrayoutputstream = new bytearrayoutputstream();
        byte[] buffer = new byte[1024];
        int ch;
        byte[] bytes = null;
        try {
            while ((ch = is.read(buffer)) != -1) {
                bytearrayoutputstream.write(buffer, 0, ch);
            }
            bytes = bytearrayoutputstream.tobytearray();
            bytearrayoutputstream.close();
        } catch (exception e) {
        	log.error("exception responseresult:{}", e.getmassage());
            e.printstacktrace();
        }
        return postinputbytes(url, bytes, gzip);
    }

     /**
     * @desc post请求文件
     * @param url, files
     * @return string
     * @author zhangh
     * @date 2019/3/11 13:23
     */
    public static string postfile(string url, file[] files) {
        return postfile(url, new hashmap<>(), files);
    }


     /**
     * @desc post请求文件
     * @param url, params, files
     * @return string
     * @author zhangh
     * @date 2019/3/11 13:23
     */
    public static string postfile(string url, map<string, object> params, file[] files) {
        httppost httppost = null;
        try {
            uri uri = new uribuilder(url).build();
            httppost = new httppost(uri);

            multipartentitybuilder multipartentitybuilder = multipartentitybuilder.create();
            string fileskey = "files";
            for (file file : files) {
                //multipartentitybuilder.addpart(fileskey,new filebody(file)); //与下面的语句作用相同
                //multipartentitybuilder.addbinarybody(fileskey, file);

                // 防止服务端收到的文件名乱码。 我们这里可以先将文件名urlencode,然后服务端拿到文件名时在urldecode。就能避免乱码问题。
                // 文件名其实是放在请求头的content-disposition里面进行传输的,如其值为form-data; name="files"; filename="头像.jpg"
                multipartentitybuilder.addbinarybody(fileskey, file, contenttype.default_binary, urlencoder.encode(file.getname(), "utf-8"));

            }

            // 其它参数(注:自定义contenttype,设置utf-8是为了防止服务端拿到的参数出现乱码)
            contenttype contenttype = contenttype.create("text/plain", standardcharsets.utf_8);
            for (string key : params.keyset()) {
                multipartentitybuilder.addtextbody(key, params.get(key).tostring(), contenttype);
            }
            httpentity entity = multipartentitybuilder.build();

            // post请求是将参数放在请求体里面传过去的,这里将entity放入post请求体中
            httppost.setentity(entity);

        } catch (exception e) {
            log.error("exception responseresult:{}", e.getmassage());
            e.printstacktrace();
        }

        return execute(httppost);
    }


}


okhttp

高效的http客户端,它能允许同一ip和端口的请求重用一个socket,这种方式能大大降低网络连接的时间,和每次请求都建立socket,再断开socket的方式相比,降低了服务器服务器的压力,透明的gzip压缩减少响应数据的大小;缓存响应内容。
okhttp 是一个现代化的 http 客户端库,由 square 公司开发并维护,用于在 android 和 java 应用程序中发送 http 请求和接收 http 响应。它具有以下特点和优势:
高性能: okhttp 使用了连接池、复用连接、异步请求等技术,可以实现高效的 http 请求和响应处理,性能优秀。
支持 http/2: okhttp 支持 http/2,能够实现多路复用,提高了网络请求的并发效率。
简洁易用的 api: okhttp 提供了简洁易用的 api 设计,使用起来非常方便,易于学习和使用。
丰富的功能: okhttp 提供了丰富的功能,包括请求和响应的拦截、重定向、gzip 压缩、连接池管理等,可以满足各种复杂的应用场景需求。
灵活性: okhttp 提供了丰富的配置选项和扩展点,可以灵活地定制和扩展功能,满足各种特定需求。
支持同步和异步请求: okhttp 支持同步和异步请求,可以根据需求选择合适的方式进行网络请求。
轻量级: okhttp 的体积相对较小,对应用程序的大小影响较小,适合于移动端应用和对包大小敏感的项目。
持续更新和维护: okhttp 是由 square 公司维护的开源项目,更新迭代较为活跃,能够及时修复 bug 和添加新功能。

1、高效的http客户端,它能允许同一ip和端口的请求重用一个socket,这种方式能大大降低网络连接的时间,和每次请求都建立socket,再断开socket的方式相比,降低了服务器服务器的压力,透明的gzip压缩减少响应数据的大小;缓存响应内容。
2、okhttp 对http和https都有良好的支持。
3、okhttp 对大数据量的网络请求支持非常好。

import okhttp3.*;
import org.apache.commons.lang3.exception.exceptionutils;

import java.io.file;
import java.util.iterator;
import java.util.map;

@slf4j
public class okhttputil{
    
    private static okhttpclient  okhttpclient;

    @autowired
    public okhttputil(okhttpclient  okhttpclient) {
        okhttputil.okhttpclient= okhttpclient;
    } 
    
    /**
     * get
     * @param url   请求的url
     * @param param 请求的参数
     * @return
     */
    public static  string get(string url, map<string, string> param) {
        string responsebody = "";
        stringbuffer sb = new stringbuffer(url);
        if (param!= null && param.keyset().size() > 0) {
            boolean firstflag = true;
            iterator iterator = param.entryset().iterator();
            while (iterator.hasnext()) {
                map.entry entry = (map.entry<string, string>) iterator.next();
                if (firstflag) {
                    sb.append("?" + entry.getkey() + "=" + entry.getvalue());
                    firstflag = false;
                } else {
                    sb.append("&" + entry.getkey() + "=" + entry.getvalue());
                }
            }
        }
        request request = new request.builder()
                .url(sb.tostring())
                .build();
        response response = null;
        try { 
            response = okhttpclient.newcall(request).execute();
            int status = response.code();
            if (response.issuccessful()) {
                return response.body().string();
            }
        } catch (exception e) {
            log.error("okhttp3 post exception:{}", e.getmessage());
        } finally {
            if (response != null) {
                response.close();
            }
        }
        return responsebody;
    }

    /**
     * post
     *
     * @param url    请求的url
     * @param params post form 提交的参数
     * @return
     */
    public static string post(string url, map<string, string> params) {
        string responsebody = "";
        formbody.builder builder = new formbody.builder();
        //添加参数
        if (params != null && params.keyset().size() > 0) {
            for (string key : params.keyset()) {
                builder.add(key, params.get(key));
            }
        }
        request request = new request.builder()
                .url(url)
                .post(builder.build())
                .build();
        response response = null;
        try { 
            response = okhttpclient.newcall(request).execute();
            int status = response.code();
            if (response.issuccessful()) {
                return response.body().string();
            }
        } catch (exception e) {
            log.error("okhttp3 post exception:{}", e.getmessage());
        } finally {
            if (response != null) {
                response.close();
            }
        }
        return responsebody;
    }

    /**
     * get
     * @param url     请求的url
     * @param param 请求的参数
     * @return
     */
    public static string getforheader(string url, map<string, string> param) {
        string responsebody = "";
        stringbuffer sb = new stringbuffer(url);
        if (param != null && param.keyset().size() > 0) {
            boolean firstflag = true;
            iterator iterator = param.entryset().iterator();
            while (iterator.hasnext()) {
                map.entry entry = (map.entry<string, string>) iterator.next();
                if (firstflag) {
                    sb.append("?" + entry.getkey() + "=" + entry.getvalue());
                    firstflag = false;
                } else {
                    sb.append("&" + entry.getkey() + "=" + entry.getvalue());
                }
            }
        }
        request request = new request.builder()
                .addheader("key", "value")
                .url(sb.tostring())
                .build();
        response response = null;
        try { 
            response = okhttpclient.newcall(request).execute();
            int status = response.code();
            if (response.issuccessful()) {
                return response.body().string();
            }
        } catch (exception e) {
            log.error("okhttp3 post exception:{}", e.getmessage());
        } finally {
            if (response != null) {
                response.close();
            }
        }
        return responsebody;
    }

    /**
     * post请求发送json数据
     * @param url 请求url
     * @param jsonparams 请求的json
     */
    public static string postjsonparams(string url, string jsonparams) {
        string responsebody = "";
        requestbody requestbody = requestbody.create(mediatype.parse("application/json; charset=utf-8"), jsonparams);
        request request = new request.builder()
                .url(url)
                .post(requestbody)
                .build();
        response response = null;
        try { 
            response = okhttpclient.newcall(request).execute();
            int status = response.code();
            if (response.issuccessful()) {
                return response.body().string();
            }
        } catch (exception e) {
            log.error("okhttp3 post exception:{}", e.getmessage());
        } finally {
            if (response != null) {
                response.close();
            }
        }
        return responsebody;
    }

    /**
     * post请求发送xml类型数据
     * @param url 请求url
     * @param xml 请求的xml
     */
    public static string postxmlparams(string url, string xml) {
        string responsebody = "";
        requestbody requestbody = requestbody.create(mediatype.parse("application/xml; charset=utf-8"), xml);
        request request = new request.builder()
                .url(url)
                .post(requestbody)
                .build();
        response response = null;
        try { 
            response = okhttpclient.newcall(request).execute();
            int status = response.code();
            if (response.issuccessful()) {
                return response.body().string();
            }
        } catch (exception e) {
            log.error("okhttp3 post exception:{}", e.getmessage());
        } finally {
            if (response != null) {
                response.close();
            }
        }
        return responsebody;
    }
}

resttemplate

resttemplate 是 spring 框架提供的一个用于进行 http 请求的模板类,它简化了在 java 中进行 http 请求的操作。resttemplate 提供了丰富的方法来发送 http 请求,并且支持多种 http 请求方法(如 get、post、put、delete 等),以及各种数据格式(如 json、xml 等)的处理。
resttemplate 是由spring提供的一个http请求工具。比传统的apache和httpclient便捷许多,能够大大提高客户端的编写效率。

1、spring 提供的用于访问rest服务的客户端, resttemplate 提供了多种便捷访问远程http服务的方法,能够大大提高客户端的编写效率。
2、面向对 restful web 服务调用的功能。
1、spring 提供的用于访问rest服务的客户端, resttemplate 提供了多种便捷访问远程http服务的方法,能够大大提高客户端的编写效率。
2、面向对 restful web 服务调用的功能。
在微服务中的使用
1、第三方服务调用,个人常用 resttemplate, 这里resttemplate未未进行封装,直接使用其方法。
2、微服务间调用,个人使用feign,同时使用okhttp替换feign中默认的httpclient。
feign在默认情况下使用的是jdk原生的urlconnection发送http请求,没有连接池,但是对每个地址会保持一个长连接,即利用http的persistence connection 。 我们可以用http client 或 okhttp 替换feign原始的http client, 从而获取连接池、超时时间等与性能息息相关的控制能力。

特点和优势:

  1. 与 spring 集成: resttemplate 是 spring 框架的一部分,与 spring 生态完美集成,可以轻松在 spring 项目中使用。
  2. 简化 http 请求: resttemplate 封装了发送 http 请求的底层细节,使得发送 http 请求变得简单和方便。
  3. restful 支持: resttemplate 提供了便捷的 restful 风格的 api 调用支持,可以方便地进行资源的增删改查操作。
  4. 丰富的方法: resttemplate 提供了多种方法来发送不同类型的 http 请求,包括 getforobject()、postforobject()、exchange() 等,以及一系列便捷的方法用于设置请求参数、请求头等。
  5. 支持数据转换: resttemplate 支持自动将请求和响应的数据转换为 java 对象,可以通过消息转换器实现 json、xml 等格式的数据转换。
  6. 同步阻塞: resttemplate 是一个同步阻塞的 http 客户端,发送请求后会阻塞当前线程直到收到响应或超时。
  7. 异常处理: resttemplate 提供了异常处理机制,可以捕获和处理请求过程中可能出现的异常。
    resttemplate 是由spring提供的一个http请求工具。比传统的apache和httpclient便捷许多,能够大大提高客户端的编写效率。
    1、spring 提供的用于访问rest服务的客户端, resttemplate 提供了多种便捷访问远程http服务的方法,能够大大提高客户端的编写效率。
    2、面向对 restful web 服务调用的功能。
    1、spring 提供的用于访问rest服务的客户端, resttemplate 提供了多种便捷访问远程http服务的方法,能够大大提高客户端的编写效率。
    2、面向对 restful web 服务调用的功能。
    在微服务中的使用
    1、第三方服务调用,个人常用 resttemplate, 这里resttemplate未未进行封装,直接使用其方法。
    2、微服务间调用,个人使用feign,同时使用okhttp替换feign中默认的httpclient。
    feign在默认情况下使用的是jdk原生的urlconnection发送http请求,没有连接池,但是对每个地址会保持一个长连接,即利用http的persistence connection 。 我们可以用http client 或 okhttp 替换feign原始的http client, 从而获取连接池、超时时间等与性能息息相关的控制能力。

resttemplate 是由spring提供的一个http请求工具。比传统的apache和httpclient便捷许多,能够大大提高客户端的编写效率。

1、spring 提供的用于访问rest服务的客户端, resttemplate 提供了多种便捷访问远程http服务的方法,能够大大提高客户端的编写效率。
2、面向对 restful web 服务调用的功能。
1、spring 提供的用于访问rest服务的客户端, resttemplate 提供了多种便捷访问远程http服务的方法,能够大大提高客户端的编写效率。
2、面向对 restful web 服务调用的功能。
在微服务中的使用
1、第三方服务调用,个人常用 resttemplate, 这里resttemplate未未进行封装,直接使用其方法。
2、微服务间调用,个人使用feign,同时使用okhttp替换feign中默认的httpclient。
feign在默认情况下使用的是jdk原生的urlconnection发送http请求,没有连接池,但是对每个地址会保持一个长连接,即利用http的persistence connection 。 我们可以用http client 或 okhttp 替换feign原始的http client, 从而获取连接池、超时时间等与性能息息相关的控制能力。

springcloud 1.x
<!-- 使用apache httpclient替换feign原生httpclient -->
        <dependency>
            <groupid>org.apache.httpcomponents</groupid>
            <artifactid>httpclient</artifactid>
        </dependency>
        <dependency>
            <groupid>com.netflix.feign</groupid>
            <artifactid>feign-httpclient</artifactid>
            <version>${feign-httpclient}</version>
        </dependency>

application.properties中添加:
feign.httpclient.enabled=true
<!-- 使用okhttp替换feign原生httpclient -->
<dependency>
    <groupid>io.github.openfeign</groupid>
    <artifactid>feign-okhttp</artifactid>
    <version>10.2.0</version>
</dependency>

 springcolud 2.x
<!-- 使用okhttp替换openfeign原生httpclient -->
<dependency>
  <groupid>com.squareup.okhttp3</groupid>
  <artifactid>okhttp</artifactid>
  <version>3.10.0</version>
</dependency>

application.properties中添加:
feign.okhttp.enabled=true

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com