HttpClient-Java

丁曦哲
2023-12-01

一、JDK原生方式发送请求

Java中发送http请求,类型有get请求,post请求,这里用jdk原生的方式,发送http请求。

/**
     * 使用jdk原生api请求网页
     */
@Test
public void test() throws Exception {
	URL url = new URL("https://www.baidu.com");
	URLConnection urlConnection = url.openConnection();
	HttpURLConnection httpURLConnection = (HttpURLConnection) urlConnection;
	// 设置请求类型
	httpURLConnection.setRequestMethod("GET");
	httpURLConnection.setRequestProperty("Accept-Charset", "UTF-8");
	// 获取HttpURLConnection的输入流
	try (
		InputStream is = httpURLConnection.getInputStream();
		InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8);
		BufferedReader br = new BufferedReader(isr)
	) {
		String line;
		while ((line = br.readLine())!= null) {
			System.out.println(line);
		}
	}
}

二、HttpClient

2.1 HttpClient发送get请求

package cn.cy.study.httpclient;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.junit.Test;

import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

public class HttpClientTest {

    @Test
    public void test() {
        // 可关闭的httpClient客户端,相当于打开一个浏览器
        CloseableHttpClient closeableHttpClient = HttpClients.createDefault();
        String url = "https://www.baidu.com";
        // 构造httpGet请求对象
        HttpGet httpGet = new HttpGet(url);
        // HttpClient可以设置请求头
        httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW)");
        // 可关闭的响应
        CloseableHttpResponse response = null;
        try {
            response = closeableHttpClient.execute(httpGet);
            // 获取请求状态
            StatusLine statusLine = response.getStatusLine();
            if (HttpStatus.SC_OK == statusLine.getStatusCode()) {
                System.out.println("响应成功!");
                // 获取请求头
                Header[] headers = response.getAllHeaders();
                for (Header header : headers) {
                    System.out.println("响应头:" + header.getName() + "的值:" + header.getValue());
                }
                // 获取响应结果
                HttpEntity entity = response.getEntity();
                System.out.println("Content type:" + entity.getContentType());
                // 工具类,对httpEntity操作的工具类
                String result = EntityUtils.toString(entity, StandardCharsets.UTF_8);
                System.out.println(result);
                // 确保流关闭
                EntityUtils.consume(entity);
            } else {
                System.out.println("响应失败,响应码:" + statusLine.getStatusCode());
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (closeableHttpClient != null) {
                try {
                    closeableHttpClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

  • 如果想设置get请求的请求头,则对HttpGet对象,使用addHeader()方法即可。
  • 如果想发送带参数的get请求,则在url后拼接参数即可。
  • 如果携带的参数有特殊类型字符,例如+、|等,则需要urlEncode下参数,例如
String url = "https://www.baidu.com";
String param = "a+";
param = URLEncoder.encode(param, StandardCharsets.UTF_8.name());
url = url + "?" + param;

2.2 HttpClient保存网络图片到本地

package cn.cy.study.httpclient;

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.junit.Test;

import java.io.FileOutputStream;
import java.io.UnsupportedEncodingException;

public class HttpClientTest {

    /**
     * httpclient保存网络的图片到本地
     */
    @Test
    public void testSavaImage() {
        CloseableHttpClient closeableHttpClient = HttpClients.createDefault();
        String url = "https://img-home.csdnimg.cn/images/20230111035923.jpg";
        HttpGet httpGet = new HttpGet(url);
        CloseableHttpResponse response = null;
        try {
            response = closeableHttpClient.execute(httpGet);
            HttpEntity entity = response.getEntity();
            // imgage/jpg or image/jpeg or image/png
            String contentType = entity.getContentType().getValue();
            String sffix = ".jpg";
            if (contentType.contains("bmp") || contentType.contains("bitmap")) {
                sffix = ".bmp";
            } else if (contentType.contains("png")){
                sffix = ".png";
            } else if (contentType.contains("gif")){
                sffix = ".gif";
            }
            // 获取文件的字节流
            byte[] bytes = EntityUtils.toByteArray(entity);
            FileOutputStream fos = new FileOutputStream("image." + sffix);
            fos.write(bytes);
            fos.close();
            EntityUtils.consume(entity);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (closeableHttpClient != null) {
                try {
                    closeableHttpClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

2.3 HttpClient设置代理

/**
     * httpclient设置访问代理
     */
    @Test
    public void testSetAgent() {
        CloseableHttpClient closeableHttpClient = HttpClients.createDefault();
        String url = "https://www.bilibili.com/video/BV1W54y1s7BZ/?p=9&spm_id_from=pageDriver&vd_source=1ade285c97f069b124a94bec55aa289c";
        HttpGet httpGet = new HttpGet(url);
        // 创建代理
        HttpHost proxy = new HttpHost("104.18.16.1", 80);
        // 对请求的配置,会覆盖全局配置
        RequestConfig requestConfig = RequestConfig.custom().setProxy(proxy).build();
        httpGet.setConfig(requestConfig);
        CloseableHttpResponse response = null;
        try {
            response = closeableHttpClient.execute(httpGet);
            HttpEntity entity = response.getEntity();
            String result = EntityUtils.toString(entity, StandardCharsets.UTF_8);
            System.out.println(result);
            EntityUtils.consume(entity);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (closeableHttpClient != null) {
                try {
                    closeableHttpClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

2.4 HttpClient设置连接超时和请求超时

    /**
     * httpclient设置连接超时和请求超时
     */
    @Test
    public void testSetTimeout() {
        CloseableHttpClient closeableHttpClient = HttpClients.createDefault();
        String url = "https://www.baidu.com";
        HttpGet httpGet = new HttpGet(url);
        // 对请求的配置,会覆盖全局配置
        RequestConfig requestConfig = RequestConfig.custom()
                // 设置连接超时时间,单位毫秒,指完成三次tcp握手时间上限
                .setConnectTimeout(5000)
                // 读取超时,指从请求的网址获得响应数据的时间间隔
                .setSocketTimeout(3000)
                // 指从连接池里面获取响应数据的时间间隔
                .setConnectionRequestTimeout(5000)
                .build();
        httpGet.setConfig(requestConfig);
        CloseableHttpResponse response = null;
        try {
            response = closeableHttpClient.execute(httpGet);
            HttpEntity entity = response.getEntity();
            String result = EntityUtils.toString(entity, StandardCharsets.UTF_8);
            System.out.println(result);
            EntityUtils.consume(entity);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (closeableHttpClient != null) {
                try {
                    closeableHttpClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

2.5 HttpClient发送表单格式的post请求

/**
     * httpclient发送表单类型的post请求
     */
    @Test
    public void testPostForm() {
        CloseableHttpClient closeableHttpClient = HttpClients.createDefault();
        String url = "https://www.baidu.com";
        // 创建HttpPost对象
        HttpPost httpPost = new HttpPost(url);
        // 给post对象设置参数
        // NameValuePair:指input标签的name属性值和input标签里输入的值,构成了NameValuePair对象
        List<NameValuePair> list = new ArrayList<>();
        list.add(new BasicNameValuePair("username", "tom"));
        list.add(new BasicNameValuePair("password", "123"));
        // 把参数集合设置到formEntity
        UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(list, Consts.UTF_8);
        httpPost.setEntity(formEntity);
        CloseableHttpResponse response = null;
        try {
            response = closeableHttpClient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            String result = EntityUtils.toString(entity, StandardCharsets.UTF_8);
            System.out.println(result);
            EntityUtils.consume(entity);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (closeableHttpClient != null) {
                try {
                    closeableHttpClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

2.6 HttpClient发送json类型的post请求

    /**
     * httpclient发送json类型的post请求
     */
    @Test
    public void testPostJson() {
        CloseableHttpClient closeableHttpClient = null;
        CloseableHttpResponse response = null;
        try {
            closeableHttpClient = HttpClients.createDefault();
            String url = "http://192.168.127.206:10006/cmk/v1/enableCmkStatus";
            // 创建HttpPost对象
            HttpPost httpPost = new HttpPost(url);
            // json字符串
            JSONObject json = new JSONObject();
            json.put("transId", "796e732d0ed24c45b3da7494c0101d02");
            json.put("appId", "APP_95608130D8554A0F89613415B3DC8758");
            json.put("deviceId", "DEV_45C5BEBABEAD406D8BB3F7C09FB11550");
            json.put("keyId", "6d190ab3264f46bc9a511a1bfa1293b6");
            json.put("signAlgo", "HmacSM3");
            json.put("signature", "EYJJF/PpLzSqXgh5hYQJCISoAnzS9XBdWkC6n01LZe4=");
            json.put("version", "1");
            StringEntity jsonEntity = new StringEntity(json.toString());
            // 给Entity设置Content-Type
            jsonEntity.setContentType(new BasicHeader("Content-Type", "application/json; charset=utf-8"));
            httpPost.setEntity(jsonEntity);
            response = closeableHttpClient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            String result = EntityUtils.toString(entity, StandardCharsets.UTF_8);
            System.out.println(result);
            EntityUtils.consume(entity);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (closeableHttpClient != null) {
                try {
                    closeableHttpClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

三、SSL

3.1 为何要绕过ssl安全认证

  1. 在网络上有两种https,一种是安全的,一种是不安全的,例如https://www.baidu.com,这个地址虽说是https请求,但因为是安全的,所以不用绕过,可以直接httpclient访问。
  2. 还有一些网址是不安全的,我们访问的时候,会提示不安全的连接
  3. 对于不安全的https,可以通过两种方式解决,一是通过认证需要的密钥配置httpclient,二是配置httpclient绕过https安全认证

3.2 Httpclient绕过https安全认证

package cn.cy.study.httpclient;

import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeader;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import org.junit.Test;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

public class SSL {

    /**
     * 创建支持安全协议的连接工程
     *
     * @return
     * @throws Exception
     */
    private ConnectionSocketFactory trustHttpsCertificates() throws Exception {
        SSLContextBuilder sslContextBuilder = new SSLContextBuilder();
        // 是否信任url
        sslContextBuilder.loadTrustMaterial(null, (x509Certificates, s) -> true);
        SSLContext sslContext = sslContextBuilder.build();
        SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(
                sslContext,
                new String[]{"SSLv2Hello", "SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2"},
                null,
                NoopHostnameVerifier.INSTANCE);
        return sslConnectionSocketFactory;
    }

    @Test
    public void testSSL() throws Exception {
        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.INSTANCE)
                .register("https", trustHttpsCertificates())
                .build();
        // 创建一个ConnectionManager
        PoolingHttpClientConnectionManager pool = new PoolingHttpClientConnectionManager(registry);
        // 定制CloseableHttpClient对象
        HttpClientBuilder httpClientBuilder = HttpClients.custom().setConnectionManager(pool);
        // 配置httpclient之后,通过build()获取httoclient对象
        CloseableHttpClient closeableHttpClient = httpClientBuilder.build();
        String url = "https://192.168.136.19:10006/cmk/v1/enableCmkStatus";
        HttpPost httpPost = new HttpPost(url);
        CloseableHttpResponse response = null;
        try {
            response = closeableHttpClient.execute(httpPost);
            // json字符串
            JSONObject json = new JSONObject();
            json.put("transId", "796e732d0ed24c45b3da7494c0101d02");
            json.put("appId", "APP_95608130D8554A0F89613415B3DC8758");
            json.put("deviceId", "DEV_45C5BEBABEAD406D8BB3F7C09FB11550");
            json.put("keyId", "6d190ab3264f46bc9a511a1bfa1293b6");
            json.put("signAlgo", "HmacSM3");
            json.put("signature", "EYJJF/PpLzSqXgh5hYQJCISoAnzS9XBdWkC6n01LZe4=");
            json.put("version", "1");
            StringEntity jsonEntity = new StringEntity(json.toString());
            // 给Entity设置Content-Type
            jsonEntity.setContentType(new BasicHeader("Content-Type", "application/json; charset=utf-8"));
            httpPost.setEntity(jsonEntity);
            response = closeableHttpClient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            String result = EntityUtils.toString(entity, StandardCharsets.UTF_8);
            System.out.println(result);
            EntityUtils.consume(entity);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (closeableHttpClient != null) {
                try {
                    closeableHttpClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

 类似资料: