第一章 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 ...
随机推荐
- Scala入门4(_的用法)
从网上找了一篇博客,详细讲解了Scala下划线的用法,这里做保留 博客链接
- 大数据技术之_16_Scala学习_04_函数式编程-基础+面向对象编程-基础
第五章 函数式编程-基础5.1 函数式编程内容说明5.1.1 函数式编程内容5.1.2 函数式编程授课顺序5.2 函数式编程介绍5.2.1 几个概念的说明5.2.2 方法.函数.函数式编程和面向对象编 ...
- OSI、TCP、IP、UDP 这些都是啥??
一个大大的问号首先抛出,计算机之间是如何进行通信的? 计算机网络是通过传输介质.通信设施和网络通信协议,把分散在不同地点的计算机设备互连起来,实现资源共享和数据传输的系统. 网络协议就是数据按照一定的 ...
- 手动制作用于启动BeagleBoneBlack(am335x)的SD
1.需求MLO.u-boot.img.uImage.Systemfile 获取MLO.u-boot.img下载U-boot源码,解压获得源码,进入源码目录 cd /home/zyr/Source_co ...
- 第4天:Django的cookie和session
Cookie Session Cookie 浏览器请求服务器是无状态的,它的每一次请求对于服务器来说都是新的,服务器默认不会保存用户的状态数据.但很多时候,服务器需要保存用户的一些状态数据,比如用户是 ...
- Linux驱动之PCI
<背景> PCI设备有许多地址配置的寄存器,初始化时这寄存器来配置设备的总线地址,配置好后CPU就可以访问该设备的各项资源了.(提炼:配置总线地址) <配置寄存器> ( ...
- SPOJ8791 DYNALCA LCT
考虑\(LCT\) 不难发现,我们不需要换根... 对于操作\(1\),\(splay(u)\)然后连虚边即可 对于操作\(3\),我们可以先\(access(u)\),然后再\(access(v)\ ...
- 解决CIFilter滤镜后图片大小和方向发生变化
调用contextWithOptions:和createCGImage: fromRect:方法创建CIContext.与以往不同的地方是CIImage没有frame与bounds属性:只有exten ...
- 记一次帮朋友解决apache站点403错误的过程
apache版本: [root@iZ25eby2utyZ web]# rpm -qa | grep httpd httpd-tools--.el6.centos..x86_64 httpd--.el6 ...
- Set常用子类特点
HashSet: 重写 hashCode和equals方法 特点:无序,唯一 底层结构是: ...