当前位置: 代码网 > it编程>编程语言>Java > 在SpringBoot中如何使用HttpClient实现HTTP请求

在SpringBoot中如何使用HttpClient实现HTTP请求

2025年02月14日 Java 我要评论
springboot使用httpclient实现http请求越来越多的 java 应用程序需要直接通过 http 协议来访问网络资源。虽然在 jdk 的 java.net 包中已经提供了访问 http

springboot使用httpclient实现http请求

越来越多的 java 应用程序需要直接通过 http 协议来访问网络资源。虽然在 jdk 的 java.net 包中已经提供了访问 http 协议的基本功能,但是对于大部分应用程序来说,jdk 库本身提供的功能还不够丰富和灵活。

httpclient 是 apache jakarta common 下的子项目,用来提供高效的、最新的、功能丰富的支持 http 协议的客户端编程工具包,并且它支持 http 协议最新的版本和建议。

httpclient 官网

新建一个 springboot 工程,引入 httpclient 的 pom 依赖:

<dependency>
	<groupid>org.apache.httpcomponents</groupid>
	<artifactid>httpclient</artifactid>
	<version>4.5.6</version>
</dependency>

总结:

public class httpclientutil {

    // get请求
    public static string get(string url, jsonobject params) {
        closeablehttpclient httpclient = httpclientbuilder.create().build();
        string sendurl = url;
        // 拼接参数
        if (objects.nonnull(params) && params.size() > 0) {
            sendurl = connectparams(url, params);
        }
        httpget httpget = new httpget(sendurl);
        closeablehttpresponse response = null;
        try {
            response = httpclient.execute(httpget);
            httpentity httpentity = response.getentity();
            if (httpstatus.sc_ok == response.getstatusline().getstatuscode() && null != httpentity) {
                return entityutils.tostring(httpentity);
            }
        } catch (ioexception e) {
            e.printstacktrace();
        } finally {
            try {
                close(httpclient, response);
            } catch (ioexception e) {
                e.printstacktrace();
            }
        }
        throw new jeecgbootexception("调用get请求失败!");
    }

    /**
     * @description: post 请求
     * @author: zzc
     * @date: 2022-12-16 16:48
     * @param url: 
     * @param params: 
     * @param requestbody: json 串
     * @return: java.lang.string
     **/
    public static string post(string url, jsonobject params, string requestbody) {
        closeablehttpclient httpclient = httpclientbuilder.create().build();
        string sendurl = url;
        // 1.拼接参数
        if (objects.nonnull(params) && params.size() > 0) {
            sendurl = connectparams(url, params);
        }
        httppost httppost = new httppost(sendurl);
        httppost.setheader("content-type", "application/json;charset=utf8");
        closeablehttpresponse response = null;
        try {
            // 2.设置request-body
            if (stringutils.isnotblank(requestbody)) {
                bytearrayentity entity = new bytearrayentity(requestbody.getbytes(standardcharsets.utf_8));
                entity.setcontenttype("application/json");
                httppost.setentity(entity);
            }
            response = httpclient.execute(httppost);
            httpentity httpentity = response.getentity();
            if (httpstatus.sc_ok == response.getstatusline().getstatuscode() && null != httpentity) {
                return entityutils.tostring(httpentity);
            }
        } catch (unsupportedencodingexception e) {
            e.printstacktrace();
        } catch (clientprotocolexception e) {
            e.printstacktrace();
        } catch (ioexception e) {
            e.printstacktrace();
        } finally {
            try {
                close(httpclient, response);
            } catch (ioexception e) {
                e.printstacktrace();
            }
        }
        throw new jeecgbootexception("调用post请求失败!");
    }

    private static string connectparams(string url, jsonobject params) {
        stringbuffer buffer = new stringbuffer();
        buffer.append(url).append("?");
        params.foreach((x, y) -> buffer.append(x).append("=").append(y).append("&"));
        buffer.deletecharat(buffer.length() - 1);
        return buffer.tostring();
    }

    public static void close(closeablehttpclient httpclient, closeablehttpresponse httpresponse) throws ioexception{
        if (null != httpclient) {
            httpclient.close();
        }
        if (null != httpresponse) {
            httpresponse.close();
        }
    }

}

详细使用示例

get 无参

调用接口:

http://localhost:8080/http/listusers

没有入参。

httpclientcontroller#dogetnoparams():get请求接口不带参数

@restcontroller
@requestmapping("/httpclient")
public class httpclientcontroller {

    @autowired
    private httpclientservice httpclientservice;

    // get请求接口不带参数
    @getmapping("/dogetnoparams")
    public string dogetnoparams() {
        return httpclientservice.dogetnoparams();
    }

}

httpclientserviceimpl#dogetnoparams():get 请求接口不带参数

@slf4j
@service
public class httpclientserviceimpl implements httpclientservice {

    // get请求接口不带参数
    @override
    public string dogetnoparams() {
        string result = httpclientutil.dogetnoparams();
        log.info("【发送get请求】返回结果为:{}", result);
        if (!stringutil.isblank(result)) {
            taskcenterutil taskcenterutil = taskcenterutil.gettaskcenterutil();
            taskcenterutil.submittask(() -> {
                log.info("【子线程】开启了一个新线程,当前线程名为:{}", thread.currentthread().getname());
                return null;
            });
        }
        log.info("【主线程】当前线程名为:{}", thread.currentthread().getname());
        return result;
    }

}

说明:

  1. 当 http 调用成功后,通过线程池开一个子线程,去异步执行任务;主线程继续向下执行

httpclientutil#dogetnoparams():get请求接口不带参数

@slf4j
public class httpclientutil {

    // 服务器ip
    public static final string ip = "http://localhost";

    // 端口
    public static final string port = ":8080";

    // get请求接口不带参数
    public static final string get_url_no_params = ip + port + "/http/listusers";

    // get请求接口不带参数
    public static string dogetnoparams() {
        closeablehttpclient httpclient = httpclientbuilder.create().build();
        // 创建 get 请求
        httpget httpget = new httpget(get_url_no_params);
        httpget.setheader("accept-encoding", "identity");
        log.info("【发送get请求】请求地址为:{}", get_url_no_params);
        closeablehttpresponse httpresponse = null;
        try {
            httpresponse = httpclient.execute(httpget);
            httpentity httpentity = httpresponse.getentity();
            log.info("【发送get请求】成功,相应状态为:{}", httpresponse.getstatusline());
            if (httpstatus.sc_ok == httpresponse.getstatusline().getstatuscode() && null != httpentity) {
                string result = entityutils.tostring(httpentity);
                log.info("【发送get请求】成功,响应内容为:{}", result);
                return result;
            }
        } catch (ioexception e) {
            log.error("【发送get请求】失败,执行发送请求时,出现io异常,异常信息为:{}", e);
            return null;
        } finally {
            try {
                close(httpclient, httpresponse);
            } catch (ioexception e) {
                log.error("【发送get请求】失败,关闭流时,出现io异常,异常信息为:{}", e);
            }
        }
        return null;
    }

}

说明:

  1. 通过类 httpget 发起 get 请求。

httpget:有 3 个构造方法

public class httpget extends httprequestbase {

    public httpget() {
    }

    public httpget(uri uri) {
        this.seturi(uri);
    }

    public httpget(string uri) {
        this.seturi(uri.create(uri));
    }

    ...
}

这里使用了 public httpget(string uri); 方式来构造 httpget 实例。

httpclientutil#close():关闭流

// 关闭流
public static void close(closeablehttpclient httpclient, closeablehttpresponse httpresponse) throws ioexception{
    if (null != httpclient) {
        httpclient.close();
    }
    if (null != httpresponse) {
        httpresponse.close();
    }
}

taskcenterutil:线程池工具类

public class taskcenterutil {

    public static integer core_pool_size = 10;
    public static integer max_num_pool_size = 10;
    public static integer max_message_size = 100;
    public static long keep_alive_time = 60l;

    private threadpoolexecutor poolexecutor = new threadpoolexecutor(core_pool_size, max_num_pool_size, keep_alive_time,
            timeunit.seconds, new linkedblockingqueue<>(max_message_size), new threadpoolexecutor.callerrunspolicy());


    private taskcenterutil() {}

    private static taskcenterutil taskcenterutil = new taskcenterutil();

    public static taskcenterutil gettaskcenterutil() {
        return taskcenterutil;
    }

    // 提交任务
    public void submittask(callable task) {
        poolexecutor.submit(task);
    }

}

postman 调用:

控制台打印日志:

get 有参

  • 方式一:使用 public httpget(string uri); 方式来构造 httpget 实例。即:使用 url 字符串来拼接参数。
  • 方式二:使用 public httpget(uri uri); 方式来构造 httpget 实例。

调用接口:

http://localhost:8080/http/getuserbyid?id=1

入参:

id=1

httpclientcontroller#dogetparams():get请求接口带参数

@getmapping("/dogetparams")
public string dogetparams(string id) {
    return httpclientservice.dogetparams(id);
}

httpclientserviceimpl

@override
public string dogetparams(string id) {
    string result = httpclientutil.dogetparams(id);
    log.info("【发送get请求】返回结果为:{}", result);
    return result;
}

httpclientutil#dogetparams():get请求接口带参数

@slf4j
public class httpclientutil {

    // get请求接口带参数
    public static final string get_url_params = ip + port + "/http/getuserbyid";

    // 入参名称
    public static final string url_params_id = "id";
	
	// http 协议
    public static final string scheme_http = "http";

    // 主机
    public static final string local_host = "localhost";

    // 请求接口路径
    public static final string get_url_params_path = "/http/getuserbyid";

    // 端口
    public static final integer local_port = 8080;

    // get请求接口带参数
    public static string dogetparams(string id) {
        closeablehttpclient httpclient = httpclientbuilder.create().build();
        // 不同方式获取 httpget
        // 方式一:
        httpget httpget = getstrhttpget(get_url_params, id);
        // 方式二:
        //httpget httpget = geturlhttpget(id);
        // 获取请求头配置信息
        requestconfig requestconfig = httpclientconfig.getrequestconfig();
        httpget.setconfig(requestconfig);
        closeablehttpresponse response = null;
        try {
            response = httpclient.execute(httpget);
            httpentity httpentity = response.getentity();
            log.info("【发送get请求】成功,相应状态为:{}", response.getstatusline());
            if (httpstatus.sc_ok == response.getstatusline().getstatuscode() && null != httpentity) {
                string result = entityutils.tostring(httpentity);
                log.info("【发送get请求】成功,响应内容为:{}", result);
                return result;
            }
        } catch (ioexception e) {
            log.error("【发送get请求】失败,执行发送请求时,出现io异常,异常信息为:{}", e);
            return null;
        } finally {
            try {
                close(httpclient, response);
            } catch (ioexception e) {
                log.error("【发送get请求】失败,关闭流时,出现io异常,异常信息为:{}", e);
            }
        }
        return null;
    }
}

getstrhttpget():方式一:url拼接参数

public static httpget getstrhttpget(string url, string id) {
    stringbuilder builder = new stringbuilder();
    // url 拼接参数  /http/getuserbyid?id=1
    string strurl = builder.append(url).append("?").append(url_params_id).append("=").append(id).tostring();
    log.info("【发送get请求】请求地址为:{}", strurl);
    httpget httpget = new httpget(strurl);
    return httpget;
}

geturlhttpget():方式二:uri对象

public static httpget geturlhttpget(string id) {
    // 将参数键值对放入集合中
    list<namevaluepair> params = new arraylist<>();
    params.add(new basicnamevaluepair(url_params_id, id));
    try {
        uri uri = new uribuilder()
                .setscheme(scheme_http)
                .sethost(local_host)
                .setport(local_port)
                .setpath(get_url_params_path)
                .setparameters(params).build();
        return new httpget(uri);
    } catch (urisyntaxexception e) {
        log.error("【发送get请求】构建uri失败,失败信息为:{}", e);
    }
    return null;
}

说明:

  1. 方式一是使用 public httpget(string uri); 方式来构造 httpget 实例
  2. 方式二是使用 public httpget(url uri); 方式来构造 httpget 实例。即:使用 url 字符串来拼接参数。

postman 调用:

post 无参

调用接口:

http://localhost:8080/http/listuserlist

入参:无

httpclientcontroller#dopostnoparams():post请求接口不带参数

@postmapping("/dopostnoparams")
public string dopostnoparams() {
    return httpclientservice.dopostnoparams();
}

httpclientserviceimpl#dopostnoparams()

@override
public string dopostnoparams() {
    string result = httpclientutil.dopostnoparams();
    log.info("【发送post请求】返回结果为:{}", result);
    return result;
}

httpclientutil

public class httpclientutil {

    // post请求接口不带参数
    public static final string post_url_no_params = ip + port + "/http/listuserlist";
	
	// post请求接口带参数
    public static final string post_url_params = ip + port + "/http/getuservobyid";

    // post请求接口带参数 -- 对象参数
    public static final string post_url_params_object = ip + port + "/http/listusers";

    // post请求接口不带参数
    public static string dopostnoparams() {
        closeablehttpclient httpclient = httpclientbuilder.create().build();
        httppost httppost = new httppost(post_url_no_params);
        log.info("【发送post请求】请求地址为:{}", post_url_no_params);
        closeablehttpresponse response = null;
        try {
            response = httpclient.execute(httppost);
            httpentity httpentity = response.getentity();
            log.info("【发送post请求】成功,相应状态为:{}", response.getstatusline());
            if (httpstatus.sc_ok == response.getstatusline().getstatuscode() && null != httpentity) {
                string result = entityutils.tostring(httpentity);
                log.info("【发送post请求】成功,响应内容为:{}", result);
                return result;
            }
        } catch (ioexception e) {
            log.error("【发送post请求】失败,执行发送请求时,出现io异常,异常信息为:{}", e);
            return null;
        } finally {
            try {
                close(httpclient, response);
            } catch (ioexception e) {
                log.error("【发送post请求】失败,关闭流时,出现io异常,异常信息为:{}", e);
            }
        }
        return null;
    }

}

post 有参

  • 参数是:普通参数。方式与get一样即可,直接在 url 后缀上拼接参数
  • 参数是:对象。将参数以请求体 request-body 的方式进行请求
  • 参数是:普通参数+对象。普通参数 直接在 url 后缀上拼接参数;对象 以请求体 request-body 的方式进行请求

普通参数

请求接口:

http://localhost:8080/http/getuservobyid?id=1

对象参数

请求接口:

http://localhost:8080/http/listusers

入参 uservo:

{
	"id": 1
}

即:这个接口可以随便写

@postmapping("/listusers")
public list<uservo> listusers(@requestbody uservo uservo) {
    return httpservice.listusers();
}

httpclientcontroller#dopostparams():post请求接口带参数

@postmapping("/dopostparams")
public string dopostparams(string id) {
    return httpclientservice.dopostparams(id);
}

httpclientserviceimpl#dopostparams()

@override
public string dopostparams(string id) {
    string result = httpclientutil.dopostparams(id);
    log.info("【发送post请求】返回结果为:{}", result);
    return result;
}

httpclientutil#dopostparams()

public static string dopostparams(string id) {
    closeablehttpclient httpclient = httpclientbuilder.create().build();
    // 参数是普通参数
    httppost httppost = getstrhttppost(post_url_params, id);
    // 参数是对象
    //httppost httppost = getobjecthttppost(id);
    // 设置contenttype(注:如果只是传普通参数的话,contenttype不一定非要用application/json)
    httppost.setheader("content-type", "application/json;charset=utf8");
    closeablehttpresponse response = null;
    try {
        response = httpclient.execute(httppost);
        httpentity httpentity = response.getentity();
        log.info("【发送post请求】成功,相应状态为:{}", response.getstatusline());
        if (httpstatus.sc_ok == response.getstatusline().getstatuscode() && null != httpentity) {
            string result = entityutils.tostring(httpentity);
            log.info("【发送post请求】成功,响应内容为:{}", result);
            return result;
        }
    } catch (ioexception e) {
        log.error("【发送post请求】失败,执行发送请求时,出现io异常,异常信息为:{}", e);
        return null;
    } finally {
        try {
            close(httpclient, response);
        } catch (ioexception e) {
            log.error("【发送post请求】失败,关闭流时,出现io异常,异常信息为:{}", e);
        }
    }
    return null;
}

getstrhttppost():post请求有参:普通参数

public static httppost getstrhttppost(string url, string id) {
    stringbuilder builder = new stringbuilder();
    // url 拼接参数  /http/getuservobyid?id=1
    string strurl = builder.append(url).append("?").append(url_params_id).append("=").append(id).tostring();
    log.info("【发送post请求】请求地址为:{}", strurl);
    httppost httppost = new httppost(strurl);
    return httppost;
}

getobjecthttppost():post请求有参:对象参数

public static httppost getobjecthttppost(string id) {
    httppost httppost = new httppost(post_url_params_object);
    log.info("【发送post请求】请求地址为:{}", post_url_params_object);
    uservo uservo = new uservo();
    uservo.setid(id);
    // 将java对象转换为json字符串
    string jsonstring = json.tojsonstring(uservo);
    stringentity stringentity = new stringentity(jsonstring, "utf-8");
    // post请求是将参数放在请求体里面传过去的
    httppost.setentity(stringentity);
    return httppost;
}

普通参数 + 对象

// params:name=zzc&age=17  marshal:json 串
public static string post(string url, string params, string marshal) {
    closeablehttpclient httpclient = httpclientbuilder.create().build();
    string strurl = url + "?" + params;
    httppost httppost = new httppost(strurl);
    httppost.setheader("content-type", "application/json;charset=utf8");

    closeablehttpresponse response = null;
    try {
        // 设置 requst-body 参数
        bytearrayentity entity = new bytearrayentity(marshal.getbytes("utf-8"));
        entity.setcontenttype("application/json");
        httppost.setentity(entity);

        response = httpclient.execute(httppost);
        httpentity httpentity = response.getentity();
        if (httpstatus.sc_ok == response.getstatusline().getstatuscode() && null != httpentity) {
            string result = entityutils.tostring(httpentity);
            return result;
        }
    } catch (exception e) {
        e.printstacktrace();
    } finally {
        try {
            close(httpclient, response);
        } catch (ioexception e) {
            e.printstacktrace();
        }
    }
    return null;
}

表单提交

public static string post(string url, map<string, string> params) {
    closeablehttpclient httpclient = httpclientbuilder.create().build();
    httppost httppost = new httppost(url);
    httppost.setheader("content-type", "application/x-www-form-urlencoded");
    // 参数
    list<namevaluepair> namevaluepairs = new arraylist<>();
    if (maputils.isnotempty(params)) {
        params.foreach((x, y) -> {
            namevaluepairs.add(new basicnamevaluepair(x, y));
        });
    }
    closeablehttpresponse response = null;
    try {
        httppost.setentity(new urlencodedformentity(namevaluepairs));
        response = httpclient.execute(httppost);
        httpentity httpentity = response.getentity();
        if (httpstatus.sc_ok == response.getstatusline().getstatuscode() && null != httpentity) {
            return entityutils.tostring(httpentity);
        }
    } catch (ioexception e) {
        e.printstacktrace();
    } finally {
        try {
            close(httpclient, response);
        } catch (ioexception e) {
            e.printstacktrace();
        }
    }
    throw new jeecgbootexception("调用accesstoken api失败");
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

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

发表评论

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