一、简单介绍下Http, tcp/ip和socket区别:
首先看一下无处不在的OSI七层传输模型:
第一层:应用层。定义了用于在网络中进行通信和传输数据的接口;(Http协议位于该层)
第二层:表示层。定义不同的系统中数据的传输格式,编码和解码规范等;
第三层:会话层。管理用户的会话,控制用户间逻辑连接的建立和中断;
第四层:传输层。管理着网络中的端到端的数据传输;(Tcp协议位于该层)
第五层:网络层。定义网络设备间如何传输数据;(IP位于该层)
第六层:链路层。将上面的网络层的数据包封装成数据帧,便于物理层传输;
第七层:物理层。这一层主要就是传输这些二进制数据。
看字面也能理解个差不多,知道个大概就行,可以自行百度。
Tcp/ip是传输层协议,而http则是建立在它之上的上层应用协议。Http聚焦在数据规范层面,tcp/ip则主要解决数据传输层面。建立在tcp/ip上的应用协议很多,我们经常接触的像rpc,ftp等。
Socket则是tcp/ip的一个编程实现,封装了传输层的众多细节,从而让协议层可以关注协议本身的处理而不用关注底层传输。在程序里http请求(连接)最终一定需要绑定到一个具体的socket连接进行上行和下行传输。
二、HttpClient特点:
- 纯Java语言实现的HTTP。
- 以可扩展的面向对象的结构实现了HTTP全部的方法(GET, POST, PUT, DELETE, HEAD, OPTIONS, and TRACE)。
- 支持加密的HTTPS协议(HTTP通过SSL协议)。
- 通过HTTP代理方式建立透明的连接。
- 利用CONNECT方法通过HTTP代理建立隧道的HTTPS连接。
- Basic, Digest, NTLMv1, NTLMv2, NTLM2 Session, SNPNEGO/Kerberos认证方案。
- 插件式的自定义认证方案。
- 可插拔的安全套接字工厂,使得接入第三方解决方案变得更容易
- 连接管理支持使用多线程的的应用。支持设置最大连接数,同时支持设置每个主机的最大连接数,发现并关闭过期的连接。
- 自动化处理Set-Cookie:来自服务器的头,并在适当的时候将它们发送回cookie。
- 可以自定义Cookie策略的插件化机制。
- Request的输出流可以避免流中内容体直接从socket缓冲到服务器。
- Response的输入流可以有效的从socket服务器直接读取相应内容。
- 在HTTP1.0和HTTP1.1中使用用KeepAlive来保持持久连接。
- 可以直接获取服务器发送的响应码和响应头部。
- 具备设置连接超时的能力。
- 支持HTTP/1.1 响应缓存。
- 源代码基于Apache License 可免费获取
三、一般使用步骤:
a)HttpGet请求响应:
1). 创建HttpClient对象,可以使用HttpClients.createDefault();
2). 如果是无参数的GET请求,则直接使用构造方法HttpGet(String url)创建HttpGet对象即可;
如果是带参数GET请求,则可以先使用URIBuilder(String url)创建对象,再调用addParameter(String param, String value),或setParameter(String param, String value)来设置请求参数,并调用build()方法构建一个URI对象。只有构造方法HttpGet(URI uri)来创建HttpGet对象。
3). 创建HttpResponse,调用HttpClient对象的execute(HttpUriRequest request)发送请求,该方法返回一个HttpResponse。调用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可获取服务器的响应头;调用HttpResponse的getEntity()方法可获取HttpEntity对象,该对象包装了服务器的响应内容。程序可通过该对象获取服务器的响应内容。通过调用getStatusLine().getStatusCode()可以获取响应状态码。
4). 释放连接。
b)HttpGet请求响应:
1). 创建HttpClient对象,可以使用HttpClients.createDefault();
2). 如果是无参数的POST请求,则直接使用构造方法HttpPost(String url)创建HttpPost对象即可;
如果是带参数POST请求,先构建HttpEntity对象并设置请求参数,然后调用setEntity(HttpEntity entity)创建HttpPost对象。
3). 创建HttpResponse,调用HttpClient对象的execute(HttpUriRequest request)发送请求,该方法返回一个HttpResponse。调用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可获取服务器的响应头;调用HttpResponse的getEntity()方法可获取HttpEntity对象,该对象包装了服务器的响应内容。程序可通过该对象获取服务器的响应内容。通过调用getStatusLine().getStatusCode()可以获取响应状态码。
4). 释放连接。
四、简单使用实例:
1.get请求
public void httpClientTestGet() {
CloseableHttpClient httpClient = HttpClients.createDefault();
try {
// 创建HttpGet
HttpGet httpGet = new HttpGet("http://www.baidu.com/");
// 执行get请求
CloseableHttpResponse response = null;
response = httpClient.execute(httpGet);
try {
// 获取详情实体
HttpEntity entity = response.getEntity();
//打印响应状态
System.out.println(response.getStatusLine());
if (entity != null) {
// 打印内容长度和内容
System.out.println("内容长度:" + entity.getContentLength());
System.out.println("响应内容:" + EntityUtils.toString(entity));
}
} finally {
response.close();
}
} catch (
IOException e) {
e.printStackTrace();
} finally {
// 关闭连接,释放资源
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.post请求
public void postFormTest() throws IOException {
System.out.println("======================================");
// 创建默认的httpClient实例
CloseableHttpClient client = HttpClients.createDefault();
// 创建post请求
HttpPost post = new HttpPost("http://localhost:8765/user//direct/airinfo/list");
// 设置请求参数
Map<String, String> map = new HashMap<String, String>();
map.put("userName", "张三");
map.put("realName", "zhangsan");
StringEntity stringEntity = new StringEntity(JSON.toJSONString(map), ContentType.APPLICATION_JSON);
stringEntity.setContentEncoding("utf-8");
post.setEntity(stringEntity);
post.releaseConnection();
// 执行请求
CloseableHttpResponse response = client.execute(post);
// 获取结果
if (response.getStatusLine().getStatusCode()!= HttpStatus.SC_OK){
System.out.println("请求出错:状态为:"+response.getStatusLine().getStatusCode());
}
System.out.println(EntityUtils.toString(response.getEntity()));
// 释放链接
response.close();
}
HttpClient使用很简单,下一篇我们来分析一下执行的原理和源码的解读