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的使用的更多相关文章

  1. 《进击吧!Blazor!》系列入门教程 第一章 8.部署

    <进击吧!Blazor!>是本人与张善友老师合作的Blazor零基础入门教程视频,此教程能让一个从未接触过Blazor的程序员掌握开发Blazor应用的能力. 视频地址:https://s ...

  2. 《Django By Example》第一章 中文 翻译 (个人学习,渣翻)

    书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:本人目前在杭州某家互联网公司工作, ...

  3. MyBatis3.2从入门到精通第一章

    第一章一.引言mybatis是一个持久层框架,是apache下的顶级项目.mybatis托管到goolecode下,再后来托管到github下.(百度百科有解释)二.概述mybatis让程序将主要精力 ...

  4. Nova PhoneGap框架 第一章 前言

    Nova PhoneGap Framework诞生于2012年11月,从第一个版本的发布到现在,这个框架经历了多个项目的考验.一直以来我们也持续更新这个框架,使其不断完善.到现在,这个框架已比较稳定了 ...

  5. 第一章 MYSQL的架构和历史

    在读第一章的过程中,整理出来了一些重要的概念. 锁粒度  表锁(服务器实现,忽略存储引擎). 行锁(存储引擎实现,服务器没有实现). 事务的ACID概念 原子性(要么全部成功,要么全部回滚). 一致性 ...

  6. 第一章 Java多线程技能

    1.初步了解"进程"."线程"."多线程" 说到多线程,大多都会联系到"进程"和"线程".那么这两者 ...

  7. 【读书笔记】《编程珠玑》第一章之位向量&位图

    此书的叙述模式是借由一个具体问题来引出的一系列算法,数据结构等等方面的技巧性策略.共分三篇,基础,性能,应用.每篇涵盖数章,章内案例都非常切实棘手,解说也生动有趣. 自个呢也是头一次接触编程技巧类的书 ...

  8. 《JavaScript高级程序设计(第3版)》阅读总结记录第一章之JavaScript简介

    前言: 为什么会想到把<JavaScript 高级程序设计(第 3 版)>总结记录呢,之前写过一篇博客,研究的轮播效果,后来又去看了<JavaScript 高级程序设计(第3版)&g ...

  9. 《Entity Framework 6 Recipes》翻译系列 (1) -----第一章 开始使用实体框架之历史和框架简述

    微软的Entity Framework 受到越来越多人的关注和使用,Entity Framework7.0版本也即将发行.虽然已经开源,可遗憾的是,国内没有关于它的书籍,更不用说好书了,可能是因为EF ...

随机推荐

  1. Python爬虫个人记录(三)爬取妹子图

    这此教程可能会比较简洁,具体细节可参考我的第一篇教程: Python爬虫个人记录(一)豆瓣250 Python爬虫个人记录(二)fishc爬虫 一.目的分析 获取煎蛋妹子图并下载 http://jan ...

  2. ubuntu16.04 安装symfony3.3.11 碰到的问题:extension dom is required | oops an error occurred 500

    问题1:Uncaught exception 'RuntimeException' with message 'Extension DOM is required' 解决:sudo apt-get i ...

  3. FILE operattion

    #include "mainwindow.h"#include "ui_mainwindow.h"#include <QMessageBox>#in ...

  4. ArrayList源码中EMPTY_ELEMENTDATA和DEFAULTCAPACITY_EMPTY_ELEMENTDATA的区别

    2018年7月22日09:54:17 JDK 1.8.0_162 ArrayList源码中EMPTY_ELEMENTDATA和DEFAULTCAPACITY_EMPTY_ELEMENTDATA的区别 ...

  5. CSUOJ 1901 赏赐 OR 灾难 单调栈

    Description 大G南征北战终于打下了大片土地成立了G国,大G在开国大典上传召帮助自己南征北战的三大开国元勋小A,小B,小C进殿,并要赏赐三人大量宝物以显示天恩浩荡.大G在征服其他国家的时候抢 ...

  6. eclipse 修改js文件无法编译到项目中

    1.场景重现 在今天修改js文件完善功能时,发现在eclipse中修改了文件后,刷新页面功能无法同步: 2.分析原因 查看编译路径,文件没有修改: 2.1 可能是缓存问题: 2.2 项目未编译: 3. ...

  7. linux驱动之一语点破天机

    <const 关键字> 在嵌入式系开发中,const关键字就是“只读”的意思   <为什么要ARM需要进行C语言环境的初始化> 在汇编情况下,指令的跳转,保护现场需要保存的数据 ...

  8. Windows下修改Git bash的HOME路径

    Windows中使用http://git-scm.com/安装Git bash工具,默认的HOME和~路径一般都是C:\Users\用户名,每次得用命令切换到常用的Repository下,此操作重复而 ...

  9. eclipse转idea, 快捷键设置

    设置快捷键的途径: 打开idea的配置,找到Keymap,设置为eclipse 另外还要手动设置某些快捷键 上下移动 点击类打开 代码提示 查询 重命名 快速实现接口 回到上一次光标处

  10. Mysql的学习随笔day2

    关于输入中文的问题,各种更改完utf8后仍然乱码. 最后找到一种可行的方法:在insert之前,输入 set names 'gbk' 约束保证数据的完整性和一致性.约束分为表级约束和列级约束,前者可以 ...