第一章 HttpClient的使用
1、http协议(这一块儿有时间的话会做记录)
2、常用的两种RPC方式
- 基于http协议:HttpClient和JDK自己的Http操作类
- 基于TCP或UDP协议:mina2和netty(这一部分以后有时间做记录)
3、HttpClient工具类的编写(只列出了两个最常用的方法get和post)
使用场合:我们可以在网页发送get或post请求去访问服务器server1,那我们在Java程序中想要模拟网页向服务器server1发送get和post请求的时候怎么办?--用HttpClient
版本:httpClient4.2.6(jar或者maven坐标自己加上)
maven坐标:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.2.6</version>
</dependency>
代码实现(两个类):
MyX509TrustManager(自定义的信任管理器)
package com.util; import java.security.cert.CertificateException;
import java.security.cert.X509Certificate; import javax.net.ssl.X509TrustManager; /**
* 自定义的信任管理器
*/
public class MyX509TrustManager implements X509TrustManager {
/**
* 检查客户端证书,若不信任,抛出异常
*/
public void checkClientTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {
}
/**
* 检查服务端证书,若不信任,抛出异常,反之,若不抛出异常,则表示信任(所以,空方法代表信任所有的服务端证书)
*/
public void checkServerTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {
}
/**
* 返回受信任的X509证书数组
*/
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
HttpClientUtil:
package com.util; import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set; import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager; import org.apache.commons.collections4.MapUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.HttpVersion;
import org.apache.http.NameValuePair;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.PoolingClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.params.HttpParams;
import org.apache.http.util.EntityUtils; /**
* 对HTTPClient的封装
*/
public class HttpClientUtil { private static final String ENCODING = "UTF-8"; private static HttpClient client = null;
private static SchemeRegistry schemeRegistry; //协议控制
private static PoolingClientConnectionManager ccm; //HttpClient连接池(多连接的线程安全的管理器) static {
try {
/*
* 与https请求相关的操作
*/
SSLContext sslContext = SSLContext.getInstance("SSL","SunJSSE");
sslContext.init(null, new TrustManager[]{new MyX509TrustManager()}, new SecureRandom());
SSLSocketFactory socketFactory = new SSLSocketFactory(sslContext);
/*
* 定义访问协议
*/
schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));//http
schemeRegistry.register(new Scheme("https", 443, socketFactory));//https
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
} Properties props = FileUtil.loadProps("http.properties");//加载属性文件 // 连接池管理
ccm = new PoolingClientConnectionManager(schemeRegistry);
ccm.setDefaultMaxPerRoute(FileUtil.getInt(props, "httpclient.max.conn.per.route", 20));//每个路由的最大连接数
ccm.setMaxTotal(FileUtil.getInt(props, "httpclient.max.conn.total", 400));//最大总连接数 HttpParams httpParams = new BasicHttpParams();
httpParams.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, FileUtil.getInt(props, "httpclient.max.conn.timeout", 1000));//连接超时时间(ms)
httpParams.setParameter(CoreConnectionPNames.SO_TIMEOUT, FileUtil.getInt(props, "httpclient.max.socket.timeout", 2000));//操作超时时间(ms)
httpParams.setParameter(CoreProtocolPNames.PROTOCOL_VERSION,HttpVersion.HTTP_1_1);//设置http1.1或http1.0 client = new DefaultHttpClient(ccm, httpParams);//一个客户端就有一个连接池
} /**
* get请求
* @param url 请求URL
* @param paramMap 请求参数
* @param headerMap 请求头信息
*/
public static String get(String url,
Map<String, String> paramMap,
Map<String, String> headerMap) throws ClientProtocolException,
IOException {
/*
* 拼接URL与参数
*/
if (MapUtils.isNotEmpty(paramMap)) {
List<NameValuePair> params = new ArrayList<NameValuePair>();
for (String key : paramMap.keySet()) {
params.add(new BasicNameValuePair(key, paramMap.get(key)));
}
String queryString = URLEncodedUtils.format(params,ENCODING);
if (url.indexOf("?") > -1) {//存在?,表示这时的URL已经带参数了
url += "&" + queryString;
} else {
url += "?" + queryString;
}
} HttpGet httpGet = new HttpGet(url); /*
* 设置头信息
*/
if (MapUtils.isNotEmpty(headerMap)) {
Set<String> keySet = headerMap.keySet();
for (String key : keySet) {
httpGet.addHeader(key, headerMap.get(key));
}
} String result = ""; HttpResponse response = client.execute(httpGet); //发出get请求
StatusLine status = response.getStatusLine(); //获取返回的状态码
HttpEntity entity = response.getEntity(); //获取返回的响应内容
if (status.getStatusCode() == HttpStatus.SC_OK) { //
result = EntityUtils.toString(entity, ENCODING);
} httpGet.abort();//中止请求,连接被释放回连接池
return result;
} /**
* post请求
* @param url //请求URL
* @param paramMap //请求参数
* @param headerMap //请求头信息
*/
public static String post(String url,
Map<String, String> paramMap,
Map<String, String> headerMap) throws ClientProtocolException,
IOException {
HttpPost httpPost = new HttpPost(url);
/*
* 处理参数
*/
List<NameValuePair> params = new ArrayList<NameValuePair>();
if (MapUtils.isNotEmpty(paramMap)) {
Set<String> keySet = paramMap.keySet();
for (String key : keySet) {
params.add(new BasicNameValuePair(key, paramMap.get(key)));
}
} /*
* 设置头信息
*/
if (MapUtils.isNotEmpty(headerMap)) {
Set<String> keySet = headerMap.keySet();
for (String key : keySet) {
httpPost.addHeader(key, headerMap.get(key));
}
} String result = ""; httpPost.setEntity(new UrlEncodedFormEntity(params, ENCODING));//设置参数
HttpResponse response = client.execute(httpPost); //发出post请求
StatusLine status = response.getStatusLine(); //获取返回的状态码
HttpEntity entity = response.getEntity(); //获取响应内容
if (status.getStatusCode() == HttpStatus.SC_OK) {
result = EntityUtils.toString(entity, ENCODING);
} httpPost.abort();//中止请求,连接被释放回连接池
return result;
} /**
* 测试
*/
public static void main(String[] args) {
try {
System.out.println(HttpClientUtil.get("https://www.baidu.com/", null, null));
//System.out.println(HttpClientUtil.post("http://www.cppblog.com/iuranus/archive/2010/07/04/119311.html", null, null));
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
在该代码中,还有两个部分:一个属性文件http.properties和一个文件操作类FileUtil。这两部分,请查看下边的这个链接:
http://www.cnblogs.com/java-zhao/p/5098813.html
注意:
- 我们发起的请求可以使http的,也可以是https(相当于http+SSL/TLS+数字证书的组合,是一种安全协议)的,对于https相关的请求而言,我们需要编写一些代码,来做特殊的处理。一般而言,处理https请求有两种方法:
1)将https服务器端的安全证书导入到客户端的TrustStore文件中去,具体的原理见"《微信公众平台应用开发(方法、技巧与案例)》第5章"或者去查看柳峰的博客
2)实现自定义的信任管理器(eg.MyX509TrustManager),需要实现X509TrustManager接口,并实现其中的三个方法。注意:这个类的注释一定要看
3)注意http大多数时候用的是8080端口而不是80
第一种方法需要手工导入证书,很费事;第二种方法十分灵活。
- 对于HttpClientUtil中,每一块做什么查看注释,这里:解释httpclient.max.conn.per.route(每个路由的最大连接数):这里路由的概念可以理解为"运行环境机器到目标机器"的一条线路。举例来说,我们使用HttpClient的实现来分别请求 www.baidu.com 的资源和 www.bing.com 的资源那么他就会产生两个route(路由),根据如上设置为20,就可以为上边两条route分别设置最大20个并发连接数。
- 假如只有HttpClientUtil使用MyX509TrustManager,我们也可以将MyX509TrustManager作为HttpClientUtil的一个内部类,代码如下:
package com.util; import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set; import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager; import org.apache.commons.collections4.MapUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.HttpVersion;
import org.apache.http.NameValuePair;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.PoolingClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.params.HttpParams;
import org.apache.http.util.EntityUtils; /**
* 对HTTPClient的封装
*/
public class HttpClientUtilWithMyX509TrustMananer { private static final String ENCODING = "UTF-8"; private static HttpClient client = null;
private static SchemeRegistry schemeRegistry; // 协议控制
private static PoolingClientConnectionManager ccm; // HttpClient连接池(多连接的线程安全的管理器) static {
try {
/*
* 与https请求相关的操作
*/
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(null,
new TrustManager[] { getMyX509TrustManager() },
new SecureRandom());
SSLSocketFactory socketFactory = new SSLSocketFactory(sslContext);
/*
* 定义访问协议
*/
schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));// http
schemeRegistry.register(new Scheme("https", 443, socketFactory));// https
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
} Properties props = FileUtil.loadProps("http.properties");// 加载属性文件 // 连接池管理
ccm = new PoolingClientConnectionManager(schemeRegistry);
ccm.setDefaultMaxPerRoute(FileUtil.getInt(props,"httpclient.max.conn.per.route", 20));// 每个路由的最大连接数
ccm.setMaxTotal(FileUtil.getInt(props, "httpclient.max.conn.total", 400));// 最大总连接数 HttpParams httpParams = new BasicHttpParams();
httpParams.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,FileUtil.getInt(props, "httpclient.max.conn.timeout", 1000));// 连接超时时间(ms)
httpParams.setParameter(CoreConnectionPNames.SO_TIMEOUT,FileUtil.getInt(props, "httpclient.max.socket.timeout", 2000));// 操作超时时间(ms)
httpParams.setParameter(CoreProtocolPNames.PROTOCOL_VERSION,HttpVersion.HTTP_1_1);// 设置http1.1或http1.0 client = new DefaultHttpClient(ccm, httpParams);// 一个客户端就有一个连接池
} /**
* get请求
* @param url 请求URL
* @param paramMap 请求参数
* @param headerMap 请求头信息
*/
public static String get(String url,
Map<String, String> paramMap,
Map<String, String> headerMap) throws ClientProtocolException,
IOException {
/*
* 拼接URL与参数
*/
if (MapUtils.isNotEmpty(paramMap)) {
List<NameValuePair> params = new ArrayList<NameValuePair>();
for (String key : paramMap.keySet()) {
params.add(new BasicNameValuePair(key, paramMap.get(key)));
}
String queryString = URLEncodedUtils.format(params, ENCODING);
if (url.indexOf("?") > -1) {// 存在?,表示这时的URL已经带参数了
url += "&" + queryString;
} else {
url += "?" + queryString;
}
} HttpGet httpGet = new HttpGet(url); /*
* 设置头信息
*/
if (MapUtils.isNotEmpty(headerMap)) {
Set<String> keySet = headerMap.keySet();
for (String key : keySet) {
httpGet.addHeader(key, headerMap.get(key));
}
} String result = ""; HttpResponse response = client.execute(httpGet); // 发出get请求
StatusLine status = response.getStatusLine(); // 获取返回的状态码
HttpEntity entity = response.getEntity(); // 获取返回的响应内容
if (status.getStatusCode() == HttpStatus.SC_OK) { //
result = EntityUtils.toString(entity, ENCODING);
} httpGet.abort();// 中止请求,连接被释放回连接池
return result;
} /**
* post请求
* @param url 请求URL
* @param paramMap 请求参数
* @param headerMap 请求头信息
*/
public static String post(String url,
Map<String, String> paramMap,
Map<String, String> headerMap) throws ClientProtocolException,
IOException {
HttpPost httpPost = new HttpPost(url);
/*
* 处理参数
*/
List<NameValuePair> params = new ArrayList<NameValuePair>();
if (MapUtils.isNotEmpty(paramMap)) {
Set<String> keySet = paramMap.keySet();
for (String key : keySet) {
params.add(new BasicNameValuePair(key, paramMap.get(key)));
}
} /*
* 设置头信息
*/
if (MapUtils.isNotEmpty(headerMap)) {
Set<String> keySet = headerMap.keySet();
for (String key : keySet) {
httpPost.addHeader(key, headerMap.get(key));
}
} String result = ""; httpPost.setEntity(new UrlEncodedFormEntity(params, ENCODING));// 设置参数
HttpResponse response = client.execute(httpPost); // 发出post请求
StatusLine status = response.getStatusLine(); // 获取返回的状态码
HttpEntity entity = response.getEntity(); // 获取响应内容
if (status.getStatusCode() == HttpStatus.SC_OK) {
result = EntityUtils.toString(entity, ENCODING);
} httpPost.abort();// 中止请求,连接被释放回连接池
return result;
} /**
* 构建自定义信任管理器内部类
*/
private static class MyX509TrustManager implements X509TrustManager {
/**
* 检查客户端证书,若不信任,抛出异常
*/
public void checkClientTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {
}
/**
* 检查服务端证书,若不信任,抛出异常,反之,若不抛出异常,则表示信任(所以,空方法代表信任所有的服务端证书)
*/
public void checkServerTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {
}
/**
* 返回受信任的X509证书数组
*/
public X509Certificate[] getAcceptedIssuers() {
return null;
}
} /**
* 为外部类获取内部类提供方法
*/
public static MyX509TrustManager getMyX509TrustManager() {
return new MyX509TrustManager();
} /**
* 测试
*/
public static void main(String[] args) {
try {
System.out.println(HttpClientUtilWithMyX509TrustMananer.get("https://www.baidu.com/", null, null));
// System.out.println(HttpClientUtil.post("http://www.cppblog.com/iuranus/archive/2010/07/04/119311.html", null, null));
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}注:在这里我定义了一个成员内部类,并提供了一个获取成员内部类的方法getMyX509TrustManager(),用于外部类来获取该内部类的实例。当然,如果对于内部类不熟的话,可以不使用内部类,直接使用上边的方式也好。
第一章 HttpClient的使用的更多相关文章
- 《进击吧!Blazor!》系列入门教程 第一章 8.部署
<进击吧!Blazor!>是本人与张善友老师合作的Blazor零基础入门教程视频,此教程能让一个从未接触过Blazor的程序员掌握开发Blazor应用的能力. 视频地址:https://s ...
- 《Django By Example》第一章 中文 翻译 (个人学习,渣翻)
书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:本人目前在杭州某家互联网公司工作, ...
- MyBatis3.2从入门到精通第一章
第一章一.引言mybatis是一个持久层框架,是apache下的顶级项目.mybatis托管到goolecode下,再后来托管到github下.(百度百科有解释)二.概述mybatis让程序将主要精力 ...
- Nova PhoneGap框架 第一章 前言
Nova PhoneGap Framework诞生于2012年11月,从第一个版本的发布到现在,这个框架经历了多个项目的考验.一直以来我们也持续更新这个框架,使其不断完善.到现在,这个框架已比较稳定了 ...
- 第一章 MYSQL的架构和历史
在读第一章的过程中,整理出来了一些重要的概念. 锁粒度 表锁(服务器实现,忽略存储引擎). 行锁(存储引擎实现,服务器没有实现). 事务的ACID概念 原子性(要么全部成功,要么全部回滚). 一致性 ...
- 第一章 Java多线程技能
1.初步了解"进程"."线程"."多线程" 说到多线程,大多都会联系到"进程"和"线程".那么这两者 ...
- 【读书笔记】《编程珠玑》第一章之位向量&位图
此书的叙述模式是借由一个具体问题来引出的一系列算法,数据结构等等方面的技巧性策略.共分三篇,基础,性能,应用.每篇涵盖数章,章内案例都非常切实棘手,解说也生动有趣. 自个呢也是头一次接触编程技巧类的书 ...
- 《JavaScript高级程序设计(第3版)》阅读总结记录第一章之JavaScript简介
前言: 为什么会想到把<JavaScript 高级程序设计(第 3 版)>总结记录呢,之前写过一篇博客,研究的轮播效果,后来又去看了<JavaScript 高级程序设计(第3版)&g ...
- 《Entity Framework 6 Recipes》翻译系列 (1) -----第一章 开始使用实体框架之历史和框架简述
微软的Entity Framework 受到越来越多人的关注和使用,Entity Framework7.0版本也即将发行.虽然已经开源,可遗憾的是,国内没有关于它的书籍,更不用说好书了,可能是因为EF ...
随机推荐
- 基于TensorFlow Serving的深度学习在线预估
一.前言 随着深度学习在图像.语言.广告点击率预估等各个领域不断发展,很多团队开始探索深度学习技术在业务层面的实践与应用.而在广告CTR预估方面,新模型也是层出不穷: Wide and Deep[1] ...
- STP协议树配置
STP协议树作用 为了提高网络可靠性,交换网络中通常会使用冗余链路. 然而,冗余链路会给交换网络带来环路风险 并导致广播风暴以及MAC地址表不稳定等问题进而会影响到用户的通信质量. 生成树协议STP( ...
- JavaQuery选择器
1.基本选择器 <!DOCTYPE html> <html> <head lang="en"> <meta charset=& ...
- ceph journal操作
查询ceph journal的地方 ceph --admin-daemon /var/run/ceph/ceph-osd.0.asok config show | grep osd_journal & ...
- bzoj5102 [POI2018]Prawnicy 线段树
$bzoj$跑的太慢了...... 我们考虑用线段树来解决这个问题 考虑扫描线 当扫到左端点$i$时,我们把线段$i$加入线段树 同时,对于每个左端点$i$,我们在线段树上二分出最远的$r$满足$r$ ...
- Loj #6560 小奇取石子
题面 分类讨论一波,n小的暴力2^n,n大的背包. #include<bits/stdc++.h> #define ll long long using namespace std; co ...
- hdu 2110 基础母函数
题意:退出本身并不麻烦,麻烦的是,退出的人需要取走相应比例(1/3)金额的资产.假设公司此时一共有n种价值的资产,每种价值的资产数量已知,请帮助心烦意乱的XHD夫妇计算一共有多少种分割资产的方法. ...
- bzoj2243 染色
Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段), 如 ...
- codevs 1052 地鼠游戏 优先队列
1052 地鼠游戏 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.codevs.cn/problem/1052/ Descriptio ...
- 读书笔记_Effective_C++_条款四十:明智而审慎地使用多重继承
多重继承是一种比较复杂的继承关系,它意味着如果用户想要使用这个类,那么就要对它的父类也了如指掌,所以在项目中会带来可读性的问题,一般我们都会尽量选择用单继承去替代它. 使用多重继承过程容易碰到的问题就 ...