第一章 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 ...
随机推荐
- Java_集合与泛型
Collection 集合,集合是java中提供的一种容器,可以用来存储多个数据.在前面的学习中,我们知道数据多了,可以使用数组存放或者使用ArrayList集合进行存放数据.那么,集合和数组既然都是 ...
- RMQ_第一弹_Sparse Table
title: RMQ_第一弹_Sparse Table date: 2018-09-21 21:33:45 tags: acm RMQ ST dp 数据结构 算法 categories: ACM 概述 ...
- Java反射机制demo(六)—获得并操作一个类的属性
Java反射机制demo(六)—获得并操作一个类的属性 获得并操作一个类的属性?! 不可思议啊,一个类的属性一般都是私有成员变量啊,private修饰符啊! 但是毫无疑问,这些东西在Java的反射机制 ...
- Pearls in a Row CodeForces 620C 水题
题目:http://codeforces.com/problemset/problem/620/C 文章末有一些测试数据仅供参考 题目大意 给你一个数字串,然后将分成几个部分,要求每个部分中必须有一对 ...
- 机器学习之路:tensorflow 深度学习中 分类问题的损失函数 交叉熵
经典的损失函数----交叉熵 1 交叉熵: 分类问题中使用比较广泛的一种损失函数, 它刻画两个概率分布之间的距离 给定两个概率分布p和q, 交叉熵为: H(p, q) = -∑ p(x) log q( ...
- BZOJ 4520 [Cqoi2016]K远点对(KD树)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4520 [题目大意] 求K远点对距离 [题解] 修改估价函数为欧式上界估价,对每个点进行 ...
- 鸟哥的私房菜:Linux文件与目录管理
1. 目录与路径 1.1 相对路径与绝对路径 绝对路径:路径的写法『一定由根目录 / 写起』,如:/usr/share/doc 这个目录. 相对路径:路径的写法『不是由 / ...
- hdu 3864 素数分解
题意:求n是否只有4个因子,如果是就输出除1外的所有因子. 模板题,就不排版了 #include<cstdio> #include<iostream> #include< ...
- python开发_tkinter_修改tkinter窗口的红色图标'Tk'
学过java的swing可能知道,在创建一个窗口的时候,窗口的左上角是一个咖啡图标 如下图所示: 在python中,tkinter模块生成的窗口左上角是一个:Tk字样的图标(Tk为tkinter的缩写 ...
- 离线下载Xcode的文档
https://developer.apple.com/library/downloads/docset-index.dvtdownloadableindex 找到里面的文档下载地址 例如iOS 8. ...