HTTP协议客户端之HttpClient的基本使用
HttpClient的基本使用
概述
HttpClient 是Apache Jakarta Common 下的子项目,可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。
HttpClient相比JDK自带的URLConnection,增加了易用性和灵活性,使客户端发送Http请求变得更加容易,而且也方便开发测试接口,大大提高开发的效率。
常用HTTP协议客户端包括有:httpclient、restTemplate、okHttp
官网:https://hc.apache.org/index.html
添加依赖
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.13</version> </dependency>
Get请求
1.无参数的GET请求
@Test public void get() throws IOException { // 创建HttpClient对象 CloseableHttpClient httpClient = HttpClients.createDefault(); // 创建HttpGet请求 HttpGet httpGet = new HttpGet("https://www.baidu.com"); // 响应对象 CloseableHttpResponse response = null; try { // 使用HttpClient发起请求 response = httpClient.execute(httpGet); // 判断响应状态码是否为200 if (response.getStatusLine().getStatusCode() == 200) { // 获取返回数据 HttpEntity httpEntity = response.getEntity(); String content = EntityUtils.toString(httpEntity, "UTF-8"); // 打印数据长度 log.info("content:{}", content); } } finally { // 释放连接 if (response != null) { response.close(); } httpClient.close(); } }
2.带参数的GET请求
HttpGet httpGet = new HttpGet("https://www.baidu.com/s?wd=java");
POST请求
1.无参数的POST请求
@Test public void post() throws IOException { // 创建HttpClient对象 CloseableHttpClient httpClient = HttpClients.createDefault(); // 创建HttpGet请求 HttpPost httpPost = new HttpPost("http://www.baidu.com"); // 响应对象 CloseableHttpResponse response = null; try { // 使用HttpClient发起请求 response = httpClient.execute(httpPost); // 判断响应状态码是否为200 if (response.getStatusLine().getStatusCode() == 200) { // 获取返回数据 HttpEntity httpEntity = response.getEntity(); String content = EntityUtils.toString(httpEntity, "UTF-8"); // 打印数据长度 log.info("content:{}", content); } } finally { // 释放连接 if (response != null) { response.close(); } httpClient.close(); } }
2.带参数的POST请求
public static void main(String[] args) throws Exception { // 创建HttpClient对象 CloseableHttpClient httpClient = HttpClients.createDefault(); // 创建HttpPost对象,设置url访问地址 HttpPost httpPost = new HttpPost("https://fanyi.baidu.com/langdetect"); // 声明List集合,封装表单中的参数 List<NameValuePair> params = new ArrayList<NameValuePair>(); // 实际请求地址:https://fanyi.baidu.com/langdetect?query=Java params.add(new BasicNameValuePair("query", "Java")); // 创建表单的Entity对象,第一个参数是封装好的表单数据,第二个参数是编码 UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(params, "utf8"); //设置表单的Entity对象到Post请求中 httpPost.setEntity(formEntity); CloseableHttpResponse response = null; try { // 使用HttpClient发起请求,获取response response = httpClient.execute(httpPost); // 解析响应 if (response.getStatusLine().getStatusCode() == 200) { String content = EntityUtils.toString(response.getEntity(), "utf8"); log.info("content={}", content); } } finally { // 关闭资源 response.close(); httpClient.close(); } }
连接池
每次请求都要创建HttpClient,会有频繁创建和销毁的问题,可以使用连接池来解决这个问题。
public class HttpClientPool { public static PoolingHttpClientConnectionManager getHttpClientPool(){ // 创建连接池管理器 PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(); // 设置最大连接数 poolingHttpClientConnectionManager.setMaxTotal(100); // 设置每个主机的最大连接数 poolingHttpClientConnectionManager.setDefaultMaxPerRoute(10); return poolingHttpClientConnectionManager; } public static void main(String[] args) { // 使用连接池管理器发起请求 PoolingHttpClientConnectionManager httpClientPool = HttpClientPool.getHttpClientPool(); // 从连接池中获取HttpClient对象 CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(httpClientPool).build(); } }
请求参数配置
对请求进行参数配置,如cookie设置,代理设置,以及常用的请求超时时间设置。
public class HttpClientPool { public static PoolingHttpClientConnectionManager getHttpClientPool() { // 创建连接池管理器 PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(); // 设置最大连接数 poolingHttpClientConnectionManager.setMaxTotal(100); // 设置每个主机的最大连接数 poolingHttpClientConnectionManager.setDefaultMaxPerRoute(10); return poolingHttpClientConnectionManager; } public static void main(String[] args) throws IOException { // 使用连接池管理器发起请求 PoolingHttpClientConnectionManager httpClientPool = HttpClientPool.getHttpClientPool(); // 从连接池中获取HttpClient对象 CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(httpClientPool).build(); HttpGet httpGet = new HttpGet("http://www.baidu.com"); // 配置请求信息 RequestConfig config = RequestConfig.custom() // 创建连接的最长时间,单位是毫秒 .setConnectTimeout(1000) // 设置获取连接的最长时间,单位是毫秒 .setConnectionRequestTimeout(500) // 设置数据传输的最长时间,单位是毫秒 .setSocketTimeout(10 * 1000) .build(); // 给请求设置请求信息 httpGet.setConfig(config); // 使用HttpClient发起请求,获取response CloseableHttpResponse execute = httpClient.execute(httpGet); } }
工具类封装
HttpClientResult
/** * Description: 封装httpClient响应结果 */ @Data @AllArgsConstructor @NoArgsConstructor public class HttpClientResult implements Serializable { /** * 响应状态码 */ private int code; /** * 响应数据 */ private String content; }
HttpClientUtils
import org.apache.http.HttpStatus; 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.*; import org.apache.http.client.utils.URIBuilder; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.*; /** * Description: httpClient工具类 */ public class HttpClientUtils { // 编码格式。发送编码格式统一用UTF-8 private static final String ENCODING = "UTF-8"; // 设置连接超时时间,单位毫秒。 private static final int CONNECT_TIMEOUT = 6000; // 请求获取数据的超时时间(即响应时间),单位毫秒。 private static final int SOCKET_TIMEOUT = 6000; /** * 发送get请求;不带请求头和请求参数 * * @param url 请求地址 */ public static HttpClientResult doGet(String url) throws Exception { return doGet(url, null, null); } /** * 发送get请求;带请求参数 * * @param url 请求地址 * @param params 请求参数集合 */ public static HttpClientResult doGet(String url, Map<String, String> params) throws Exception { return doGet(url, null, params); } /** * 发送get请求;带请求头和请求参数 * * @param url 请求地址 * @param headers 请求头集合 * @param params 请求参数集合 */ public static HttpClientResult doGet(String url, Map<String, String> headers, Map<String, String> params) throws Exception { // 创建httpClient对象 CloseableHttpClient httpClient = HttpClients.createDefault(); // 创建访问的地址 URIBuilder uriBuilder = new URIBuilder(url); if (params != null) { Set<Map.Entry<String, String>> entrySet = params.entrySet(); for (Map.Entry<String, String> entry : entrySet) { uriBuilder.setParameter(entry.getKey(), entry.getValue()); } } // 创建http对象 HttpGet httpGet = new HttpGet(uriBuilder.build()); /** * setConnectTimeout:设置连接超时时间,单位毫秒。 * setConnectionRequestTimeout:设置从connect Manager(连接池)获取Connection * 超时时间,单位毫秒。这个属性是新加的属性,因为目前版本是可以共享连接池的。 * setSocketTimeout:请求获取数据的超时时间(即响应时间),单位毫秒。 如果访问一个接口,多少时间内无法返回数据,就直接放弃此次调用。 */ RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(CONNECT_TIMEOUT).setSocketTimeout(SOCKET_TIMEOUT).build(); httpGet.setConfig(requestConfig); // 设置请求头 packageHeader(headers, httpGet); try { // 执行请求并获得响应结果 return getHttpClientResult(httpClient, httpGet); } finally { // 释放资源 close(httpClient); } } /** * 发送post请求;不带请求头和请求参数 * * @param url 请求地址 */ public static HttpClientResult doPost(String url) throws Exception { return doPost(url, null, null); } /** * 发送post请求;带请求参数 * * @param url 请求地址 * @param params 参数集合 */ public static HttpClientResult doPost(String url, Map<String, String> params) throws Exception { return doPost(url, null, params); } /** * 发送post请求;带请求头和请求参数 * * @param url 请求地址 * @param headers 请求头集合 * @param params 请求参数集合 */ public static HttpClientResult doPost(String url, Map<String, String> headers, Map<String, String> params) throws Exception { // 创建httpClient对象 CloseableHttpClient httpClient = HttpClients.createDefault(); // 创建http对象 HttpPost httpPost = new HttpPost(url); /** * setConnectTimeout:设置连接超时时间,单位毫秒。 * setConnectionRequestTimeout:设置从connect Manager(连接池)获取Connection * 超时时间,单位毫秒。这个属性是新加的属性,因为目前版本是可以共享连接池的。 * setSocketTimeout:请求获取数据的超时时间(即响应时间),单位毫秒。 如果访问一个接口,多少时间内无法返回数据,就直接放弃此次调用。 */ RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(CONNECT_TIMEOUT).setSocketTimeout(SOCKET_TIMEOUT).build(); httpPost.setConfig(requestConfig); // 设置请求头 /*httpPost.setHeader("Cookie", ""); httpPost.setHeader("Accept", "application/json"); httpPost.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36");*/ packageHeader(headers, httpPost); // 封装请求参数 packageParam(params, httpPost); try { // 执行请求并获得响应结果 return getHttpClientResult(httpClient, httpPost); } finally { // 释放资源 close(httpClient); } } /** * 发送put请求;不带请求参数 * * @param url 请求地址 */ public static HttpClientResult doPut(String url) throws Exception { return doPut(url, null); } /** * 发送put请求;带请求参数 * * @param url 请求地址 * @param params 参数集合 */ public static HttpClientResult doPut(String url, Map<String, String> params) throws Exception { CloseableHttpClient httpClient = HttpClients.createDefault(); HttpPut httpPut = new HttpPut(url); RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(CONNECT_TIMEOUT).setSocketTimeout(SOCKET_TIMEOUT).build(); httpPut.setConfig(requestConfig); packageParam(params, httpPut); try { return getHttpClientResult(httpClient, httpPut); } finally { close(httpClient); } } /** * 发送delete请求;不带请求参数 * * @param url 请求地址 */ public static HttpClientResult doDelete(String url) throws Exception { CloseableHttpClient httpClient = HttpClients.createDefault(); HttpDelete httpDelete = new HttpDelete(url); RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(CONNECT_TIMEOUT).setSocketTimeout(SOCKET_TIMEOUT).build(); httpDelete.setConfig(requestConfig); try { return getHttpClientResult(httpClient, httpDelete); } finally { close(httpClient); } } /** * 发送delete请求;带请求参数 * * @param url 请求地址 * @param params 参数集合 */ public static HttpClientResult doDelete(String url, Map<String, String> params) throws Exception { if (params == null) { params = new HashMap<>(); } params.put("_method", "delete"); return doPost(url, params); } /** * Description: 封装请求头 */ public static void packageHeader(Map<String, String> params, HttpRequestBase httpMethod) { // 封装请求头 if (params != null) { Set<Map.Entry<String, String>> entrySet = params.entrySet(); for (Map.Entry<String, String> entry : entrySet) { // 设置到请求头到HttpRequestBase对象中 httpMethod.setHeader(entry.getKey(), entry.getValue()); } } } /** * Description: 封装请求参数 */ public static void packageParam(Map<String, String> params, HttpEntityEnclosingRequestBase httpMethod) throws UnsupportedEncodingException { // 封装请求参数 if (params != null) { List<NameValuePair> nvps = new ArrayList<>(); Set<Map.Entry<String, String>> entrySet = params.entrySet(); for (Map.Entry<String, String> entry : entrySet) { nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue())); } // 设置到请求的http对象中 httpMethod.setEntity(new UrlEncodedFormEntity(nvps, ENCODING)); } } /** * Description: 获得响应结果 */ public static HttpClientResult getHttpClientResult(CloseableHttpClient httpClient, HttpRequestBase httpMethod) throws IOException { try (CloseableHttpResponse httpResponse = httpClient.execute(httpMethod)) { // 获取返回结果 if (httpResponse != null && httpResponse.getStatusLine() != null) { String content = ""; if (httpResponse.getEntity() != null) { content = EntityUtils.toString(httpResponse.getEntity(), ENCODING); } return new HttpClientResult(httpResponse.getStatusLine().getStatusCode(), content); } } return new HttpClientResult(HttpStatus.SC_INTERNAL_SERVER_ERROR, null); } /** * Description: 释放资源 */ public static void close(CloseableHttpClient httpClient) throws IOException { if (httpClient != null) { httpClient.close(); } } }
测试
public class HttpClientUtilsTest { /** * Description: 测试get无参请求 */ @Test public void testGet() throws Exception { HttpClientResult result = HttpClientUtils.doGet("https://www.baidu.com"); System.out.println(result); } /** * Description: 测试get带参请求 */ @Test public void testGetWithParam() throws Exception { Map<String, String> params = new HashMap<String, String>(); params.put("word", "java"); HttpClientResult result = HttpClientUtils.doGet("url", params); System.out.println(result); } /** * Description: 测试post带请求头不带请求参数 */ @Test public void testPost() throws Exception { Map<String, String> headers = new HashMap<String, String>(); headers.put("Cookie", "cokie"); headers.put("Accept", "application/json"); headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36"); HttpClientResult result = HttpClientUtils.doPost("url", headers, null); System.out.println(result); } /** * Description: 测试post带参请求 */ @Test public void testPostWithParam() throws Exception { Map<String, String> params = new HashMap<String, String>(); params.put("word", "java"); HttpClientResult result = HttpClientUtils.doPost("url", params); System.out.println(result); } }#HTTP##Java##程序员#