HttpClient 官网
这里我们使用的是 HttpClient 4.5
引入相关依赖
<!-- httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
/**
* 使用 jdk 原始 api 请求网页
*/
@Test
void test() throws Exception {
// 1. 输入需要访问的网址
String strUrl = "https://www.baidu.com";
// 2. 转换成 Url
URL url = new URL(strUrl);
// 3. 打开连接
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try (
// 4. 获取 httpUrlConnection 的输入流
InputStream inputStream = urlConnection.getInputStream();
// 转换为字符串
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8); // 指定编码方式为 utf8
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
) {
// 读取字符串中的内容
String line;
while((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
}
}
运行结果
运行查看效果
/**
* 使用 httpclient 发送 get 请求
*/
@Test
void testGet1() {
// 1. 创建一个可关闭的 httpclient 客户端.
// 相当于打开的一个浏览器, 用于发送请求
CloseableHttpClient httpClient = HttpClients.createDefault();
// 要访问的地址
String strUrl = "https://www.baidu.com";
// 2. 构造 get 请求
HttpGet httpGet = new HttpGet(strUrl);
// 3. 构造响应对象
CloseableHttpResponse response = null;
try {
// 浏览器发送 get 请求
response = httpClient.execute(httpGet);
// 获取响应结果
HttpEntity entity = response.getEntity();
// HttpEntity 的工具类
// 输出响应结果
String ret = EntityUtils.toString(entity, StandardCharsets.UTF_8);
System.out.println(ret);
// 确保 entity 被消费, 且对应的流被关闭
EntityUtils.consume(entity);
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭 httpclient
if(httpClient != null) {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// 关闭 response
if(response != null) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
当出现诸如这种系统检测亲不是真人行为时, 可以在请求中添加 User-Agent 解决这类问题
// 构造 get 请求
HttpGet httpGet = new HttpGet(strUrl);
// 添加 User-Agent
// 解决 httpclient 被检测不是真人行为问题
httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36");
当我们爬取某个网站的图片时, 可能会出现提示 不是从本网站请求的图片 → 爬取失败. 这种行为被称作防盗链
可以通过添加 Referer 的方式来解决上述问题
// 构造 get 请求
HttpGet httpGet = new HttpGet(strUrl);
// 添加 Referer
// 解决爬取图片失败的问题 -> 网址选择需要爬取对应图片的网址
httpGet.addHeader("Referer", "https://www.baidu.com/");
@Test
void testGet1() {
// 1. 创建一个可关闭的 httpclient 客户端.
// 相当于打开的一个浏览器, 用于发送请求
CloseableHttpClient httpClient = HttpClients.createDefault();
// 要访问的地址
String strUrl = "https://www.baidu.com";
// 2. 构造 get 请求
HttpGet httpGet = new HttpGet(strUrl);
// 添加 User-Agent
// 解决 httpclient 被检测不是真人行为问题
httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36");
// 防盗链
// 解决爬取图片失败的问题 -> 网址选择需要爬取对应图片的网址
httpGet.addHeader("Referer", "https://www.baidu.com/");
// 3. 构造响应对象
CloseableHttpResponse response = null;
try {
// 浏览器发送 get 请求
response = httpClient.execute(httpGet);
// 获取响应结果
HttpEntity entity = response.getEntity();
// HttpEntity 的工具类
// 输出响应结果
String ret = EntityUtils.toString(entity, StandardCharsets.UTF_8);
System.out.println(ret);
// 确保 entity 被消费, 且对应的流被关闭
EntityUtils.consume(entity);
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭 httpclient
if(httpClient != null) {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// 关闭 response
if(response != null) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
url 中含有参数时, 使用 httpclient 发送请求需要进行 encode 操作 → 避免参数中出现特殊字符从而解码失败
@Test
void testGet1() throws UnsupportedEncodingException {
// 1. 创建一个可关闭的 httpclient 客户端.
// 相当于打开的一个浏览器, 用于发送请求
CloseableHttpClient httpClient = HttpClients.createDefault();
String password = "bbb| dsa+321";
// URLEncode, 避免参数中出现特殊字符从而解码失败
// 如果是浏览器, 浏览器会自动进行 URLEncode 操作
// 对于 httpclient 则需要手动执行 URLEncode
password = URLEncoder.encode(password, StandardCharsets.UTF_8.name());
String strUrl = "http://localhost:8811/httpclient-demo/test1?username=aaa&password=" + password;
// 2. 构造 get 请求
HttpGet httpGet = new HttpGet(strUrl);
// 3. 构造响应对象
CloseableHttpResponse response = null;
try {
// 浏览器发送 get 请求
response = httpClient.execute(httpGet);
// 获取响应结果
HttpEntity entity = response.getEntity();
// 获取响应的类型
// System.out.println("ContentType: " + entity.getContentType());
// HttpEntity 的工具类
String ret = EntityUtils.toString(entity, StandardCharsets.UTF_8);
System.out.println(ret);
// 确保 entity 被消费, 且对应的流被关闭
EntityUtils.consume(entity);
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭 httpclient
if(httpClient != null) {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// 关闭 response
if(response != null) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
// 获取响应头
Header[] headers = response.getAllHeaders();
for (Header header : headers) {
System.out.println("响应头: " + header.getName() + " value: " + header.getValue());
}
// 获取响应结果
HttpEntity entity = response.getEntity();
// 获取响应的类型
System.out.println("ContentType: " + entity.getContentType());
@Test
void testGet1() {
// 1. 创建一个可关闭的 httpclient 客户端.
// 相当于打开的一个浏览器, 用于发送请求
CloseableHttpClient httpClient = HttpClients.createDefault();
// 要访问的地址
String strUrl = "https://www.baidu.com";
// 2. 构造 get 请求
HttpGet httpGet = new HttpGet(strUrl);
// 3. 构造响应对象
CloseableHttpResponse response = null;
try {
// 浏览器发送 get 请求
response = httpClient.execute(httpGet);
// 本次请求的状态
StatusLine statusLine = response.getStatusLine();
if(statusLine.getStatusCode() == HttpStatus.SC_OK) { // HttpStatus.SC_OK -> 200
// 响应成功
System.out.println("响应成功 | StatusCode: " + statusLine.getStatusCode());
// 获取响应头
Header[] headers = response.getAllHeaders();
for (Header header : headers) {
System.out.println("响应头: " + header.getName() + " value: " + header.getValue());
}
// 获取响应结果
HttpEntity entity = response.getEntity();
// 获取响应的类型
System.out.println("ContentType: " + entity.getContentType());
// HttpEntity 的工具类
/*String ret = EntityUtils.toString(entity, StandardCharsets.UTF_8);
System.out.println(ret);*/
// 确保 entity 被消费, 且对应的流被关闭
EntityUtils.consume(entity);
} else {
System.out.println("响应失败 | StatusCode: " + statusLine.getStatusCode());
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭 httpclient
if(httpClient != null) {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// 关闭 response
if(response != null) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
图片链接
/**
* 保存网络图片到本地
*/
@Test
void testGet2() {
// 1. 创建一个可关闭的 httpclient 客户端.
// 相当于打开的一个浏览器, 用于发送请求
CloseableHttpClient httpClient = HttpClients.createDefault();
// 要访问的地址
String strUrl = "https://www.baidu.com/img/PCfb_5bf082d29588c07f842ccde3f97243ea.png";
// 2. 构造 get 请求
HttpGet httpGet = new HttpGet(strUrl);
// 3. 构造响应对象
CloseableHttpResponse response = null;
try {
// 浏览器发送 get 请求
response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
String contentType = entity.getContentType().getValue();
// 图片格式可能为 (1)image (2)png (3)jpg...
String suffix = contentType.substring(contentType.lastIndexOf('/') + 1); // 确定图片的格式
suffix = "." + suffix;
// 获取文件的字节流
// 由于获取的是图片, 二进制数据. 因此使用 toByteArray() 方法
byte[] byteArray = EntityUtils.toByteArray(entity);
// 将图片保存到 e 盘
String localPath = "e:\\aa" + suffix;
FileOutputStream fileOutputStream = new FileOutputStream(new File(localPath));
fileOutputStream.write(byteArray);
// 关闭输出流
fileOutputStream.close();
// 确保 entity 被消费, 且对应的流被关闭
EntityUtils.consume(entity);
} catch (IOException e) {
e.printStackTrace();
} finally {
if(httpClient != null) {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(response != null) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
在爬虫系统中, 高频率的访问一个网站时, 某些网站会禁止该 IP
针对这种情况我们可以通过设置访问代理来继续爬取内容
免费代理 IP 网站
// 构造 get 请求
HttpGet httpGet = new HttpGet(strUrl);
// 创建一个代理
String ip = "42.63.65.119";
int port = 80;
HttpHost proxy = new HttpHost(ip, port);
// 配置 get 请求
RequestConfig requestConfig = RequestConfig.custom().setProxy(proxy).build();
httpGet.setConfig(requestConfig);
/**
* 设置访问代理
*/
@Test
void testGet3() {
// 1. 创建一个可关闭的 httpclient 客户端.
// 相当于打开的一个浏览器, 用于发送请求
CloseableHttpClient httpClient = HttpClients.createDefault();
// 要访问的地址
String strUrl = "https://www.baidu.com";
// 2. 构造 get 请求
HttpGet httpGet = new HttpGet(strUrl);
// 创建一个代理
String ip = "42.63.65.119";
int port = 80;
HttpHost proxy = new HttpHost(ip, port);
// 配置 get 请求, 会覆盖全局的默认请求配置
RequestConfig requestConfig = RequestConfig.custom().setProxy(proxy).build();
httpGet.setConfig(requestConfig);
// 3. 构造响应对象
CloseableHttpResponse response = null;
try {
// 浏览器发送 get 请求
response = httpClient.execute(httpGet);
// 本次请求的状态
StatusLine statusLine = response.getStatusLine();
if(statusLine.getStatusCode() == HttpStatus.SC_OK) { // HttpStatus.SC_OK -> 200
// 响应成功
System.out.println("响应成功 | StatusCode: " + statusLine.getStatusCode());
// 获取响应结果
HttpEntity entity = response.getEntity();
System.out.println(EntityUtils.toString(entity, StandardCharsets.UTF_8));
// 确保 entity 被消费, 且对应的流被关闭
EntityUtils.consume(entity);
} else {
System.out.println("响应失败 | StatusCode: " + statusLine.getStatusCode());
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭 httpclient
if(httpClient != null) {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// 关闭 response
if(response != null) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Test
void testGet3() {
// 1. 创建一个可关闭的 httpclient 客户端.
// 相当于打开的一个浏览器, 用于发送请求
CloseableHttpClient httpClient = HttpClients.createDefault();
// 要访问的地址
// String strUrl = "https://www.baidu.com";
String strUrl = "https://www.github.com";
// String strUrl = "https://www.csdn.net/";
// 2. 构造 get 请求
HttpGet httpGet = new HttpGet(strUrl);
// 创建一个代理
String ip = "42.63.65.119";
int port = 80;
HttpHost proxy = new HttpHost(ip, port);
// 配置 get 请求, 会覆盖全局的默认请求配置
RequestConfig requestConfig = RequestConfig
.custom()
// .setProxy(proxy)
.setConnectTimeout(5000) // 设置连接超时时间最大为 5000ms -> 5s
.setSocketTimeout(1) // 设置读取超时时间最大为 1ms -> 0.001s
.build();
httpGet.setConfig(requestConfig);
// 3. 构造响应对象
CloseableHttpResponse response = null;
try {
// 浏览器发送 get 请求
response = httpClient.execute(httpGet);
// 本次请求的状态
StatusLine statusLine = response.getStatusLine();
if(statusLine.getStatusCode() == HttpStatus.SC_OK) { // HttpStatus.SC_OK -> 200
// 响应成功
System.out.println("响应成功 | StatusCode: " + statusLine.getStatusCode());
// 获取响应结果
HttpEntity entity = response.getEntity();
System.out.println(EntityUtils.toString(entity, StandardCharsets.UTF_8));
// 确保 entity 被消费, 且对应的流被关闭
EntityUtils.consume(entity);
} else {
System.out.println("响应失败 | StatusCode: " + statusLine.getStatusCode());
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭 httpclient
if(httpClient != null) {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// 关闭 response
if(response != null) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
mime type → Multipurpose Internet Mail Extensions → 多用途互联网邮件扩展类型
参考手册
/**
* 发送 application/x-www-form-urlencoded 类型的请求(表单类型的请求)
*/
@Test
void testPost1() {
// 创建一个可关闭的 httpclient 客户端
// 相当于打开一个浏览器, 用于发送请求
CloseableHttpClient httpClient = HttpClients.createDefault();
// 输入要访问的网址
String url = "xxx";
// 构造 post 请求
HttpPost post = new HttpPost(url);
// 设置请求头
post.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
// 为 post 对象设置参数
/**
* NameValuePair:
* name(userName) 和 input 标签中输入的值构成了一个 NameValuePair 对象
*/
List<NameValuePair> parameters = new ArrayList<>();
parameters.add(new BasicNameValuePair("email", "xxx"));
parameters.add(new BasicNameValuePair("password", "xxx"));
// 将参数集合设置到 formEntity
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(parameters, StandardCharsets.UTF_8);
post.setEntity(formEntity);
CloseableHttpResponse response = null;
try {
response = httpClient.execute(post);
HttpEntity entity = response.getEntity();
System.out.println("ContentType: " + entity.getContentType());
EntityUtils.toString(entity, StandardCharsets.UTF_8); // 以 utf8 的编码方式输出响应结果
// 关闭流
EntityUtils.consume(entity);
} catch (IOException e) {
e.printStackTrace();
} finally {
if(response != null) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(httpClient != null) {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
引入 Hutool → String 转 Json
<!-- Hutool -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.16</version>
</dependency>
/**
* 发送 application/json 类型的请求
*/
@Test
void testPost2() {
// 创建一个可关闭的 httpclient 客户端
// 相当于打开一个浏览器, 用于发送请求
CloseableHttpClient httpClient = HttpClients.createDefault();
// 输入要访问的网址
String url = "https://mail.163.com/?msg=authfail#return";
// 构造 post 请求
HttpPost post = new HttpPost(url);
Map<String, String> map = new HashMap<>();
map.put("name", "bibubibu");
map.put("password", "123456");
// 转 Json
String jsonStr = JSONUtil.toJsonStr(map);
StringEntity jsonEntity = new StringEntity(jsonStr, StandardCharsets.UTF_8);
// 设置编码方式
jsonEntity.setContentEncoding(Consts.UTF_8.name()); // utf-8
// 设置数据的传输格式
// jsonEntity.setContentType(new BasicHeader("Content-Type", "application/json; charset=utf-8"));
jsonEntity.setContentType("application/json; charset=utf-8"); // 效果同上
post.setEntity(jsonEntity);
CloseableHttpResponse response = null;
try {
response = httpClient.execute(post);
HttpEntity entity = response.getEntity();
System.out.println(EntityUtils.toString(entity, StandardCharsets.UTF_8)); // 以 utf8 的编码方式输出响应结果
// 关闭流
EntityUtils.consume(entity);
} catch (IOException e) {
e.printStackTrace();
} finally {
if(response != null) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(httpClient != null) {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
引入 mime → 上传文件
<!-- mime -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5.13</version>
</dependency>
/**
* 发送 multipart / form-data 类型上传文件的请求
*/
@Test
void testPost3() {
// 创建一个可关闭的 httpclient 客户端
// 相当于打开一个浏览器, 用于发送请求
CloseableHttpClient httpClient = HttpClients.createDefault();
// 输入要访问的网址
String url = "xxx";
// 构造 post 请求
HttpPost post = new HttpPost(url);
// 构造一个 ContentBody 实现类对象
FileBody contentBody = new FileBody(new File("e:\\t1.txt"));
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
// 对于普通的表单字段如果含有中文, 则不能通过 addTextBody, 否则会出现乱码
StringBody usernameText = new StringBody("bibubibu", ContentType.create("text/plain", StandardCharsets.UTF_8));
HttpEntity httpEntity = builder.setCharset(StandardCharsets.UTF_8) // 设置编码方式
.setContentType(ContentType.create("multipart/form-data", Consts.UTF_8)) // 设置数据的传输格式
.setMode(HttpMultipartMode.BROWSER_COMPATIBLE) // 设置浏览器模式, 确保 multipart 与浏览器的提交表单兼容
.addPart("filename", contentBody) // 上传文件
.addBinaryBody("filename", new File("e:\\1.png")) // 上传二进制文件
// .addTextBody("username", "bibubibu") // 上传对应的参数
.addPart("username", usernameText)
.addTextBody("password", "123456") // 上传对应的参数
.build();
post.setEntity(httpEntity);
CloseableHttpResponse response = null;
try {
response = httpClient.execute(post);
HttpEntity entity = response.getEntity();
System.out.println(EntityUtils.toString(entity, StandardCharsets.UTF_8)); // 以 utf8 的编码方式输出响应结果
// 关闭流
EntityUtils.consume(entity);
} catch (IOException e) {
e.printStackTrace();
} finally {
if(response != null) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(httpClient != null) {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
提出疑问 → 使用 httpclient 可以请求 https, 为何还要绕过 https 安全验证
这里指的 https 是针对不安全的 https 链接, 而上图中的 https://www.baidu.com 是安全的 https 链接
因为官方 https 证书是收费且存在有效期的, 如果证书是非官方认证或者证书已过期, 就是不安全的 https 链接
对于这种不安全的 https 链接, 解决方式如下
如果不配置 httpclient, 则会抛出 SSLHandshakeException
/**
* 绕过 https 安全认证
*/
@Test
void testHttps() throws Exception {
// 1. 创建一个可关闭的 httpclient 客户端.
// 相当于打开的一个浏览器, 用于发送请求
// 绕过 https 安全认证
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.INSTANCE)
.register("https", trustHttpsCertificates())
.build();
PoolingHttpClientConnectionManager pool = new PoolingHttpClientConnectionManager(registry);
HttpClientBuilder httpClientBuilder = HttpClients.custom().setConnectionManager(pool);
CloseableHttpClient httpClient = httpClientBuilder.build();
// 要访问的地址
String strUrl = "https://www.baidu.com";
// 2. 构造 get 请求
HttpGet httpGet = new HttpGet(strUrl);
// 3. 构造响应对象
CloseableHttpResponse response = null;
try {
// 浏览器发送 get 请求
response = httpClient.execute(httpGet);
// 获取响应结果
HttpEntity entity = response.getEntity();
// 获取响应的类型
// System.out.println("ContentType: " + entity.getContentType());
// HttpEntity 的工具类
String ret = EntityUtils.toString(entity, StandardCharsets.UTF_8);
System.out.println(ret);
// 确保 entity 被消费, 且对应的流被关闭
EntityUtils.consume(entity);
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭 httpclient
if(httpClient != null) {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// 关闭 response
if(response != null) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
// 创建支持安全协议的连接工厂
private ConnectionSocketFactory trustHttpsCertificates() throws Exception {
// 判断是否信任 url(true, 信任所有的 url)
SSLContext sslContext = SSLContextBuilder.create()
.loadTrustMaterial(null, (chain, authType) -> true) // 加载信任的证书
.build();
SSLConnectionSocketFactory socketFactory =
new SSLConnectionSocketFactory(sslContext
, new String[]{"SSLv2Hello", "SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2"}
, null
, NoopHostnameVerifier.INSTANCE);
return socketFactory;
}
使用 httpclient 连接池的优点
/**
* 封装 httpclient 工具类
*/
@Slf4j
public class HttpClientUtils {
private static final int CONNECT_TIMEOUT = 5 * 1000; // 5000ms -> 5s
private static final int SOCKET_TIMEOUT = 5 * 1000; // 5000ms -> 5s
private static final int CONNECT_REQUEST_TIMEOUT = 5 * 1000; // 5000ms -> 5s
/**
* 请求配置
* @return
*/
private static RequestConfig builderRequestConfig() {
return RequestConfig.custom()
.setConnectTimeout(CONNECT_TIMEOUT) // 设置连接到目标地址的超时时间
.setSocketTimeout(SOCKET_TIMEOUT) // 设置读取到数据的超时时间
.setConnectionRequestTimeout(CONNECT_REQUEST_TIMEOUT) // 设置获取到连接(httpclient)的超时时间
.build();
}
/**
* Get 请求
* @param url, 要访问的地址
* @param paramMap, 请求头
* @return
*/
public static String doGet(String url, Map<String, String> paramMap) {
// 1. 创建一个可关闭的 httpclient 客户端.
// 相当于打开的一个浏览器, 用于发送请求
CloseableHttpClient httpClient = HttpClients.createDefault();
String ret = "";
CloseableHttpResponse response = null;
// 2. 构造 get 请求
HttpGet get = new HttpGet(url);
// 设置请求头
if(paramMap != null) {
for(Map.Entry<String, String> entry : paramMap.entrySet()) {
// 添加请求头
get.addHeader(entry.getKey(), entry.getValue());
}
}
// 设置请求头的另一种方式
/*try {
URIBuilder uriBuilder = new URIBuilder(url);
if(paramMap != null) {
for(Map.Entry entry : paramMap.entrySet()) {
// 添加请求头
uriBuilder.addParameter(entry.getKey(), entry.getValue());
}
}
URI uri = uriBuilder.build();
HttpGet httpGet = new HttpGet(uri);
} catch (Exception e) {
e.printStackTrace();
}*/
try {
// 3. 发送 Get 请求
response = httpClient.execute(get);
// 判断响应状态
StatusLine statusLine = response.getStatusLine();
int statusCode = statusLine.getStatusCode();
if(HttpStatus.SC_OK == statusCode) { // statusCode == 200
log.info("响应成功, 状态码为: " + statusCode);
HttpEntity entity = response.getEntity();
ret = EntityUtils.toString(entity, StandardCharsets.UTF_8);
// 关闭 entity
EntityUtils.consume(entity);
} else {
log.info("响应失败, 状态码为: " + statusCode);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
extracted(response, httpClient);
}
return ret;
}
/**
* Post, 发送 application/x-www-form-urlencoded 类型的请求(表单类型的请求)
* @param url, 要访问的地址
* @param paramMap, 参数列表
* @return
*/
public static String doPost(String url, Map<String, String> paramMap) {
// 1. 创建一个可关闭的 httpclient 客户端.
// 相当于打开的一个浏览器, 用于发送请求
CloseableHttpClient httpClient = HttpClients.createDefault();
String ret = "";
CloseableHttpResponse response = null;
// 2. 构造 post 请求
HttpPost post = new HttpPost(url);
// 设置请求头 -> 确保请求头是 x-www-form-urlencoded 类型
// post.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
if(paramMap != null) {
List<NameValuePair> parameters = new ArrayList<>();
for (Map.Entry<String, String> entry : paramMap.entrySet()) {
parameters.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
// 模拟表单
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(parameters, StandardCharsets.UTF_8);
post.setEntity(formEntity);
}
// 配置 post 请求
post.setConfig(builderRequestConfig());
try {
// 3. 发送 post 请求
response = httpClient.execute(post);
// 判断响应状态
StatusLine statusLine = response.getStatusLine();
int statusCode = statusLine.getStatusCode();
if(HttpStatus.SC_OK == statusCode) { // statusCode == 200
log.info("响应成功, 状态码为: " + statusCode);
HttpEntity entity = response.getEntity();
ret = EntityUtils.toString(entity, StandardCharsets.UTF_8);
// 关闭 entity
EntityUtils.consume(entity);
} else {
log.info("响应失败, 状态码为: " + statusCode);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
extracted(response, httpClient);
}
return ret;
}
/**
* Post, 发送 application/json 类型的请求
* @param url, 要访问的地址
* @param paramMap, 参数列表
* @return
*/
public static String doPost4Json(String url, Map<String, String> paramMap) {
// 1. 创建一个可关闭的 httpclient 客户端.
// 相当于打开的一个浏览器, 用于发送请求
CloseableHttpClient httpClient = HttpClients.createDefault();
String ret = "";
CloseableHttpResponse response = null;
// 构造 post 请求
HttpPost post = new HttpPost(url);
// 设置请求头 -> 确保请求头是 json 类型
post.addHeader("Content-Type", "application/json; charset=utf-8");
StringEntity jsonEntity = new StringEntity(JSONUtil.toJsonStr(paramMap), StandardCharsets.UTF_8);
// 设置编码方式
jsonEntity.setContentEncoding(Consts.UTF_8.name());
// 设置请求头
// jsonEntity.setContentType("application/json; charset=utf-8"); // 效果等同于 post.addHeader("Content-Type", "application/json; charset=utf-8");
post.setEntity(jsonEntity);
// 配置 post 请求
post.setConfig(builderRequestConfig());
try {
// 3. 发送 post 请求
response = httpClient.execute(post);
// 判断响应状态
StatusLine statusLine = response.getStatusLine();
int statusCode = statusLine.getStatusCode();
if(HttpStatus.SC_OK == statusCode) { // statusCode == 200
log.info("响应成功, 状态码为: " + statusCode);
HttpEntity entity = response.getEntity();
ret = EntityUtils.toString(entity, StandardCharsets.UTF_8);
// 关闭 entity
EntityUtils.consume(entity);
} else {
log.info("响应失败, 状态码为: " + statusCode);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
extracted(response, httpClient);
}
return ret;
}
private static void extracted(CloseableHttpResponse response, CloseableHttpClient httpClient) {
if(response != null) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(httpClient != null) {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}