网站首页 > java教程 正文
记得之前在公众号提过曾经在 T 公司做 Java 爬虫,有读者对爬虫的实现很感兴趣。在 Java 应用中读取远程 URL 内容是一个比较常见的需求,可以使用 Apache 旗下的开源项目 Httpclient 来实现。
Httpclient 基于 Java 语言,实现了 HTTP 1.0 和 HTTP 1.1 协议。实现了 GET、POST、PUT、DELETE、HEAD、OPTIONS、TRACE 等全部方法。支持使用代理建立连接。支持设置最大连接数,同时支持设置每个主机的最大连接数,发现并关闭过期的连接。能够自动处理 cookie,支持用 KeepAlive 来保持持久连接。
使用 Httpclient 很简单,在如下的示例代码中,分为以下几个步骤:
- 创建 HttpClient 对象,这里使用了默认设置;
- 创建请求对象 httpGet,对应一次 get 请求;
- 调用 HttpClient.execute 执行一次请求,得到的返回是 response;
- 通过 response 可以获取返回的状态和HTML内容;
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet("http://www.baidu.com");
CloseableHttpResponse response = httpclient.execute(httpGet);
try {
System.out.println(response.getStatusLine());
HttpEntity entity = response.getEntity();
System.out.println(EntityUtils.toString(entity));
} finally {
response.close();
}
发送 get 请求,需要创建 HttpGet 请求。发送 post 请求,需要创建 HttpPost 请求。如果是带参数的请求,可以直接拼接在 URL 中,也可以使用 URIBuilder 创建对象然后通过 addParameter 或 setParameter 方法添加 。如果需要设置请求 header,可以调用 addHeader 或 setHeader 方法设置 header。
对于 post 请求,可以调用 setEntity 方法设置请求的数据。如 post.setEntity(new StringEntity(body, "utf-8"))。支持提交多种数据:
- StringEntity:纯文本内容,比如提交 json 数据;
- FileEntity:文件,比如文件上传;
- ByteArrayEntity:字节流数据,比如提交序列化数据;
- UrlEncodedFormEntity:表单数据,比如提交 form 表单;
- InputStreamEntity:输入流数据,比如文件上传;
- SerializableEntity:序列化数据,支持提交 Serializable 序列化对象;
- BasicHttpEntity:通用数据,使用者自行写入流和内容长度。
调用 HttpClient 的 execute 方法发送请求,返回的是一个 HttpResponse 对象。通过该对象可以获取返回的所有数据:
- getStatusLine:获取返回状态 StatusLine 对象,如 HTTP/1.1 200 OK;
- getEntity:获取返回的内容,如 HTML 数据;
- getHeaders / getAllHeaders:获取返回的 header 内容;
设置请求参数
HttpClient 支持设置 RequestConfig 来配置请求默认参数。一般使用 RequestConfig.Builder 来构建 RequestConfig。Builder 支持进行如下设置:
- setProxy:设置代理服务器,需要传入 HttpHost 对象;
- setLocalAddress:设置本地地址;
- setCookieSpec:设置 cookie 处理策略;
- setRedirectsEnabled:设置是否允许自动跳转,处理 302 等响应;
- setMaxRedirects:设置最大跳转数量,302 跳转次数;
- setAuthenticationEnabled:设置是否启用认证,如启用需要提供密码;
- setConnectionRequestTimeout:设置连接请求超时时间,指从连接池获取连接的timeout;
- setConnectTimeout:设置连接超时时间,指客户端和服务器建立连接的timeout;
- setSocketTimeout:设置 socket 时间,指客户端从服务器读取数据的timeout;
RequestConfig 构建后,需要调用 HttpClient setDefaultRequestConfig 方法设置到客户端中。
使用代理
通过 RequestConfig.setProxy 可以设置请求的代理,在爬虫等场景非常实用。代理的对象类型是 HttpHost,一般设置代理的 ip 和端口。如果代理有密码,可以使用 CredentialsProvider 配置用户名和密码自动完成认证。
CredentialsProvider credsProvider = new BasicCredentialsProvider();
//使用密码的代理端口
credsProvider.setCredentials(new AuthScope(null,port),
//用户名和密码
new UsernamePasswordCredentials(username,password)
);
httpClientBuilder.setDefaultCredentialsProvider(credsProvider);
支持 HTTPS 协议
请求 HTTPS 需要在 HttpClient 中设置 ssl 协议。主要分为以下几个步骤:
- 创建 SSL 协议上下文 SSLContext,通常使用 SSLContextBuilder 构建;
- 创建 SSLConnectionSocketFactory,是 TLS/SSL 连接的 socket 工厂;
- 向连接工厂中注册 https 协议使用 SSLConnectionSocketFactory 处理;
- 创建连接池管理器 PoolingHttpClientConnectionManager,并注册 HTTPS;
- 向 HttpClient 设置连接池管理器。
如果请求报错 HTTPS 证书问题,可以设置忽略证书。设置系统变量 System.setProperty("jsse.enableSNIExtension", "false"); 即可。
// 需要通过以下代码声明对https连接支持
SSLContext sslcontext = SSLContexts.custom()
.loadTrustMaterial(null, new TrustSelfSignedStrategy())
.build();
// SSL 连接工厂
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, NoopHostnameVerifier.INSTANCE);
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder
.<ConnectionSocketFactory> create()
.register("http",PlainConnectionSocketFactory.getSocketFactory())
.register("https", sslsf).build();
// 初始化连接管理器
PoolingHttpClientConnectionManager poolConnManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
client = HttpClients.custom()
.setConnectionManager(poolConnManager)
.build();
推荐阅读
30 个 Spring 常用注解与差异总结
又到黄金季节,该跳槽吗?怎么跳?
分布式事务 6 个技术方案
15 个 MyBatis 技巧,赶紧收藏吧!
你的工资被倒挂了吗
猜你喜欢
- 2024-11-24 如何追踪Java对象的访问?
- 2024-11-24 java项目本地部署JeecgBoot低代码开发平台Vue3版系统源码
- 2024-11-24 windows本地通过Java API方式监控远程Yarn
- 2024-11-24 Java项目本地部署搭建实战SpringBoot高校宿舍管理系统源码
- 2024-11-24 Java项目本地搭建宝塔部署AI物品分类识别管理系统uniapp源码
- 2024-11-24 java本地线程ThreadLocal
- 2024-11-24 Java类加载过程
- 2024-11-24 Java项目本地部署宝塔搭建实战-医院HIS系统源码
- 2024-11-24 在Java程序中监听mysql的binlog
- 2024-11-24 快来试试这款一行代码实现多平台文件存储的工具!
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)