进行Web开发关键是要了解超文本传输协议(HTTP),该协议用来传输网页、图像以及因特网上在浏览器与服务器间传输的其他类型文件。只要你在浏览器上输入一个URL,最前面的http://就表示使用HTTP来访问指定位置的信息。(大部分浏览器还支持其他一些不同的协议,其中FTP就是一个典型例子。)
本文从HTTP协议的结构上初步探讨HTTP协议的工作原理和请求响应格式,并最后通过一个使用Java编写的小HTTP服务器验证了如何处理和响应HTTP请求
HTTP 由两部分组成:请求和响应。当你在Web浏览器中输入一个URL时,浏览器将根据你的要求创建并发送请求,该请求包含所输入的URL以及一些与浏览器本身相关的信息。当服务器收到这个请求时将返回一个响应,该响应包括与该请求相关的信息以及位于指定URL(如果有的话)的数据。直到浏览器解析该响应并显示出网页(或其他资源)为止。
HTTP请求
HTTP请求的格式如下所示:
<request-line>
<headers>
<blank line>
[<request-body>]
在HTTP 请求中,第一行必须是一个请求行(request line),用来说明请求类型、要访问的资源以及使用的HTTP版本。紧接着是一个首部(header)小节,用来说明服务器要使用的附加信息。在首部之后是一个空行,再此之后可以添加任意的其他数据[称之为主体(body)]。
在HTTP中,定义了大量的请求类型,不过Ajax开发人员关心的只有GET请求和POST 请求。只要在Web浏览器上输入一个URL,浏览器就将基于该URL向服务器发送一个GET请求,以告诉服务器获取并返回什么资源。对于 www.wrox.com的GET请求如下所示:
GET / HTTP/1.1
Host: www.wrox.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
Gecko/20050225 Firefox/1.0.1
Connection: Keep-Alive
请求行的第一部分说明了该请求是GET请求。该行的第二部分是一个斜杠(/),用来说明请求的是该域名的根目录。该行的最后一部分说明使用的是HTTP 1.1版本(另一个可选项是1.0)。那么请求发到哪里去呢?这就是第二行的内容。
第2 行是请求的第一个首部,HOST。首部HOST将指出请求的目的地。结合HOST和上一行中的斜杠(/),可以通知服务器请求的是 www.wrox.com/(HTTP 1.1才需要使用首部HOST,而原来的1.0版本则不需要使用)。第三行中包含的是首部User-Agent,服务器端和客户端脚本都能够访问它,它是浏览器类型检测逻辑的重要基础。该信息由你使用的浏览器来定义(在本例中是Firefox 1.0.1),并且在每个请求中将自动发送。最后一行是首部Connection,通常将浏览器操作设置为Keep-Alive(当然也可以设置为其他值,但这已经超出了本书讨论的范围)。注意,在最后一个首部之后有一个空行。即使不存在请求主体,这个空行也是必需的。
如果要获取一个诸如http://www.wrox.com/books的www.wrox.com域内的页面,那么该请求可能类似于:
GET /books/ HTTP/1.1
Host: www.wrox.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
Gecko/20050225 Firefox/1.0.1
Connection: Keep-Alive
注意只有第一行的内容发生了变化,它只包含URL中www.wrox.com后面的部分。
要发送GET请求的参数,则必须将这些额外的信息附在URL本身的后面。其格式类似于:
URL ? name1=value1&name2=value2&..&nameN=valueN
该信息称之为查询字符串(query string),它将会复制在HTTP请求的请求行中,如下所示:
GET /books/?name=Professional%20Ajax HTTP/1.1
Host: www.wrox.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
Gecko/20050225 Firefox/1.0.1
Connection: Keep-Alive
注意,为了将文本“Professional Ajax”作为URL的参数,需要编码处理其内容,将空格替换成%20,这称为URL编码(URL encoding),常用于HTTP的许多地方(JavaScript提供了内建的函数来处理URL编码和解码,这些将在本章中的后续部分中说明)。“名称—值”(name—value)对用 & 隔开。绝大部分的服务器端技术能够自动对请求主体进行解码,并为这些值的访问提供一些逻辑方式。当然,如何使用这些数据还是由服务器决定的。
浏览器发送的首部,通常比本文中所讨论的要多得多。为了简单起见,这里的例子尽可能简短。
另一方面,POST请求在请求主体中为服务器提供了一些附加的信息。通常,当填写一个在线表单并提交它时,这些填入的数据将以POST请求的方式发送给服务器。
以下就是一个典型的POST请求:
POST / HTTP/1.1
Host: www.wrox.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
Gecko/20050225 Firefox/1.0.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 40
Connection: Keep-Alive
name=Professional%20Ajax&publisher=Wiley
从上面可以发现, POST请求和GET请求之间有一些区别。首先,请求行开始处的GET改为了POST,以表示不同的请求类型。你会发现首部Host和User- Agent仍然存在,在后面有两个新行。其中首部Content-Type说明了请求主体的内容是如何编码的。浏览器始终以application/ x-www-form- urlencoded的格式编码来传送数据,这是针对简单URL编码的MIME类型。首部Content-Length说明了请求主体的字节数。在首部 Connection后是一个空行,再后面就是请求主体。与大多数浏览器的POST请求一样,这是以简单的“名称—值”对的形式给出的,其中name是 Professional Ajax,publisher是Wiley。你可以以同样的格式来组织URL的查询字符串参数。
正如前面所提到的,还有其他的HTTP请求类型,它们遵从的基本格式与GET请求和POST请求相同。下一步我们来看看服务器将对HTTP请求发送什么响应。
HTTP响应
如下所示,HTTP响应的格式与请求的格式十分类似:
<status-line>
<headers>
<blank line>
[<response-body>]
正如你所见,在响应中唯一真正的区别在于第一行中用状态信息代替了请求信息。状态行(status line)通过提供一个状态码来说明所请求的资源情况。以下就是一个HTTP响应的例子:
HTTP/1.1 200 OK
Date: Sat, 31 Dec 2005 23:59:59 GMT
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 122
<html>
<head>
<title>Wrox Homepage</title>
</head>
<body>
<!-- body goes here -->
</body>
</html>
在本例中,状态行给出的HTTP状态代码是200,以及消息OK。状态行始终包含的是状态码和相应的简短消息,以避免混乱。最常用的状态码有:
◆200 (OK): 找到了该资源,并且一切正常。
◆304 (NOT MODIFIED): 该资源在上次请求之后没有任何修改。这通常用于浏览器的缓存机制。
◆401 (UNAUTHORIZED): 客户端无权访问该资源。这通常会使得浏览器要求用户输入用户名和密码,以登录到服务器。
◆403 (FORBIDDEN): 客户端未能获得授权。这通常是在401之后输入了不正确的用户名或密码。
◆404 (NOT FOUND): 在指定的位置不存在所申请的资源。
在状态行之后是一些首部。通常,服务器会返回一个名为Data的首部,用来说明响应生成的日期和时间(服务器通常还会返回一些关于其自身的信息,尽管并非是必需的)。接下来的两个首部大家应该熟悉,就是与POST请求中一样的Content-Type和Content-Length。在本例中,首部 Content-Type指定了MIME类型HTML(text/html),其编码类型是ISO-8859-1(这是针对美国英语资源的编码标准)。响应主体所包含的就是所请求资源的HTML源文件(尽管还可能包含纯文本或其他资源类型的二进制数据)。浏览器将把这些数据显示给用户。
本文从HTTP协议的结构上初步探讨HTTP协议的工作原理和请求响应格式,并最后通过一个使用Java编写的小HTTP服务器验证了如何处理和响应HTTP请求
HTTP 由两部分组成:请求和响应。当你在Web浏览器中输入一个URL时,浏览器将根据你的要求创建并发送请求,该请求包含所输入的URL以及一些与浏览器本身相关的信息。当服务器收到这个请求时将返回一个响应,该响应包括与该请求相关的信息以及位于指定URL(如果有的话)的数据。直到浏览器解析该响应并显示出网页(或其他资源)为止。
HTTP请求
HTTP请求的格式如下所示:
<request-line>
<headers>
<blank line>
[<request-body>]
在HTTP 请求中,第一行必须是一个请求行(request line),用来说明请求类型、要访问的资源以及使用的HTTP版本。紧接着是一个首部(header)小节,用来说明服务器要使用的附加信息。在首部之后是一个空行,再此之后可以添加任意的其他数据[称之为主体(body)]。
在HTTP中,定义了大量的请求类型,不过Ajax开发人员关心的只有GET请求和POST 请求。只要在Web浏览器上输入一个URL,浏览器就将基于该URL向服务器发送一个GET请求,以告诉服务器获取并返回什么资源。对于 www.wrox.com的GET请求如下所示:
GET / HTTP/1.1
Host: www.wrox.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
Gecko/20050225 Firefox/1.0.1
Connection: Keep-Alive
请求行的第一部分说明了该请求是GET请求。该行的第二部分是一个斜杠(/),用来说明请求的是该域名的根目录。该行的最后一部分说明使用的是HTTP 1.1版本(另一个可选项是1.0)。那么请求发到哪里去呢?这就是第二行的内容。
第2 行是请求的第一个首部,HOST。首部HOST将指出请求的目的地。结合HOST和上一行中的斜杠(/),可以通知服务器请求的是 www.wrox.com/(HTTP 1.1才需要使用首部HOST,而原来的1.0版本则不需要使用)。第三行中包含的是首部User-Agent,服务器端和客户端脚本都能够访问它,它是浏览器类型检测逻辑的重要基础。该信息由你使用的浏览器来定义(在本例中是Firefox 1.0.1),并且在每个请求中将自动发送。最后一行是首部Connection,通常将浏览器操作设置为Keep-Alive(当然也可以设置为其他值,但这已经超出了本书讨论的范围)。注意,在最后一个首部之后有一个空行。即使不存在请求主体,这个空行也是必需的。
如果要获取一个诸如http://www.wrox.com/books的www.wrox.com域内的页面,那么该请求可能类似于:
GET /books/ HTTP/1.1
Host: www.wrox.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
Gecko/20050225 Firefox/1.0.1
Connection: Keep-Alive
注意只有第一行的内容发生了变化,它只包含URL中www.wrox.com后面的部分。
要发送GET请求的参数,则必须将这些额外的信息附在URL本身的后面。其格式类似于:
URL ? name1=value1&name2=value2&..&nameN=valueN
该信息称之为查询字符串(query string),它将会复制在HTTP请求的请求行中,如下所示:
GET /books/?name=Professional%20Ajax HTTP/1.1
Host: www.wrox.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
Gecko/20050225 Firefox/1.0.1
Connection: Keep-Alive
注意,为了将文本“Professional Ajax”作为URL的参数,需要编码处理其内容,将空格替换成%20,这称为URL编码(URL encoding),常用于HTTP的许多地方(JavaScript提供了内建的函数来处理URL编码和解码,这些将在本章中的后续部分中说明)。“名称—值”(name—value)对用 & 隔开。绝大部分的服务器端技术能够自动对请求主体进行解码,并为这些值的访问提供一些逻辑方式。当然,如何使用这些数据还是由服务器决定的。
浏览器发送的首部,通常比本文中所讨论的要多得多。为了简单起见,这里的例子尽可能简短。
另一方面,POST请求在请求主体中为服务器提供了一些附加的信息。通常,当填写一个在线表单并提交它时,这些填入的数据将以POST请求的方式发送给服务器。
以下就是一个典型的POST请求:
POST / HTTP/1.1
Host: www.wrox.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
Gecko/20050225 Firefox/1.0.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 40
Connection: Keep-Alive
name=Professional%20Ajax&publisher=Wiley
从上面可以发现, POST请求和GET请求之间有一些区别。首先,请求行开始处的GET改为了POST,以表示不同的请求类型。你会发现首部Host和User- Agent仍然存在,在后面有两个新行。其中首部Content-Type说明了请求主体的内容是如何编码的。浏览器始终以application/ x-www-form- urlencoded的格式编码来传送数据,这是针对简单URL编码的MIME类型。首部Content-Length说明了请求主体的字节数。在首部 Connection后是一个空行,再后面就是请求主体。与大多数浏览器的POST请求一样,这是以简单的“名称—值”对的形式给出的,其中name是 Professional Ajax,publisher是Wiley。你可以以同样的格式来组织URL的查询字符串参数。
正如前面所提到的,还有其他的HTTP请求类型,它们遵从的基本格式与GET请求和POST请求相同。下一步我们来看看服务器将对HTTP请求发送什么响应。
HTTP响应
如下所示,HTTP响应的格式与请求的格式十分类似:
<status-line>
<headers>
<blank line>
[<response-body>]
正如你所见,在响应中唯一真正的区别在于第一行中用状态信息代替了请求信息。状态行(status line)通过提供一个状态码来说明所请求的资源情况。以下就是一个HTTP响应的例子:
HTTP/1.1 200 OK
Date: Sat, 31 Dec 2005 23:59:59 GMT
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 122
<html>
<head>
<title>Wrox Homepage</title>
</head>
<body>
<!-- body goes here -->
</body>
</html>
在本例中,状态行给出的HTTP状态代码是200,以及消息OK。状态行始终包含的是状态码和相应的简短消息,以避免混乱。最常用的状态码有:
◆200 (OK): 找到了该资源,并且一切正常。
◆304 (NOT MODIFIED): 该资源在上次请求之后没有任何修改。这通常用于浏览器的缓存机制。
◆401 (UNAUTHORIZED): 客户端无权访问该资源。这通常会使得浏览器要求用户输入用户名和密码,以登录到服务器。
◆403 (FORBIDDEN): 客户端未能获得授权。这通常是在401之后输入了不正确的用户名或密码。
◆404 (NOT FOUND): 在指定的位置不存在所申请的资源。
在状态行之后是一些首部。通常,服务器会返回一个名为Data的首部,用来说明响应生成的日期和时间(服务器通常还会返回一些关于其自身的信息,尽管并非是必需的)。接下来的两个首部大家应该熟悉,就是与POST请求中一样的Content-Type和Content-Length。在本例中,首部 Content-Type指定了MIME类型HTML(text/html),其编码类型是ISO-8859-1(这是针对美国英语资源的编码标准)。响应主体所包含的就是所请求资源的HTML源文件(尽管还可能包含纯文本或其他资源类型的二进制数据)。浏览器将把这些数据显示给用户。
注意,这里并没有指明针对该响应的请求类型,不过这对于服务器并不重要。客户端知道每种类型的请求将返回什么类型的数据,并决定如何使用这些数据。
http://canrry.iteye.com/blog/1331292
以下是
java 常见几种发送http请求和响应的方式
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.Socket;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
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.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
/**
* @Description:发送http请求帮助类
* @author:liuyc
* @time:2016年5月17日 下午3:25:32
*/
public class HttpClientHelper {
/**
* @Description:使用HttpURLConnection发送post请求
* @author:liuyc
* @time:2016年5月17日 下午3:26:07
*/
public static String sendPost(String urlParam, Map
params, String charset) {
StringBuffer resultBuffer = null;
// 构建请求参数
StringBuffer sbParams = new StringBuffer();
if (params != null && params.size() > 0) {
for (Entry
e : params.entrySet()) {
sbParams.append(e.getKey());
sbParams.append("=");
sbParams.append(e.getValue());
sbParams.append("&");
}
}
HttpURLConnection con = null;
OutputStreamWriter osw = null;
BufferedReader br = null;
// 发送请求
try {
URL url = new URL(urlParam);
con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("POST");
con.setDoOutput(true);
con.setDoInput(true);
con.setUseCaches(false);
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
if (sbParams != null && sbParams.length() > 0) {
osw = new OutputStreamWriter(con.getOutputStream(), charset);
osw.write(sbParams.substring(0, sbParams.length() - 1));
osw.flush();
}
// 读取返回内容
resultBuffer = new StringBuffer();
int contentLength = Integer.parseInt(con.getHeaderField("Content-Length"));
if (contentLength > 0) {
br = new BufferedReader(new InputStreamReader(con.getInputStream(), charset));
String temp;
while ((temp = br.readLine()) != null) {
resultBuffer.append(temp);
}
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
if (osw != null) {
try {
osw.close();
} catch (IOException e) {
osw = null;
throw new RuntimeException(e);
} finally {
if (con != null) {
con.disconnect();
con = null;
}
}
}
if (br != null) {
try {
br.close();
} catch (IOException e) {
br = null;
throw new RuntimeException(e);
} finally {
if (con != null) {
con.disconnect();
con = null;
}
}
}
}
return resultBuffer.toString();
}
/**
* @Description:使用URLConnection发送post
* @author:liuyc
* @time:2016年5月17日 下午3:26:52
*/
public static String sendPost2(String urlParam, Map
params, String charset) {
StringBuffer resultBuffer = null;
// 构建请求参数
StringBuffer sbParams = new StringBuffer();
if (params != null && params.size() > 0) {
for (Entry
e : params.entrySet()) {
sbParams.append(e.getKey());
sbParams.append("=");
sbParams.append(e.getValue());
sbParams.append("&");
}
}
URLConnection con = null;
OutputStreamWriter osw = null;
BufferedReader br = null;
try {
URL realUrl = new URL(urlParam);
// 打开和URL之间的连接
con = realUrl.openConnection();
// 设置通用的请求属性
con.setRequestProperty("accept", "*/*");
con.setRequestProperty("connection", "Keep-Alive");
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
con.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 发送POST请求必须设置如下两行
con.setDoOutput(true);
con.setDoInput(true);
// 获取URLConnection对象对应的输出流
osw = new OutputStreamWriter(con.getOutputStream(), charset);
if (sbParams != null && sbParams.length() > 0) {
// 发送请求参数
osw.write(sbParams.substring(0, sbParams.length() - 1));
// flush输出流的缓冲
osw.flush();
}
// 定义BufferedReader输入流来读取URL的响应
resultBuffer = new StringBuffer();
int contentLength = Integer.parseInt(con.getHeaderField("Content-Length"));
if (contentLength > 0) {
br = new BufferedReader(new InputStreamReader(con.getInputStream(), charset));
String temp;
while ((temp = br.readLine()) != null) {
resultBuffer.append(temp);
}
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
if (osw != null) {
try {
osw.close();
} catch (IOException e) {
osw = null;
throw new RuntimeException(e);
}
}
if (br != null) {
try {
br.close();
} catch (IOException e) {
br = null;
throw new RuntimeException(e);
}
}
}
return resultBuffer.toString();
}
/**
* @Description:发送get请求保存下载文件
* @author:liuyc
* @time:2016年5月17日 下午3:27:29
*/
public static void sendGetAndSaveFile(String urlParam, Map
params, String fileSavePath) { // 构建请求参数 StringBuffer sbParams = new StringBuffer(); if (params != null && params.size() > 0) { for (Entry
entry : params.entrySet()) { sbParams.append(entry.getKey()); sbParams.append("="); sbParams.append(entry.getValue()); sbParams.append("&"); } } HttpURLConnection con = null; BufferedReader br = null; FileOutputStream os = null; try { URL url = null; if (sbParams != null && sbParams.length() > 0) { url = new URL(urlParam + "?" + sbParams.substring(0, sbParams.length() - 1)); } else { url = new URL(urlParam); } con = (HttpURLConnection) url.openConnection(); con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); con.connect(); InputStream is = con.getInputStream(); os = new FileOutputStream(fileSavePath); byte buf[] = new byte[1024]; int count = 0; while ((count = is.read(buf)) != -1) { os.write(buf, 0, count); } os.flush(); } catch (Exception e) { throw new RuntimeException(e); } finally { if (os != null) { try { os.close(); } catch (IOException e) { os = null; throw new RuntimeException(e); } finally { if (con != null) { con.disconnect(); con = null; } } } if (br != null) { try { br.close(); } catch (IOException e) { br = null; throw new RuntimeException(e); } finally { if (con != null) { con.disconnect(); con = null; } } } } } /** * @Description:使用HttpURLConnection发送get请求 * @author:liuyc * @time:2016年5月17日 下午3:27:29 */ public static String sendGet(String urlParam, Map
params, String charset) { StringBuffer resultBuffer = null; // 构建请求参数 StringBuffer sbParams = new StringBuffer(); if (params != null && params.size() > 0) { for (Entry
entry : params.entrySet()) { sbParams.append(entry.getKey()); sbParams.append("="); sbParams.append(entry.getValue()); sbParams.append("&"); } } HttpURLConnection con = null; BufferedReader br = null; try { URL url = null; if (sbParams != null && sbParams.length() > 0) { url = new URL(urlParam + "?" + sbParams.substring(0, sbParams.length() - 1)); } else { url = new URL(urlParam); } con = (HttpURLConnection) url.openConnection(); con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); con.connect(); resultBuffer = new StringBuffer(); br = new BufferedReader(new InputStreamReader(con.getInputStream(), charset)); String temp; while ((temp = br.readLine()) != null) { resultBuffer.append(temp); } } catch (Exception e) { throw new RuntimeException(e); } finally { if (br != null) { try { br.close(); } catch (IOException e) { br = null; throw new RuntimeException(e); } finally { if (con != null) { con.disconnect(); con = null; } } } } return resultBuffer.toString(); } /** * @Description:使用URLConnection发送get请求 * @author:liuyc * @time:2016年5月17日 下午3:27:58 */ public static String sendGet2(String urlParam, Map
params, String charset) { StringBuffer resultBuffer = null; // 构建请求参数 StringBuffer sbParams = new StringBuffer(); if (params != null && params.size() > 0) { for (Entry
entry : params.entrySet()) { sbParams.append(entry.getKey()); sbParams.append("="); sbParams.append(entry.getValue()); sbParams.append("&"); } } BufferedReader br = null; try { URL url = null; if (sbParams != null && sbParams.length() > 0) { url = new URL(urlParam + "?" + sbParams.substring(0, sbParams.length() - 1)); } else { url = new URL(urlParam); } URLConnection con = url.openConnection(); // 设置请求属性 con.setRequestProperty("accept", "*/*"); con.setRequestProperty("connection", "Keep-Alive"); con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); con.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); // 建立连接 con.connect(); resultBuffer = new StringBuffer(); br = new BufferedReader(new InputStreamReader(con.getInputStream(), charset)); String temp; while ((temp = br.readLine()) != null) { resultBuffer.append(temp); } } catch (Exception e) { throw new RuntimeException(e); } finally { if (br != null) { try { br.close(); } catch (IOException e) { br = null; throw new RuntimeException(e); } } } return resultBuffer.toString(); } /** * @Description:使用HttpClient发送post请求 * @author:liuyc * @time:2016年5月17日 下午3:28:23 */ public static String httpClientPost(String urlParam, Map
params, String charset) { StringBuffer resultBuffer = null; HttpClient client = new DefaultHttpClient(); HttpPost httpPost = new HttpPost(urlParam); // 构建请求参数 List
list = new ArrayList
(); Iterator
> iterator = params.entrySet().iterator(); while (iterator.hasNext()) { Entry
elem = iterator.next(); list.add(new BasicNameValuePair(elem.getKey(), String.valueOf(elem.getValue()))); } BufferedReader br = null; try { if (list.size() > 0) { UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, charset); httpPost.setEntity(entity); } HttpResponse response = client.execute(httpPost); // 读取服务器响应数据 resultBuffer = new StringBuffer(); br = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); String temp; while ((temp = br.readLine()) != null) { resultBuffer.append(temp); } } catch (Exception e) { throw new RuntimeException(e); } finally { if (br != null) { try { br.close(); } catch (IOException e) { br = null; throw new RuntimeException(e); } } } return resultBuffer.toString(); } /** * @Description:使用HttpClient发送get请求 * @author:liuyc * @time:2016年5月17日 下午3:28:56 */ public static String httpClientGet(String urlParam, Map
params, String charset) { StringBuffer resultBuffer = null; HttpClient client = new DefaultHttpClient(); BufferedReader br = null; // 构建请求参数 StringBuffer sbParams = new StringBuffer(); if (params != null && params.size() > 0) { for (Entry
entry : params.entrySet()) { sbParams.append(entry.getKey()); sbParams.append("="); try { sbParams.append(URLEncoder.encode(String.valueOf(entry.getValue()), charset)); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } sbParams.append("&"); } } if (sbParams != null && sbParams.length() > 0) { urlParam = urlParam + "?" + sbParams.substring(0, sbParams.length() - 1); } HttpGet httpGet = new HttpGet(urlParam); try { HttpResponse response = client.execute(httpGet); // 读取服务器响应数据 br = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); String temp; resultBuffer = new StringBuffer(); while ((temp = br.readLine()) != null) { resultBuffer.append(temp); } } catch (Exception e) { throw new RuntimeException(e); } finally { if (br != null) { try { br.close(); } catch (IOException e) { br = null; throw new RuntimeException(e); } } } return resultBuffer.toString(); } /** * @Description:使用socket发送post请求 * @author:liuyc * @time:2016年5月18日 上午9:26:22 */ public static String sendSocketPost(String urlParam, Map
params, String charset) { String result = ""; // 构建请求参数 StringBuffer sbParams = new StringBuffer(); if (params != null && params.size() > 0) { for (Entry
entry : params.entrySet()) { sbParams.append(entry.getKey()); sbParams.append("="); sbParams.append(entry.getValue()); sbParams.append("&"); } } Socket socket = null; OutputStreamWriter osw = null; InputStream is = null; try { URL url = new URL(urlParam); String host = url.getHost(); int port = url.getPort(); if (-1 == port) { port = 80; } String path = url.getPath(); socket = new Socket(host, port); StringBuffer sb = new StringBuffer(); sb.append("POST " + path + " HTTP/1.1\r\n"); sb.append("Host: " + host + "\r\n"); sb.append("Connection: Keep-Alive\r\n"); sb.append("Content-Type: application/x-www-form-urlencoded; charset=utf-8 \r\n"); sb.append("Content-Length: ").append(sb.toString().getBytes().length).append("\r\n"); // 这里一个回车换行,表示消息头写完,不然服务器会继续等待 sb.append("\r\n"); if (sbParams != null && sbParams.length() > 0) { sb.append(sbParams.substring(0, sbParams.length() - 1)); } osw = new OutputStreamWriter(socket.getOutputStream()); osw.write(sb.toString()); osw.flush(); is = socket.getInputStream(); String line = null; // 服务器响应体数据长度 int contentLength = 0; // 读取http响应头部信息 do { line = readLine(is, 0, charset); if (line.startsWith("Content-Length")) { // 拿到响应体内容长度 contentLength = Integer.parseInt(line.split(":")[1].trim()); } // 如果遇到了一个单独的回车换行,则表示请求头结束 } while (!line.equals("\r\n")); // 读取出响应体数据(就是你要的数据) result = readLine(is, contentLength, charset); } catch (Exception e) { throw new RuntimeException(e); } finally { if (osw != null) { try { osw.close(); } catch (IOException e) { osw = null; throw new RuntimeException(e); } finally { if (socket != null) { try { socket.close(); } catch (IOException e) { socket = null; throw new RuntimeException(e); } } } } if (is != null) { try { is.close(); } catch (IOException e) { is = null; throw new RuntimeException(e); } finally { if (socket != null) { try { socket.close(); } catch (IOException e) { socket = null; throw new RuntimeException(e); } } } } } return result; } /** * @Description:使用socket发送get请求 * @author:liuyc * @time:2016年5月18日 上午9:27:18 */ public static String sendSocketGet(String urlParam, Map
params, String charset) { String result = ""; // 构建请求参数 StringBuffer sbParams = new StringBuffer(); if (params != null && params.size() > 0) { for (Entry
entry : params.entrySet()) { sbParams.append(entry.getKey()); sbParams.append("="); sbParams.append(entry.getValue()); sbParams.append("&"); } } Socket socket = null; OutputStreamWriter osw = null; InputStream is = null; try { URL url = new URL(urlParam); String host = url.getHost(); int port = url.getPort(); if (-1 == port) { port = 80; } String path = url.getPath(); socket = new Socket(host, port); StringBuffer sb = new StringBuffer(); sb.append("GET " + path + " HTTP/1.1\r\n"); sb.append("Host: " + host + "\r\n"); sb.append("Connection: Keep-Alive\r\n"); sb.append("Content-Type: application/x-www-form-urlencoded; charset=utf-8 \r\n"); sb.append("Content-Length: ").append(sb.toString().getBytes().length).append("\r\n"); // 这里一个回车换行,表示消息头写完,不然服务器会继续等待 sb.append("\r\n"); if (sbParams != null && sbParams.length() > 0) { sb.append(sbParams.substring(0, sbParams.length() - 1)); } osw = new OutputStreamWriter(socket.getOutputStream()); osw.write(sb.toString()); osw.flush(); is = socket.getInputStream(); String line = null; // 服务器响应体数据长度 int contentLength = 0; // 读取http响应头部信息 do { line = readLine(is, 0, charset); if (line.startsWith("Content-Length")) { // 拿到响应体内容长度 contentLength = Integer.parseInt(line.split(":")[1].trim()); } // 如果遇到了一个单独的回车换行,则表示请求头结束 } while (!line.equals("\r\n")); // 读取出响应体数据(就是你要的数据) result = readLine(is, contentLength, charset); } catch (Exception e) { throw new RuntimeException(e); } finally { if (osw != null) { try { osw.close(); } catch (IOException e) { osw = null; throw new RuntimeException(e); } finally { if (socket != null) { try { socket.close(); } catch (IOException e) { socket = null; throw new RuntimeException(e); } } } } if (is != null) { try { is.close(); } catch (IOException e) { is = null; throw new RuntimeException(e); } finally { if (socket != null) { try { socket.close(); } catch (IOException e) { socket = null; throw new RuntimeException(e); } } } } } return result; } /** * @Description:读取一行数据,contentLe内容长度为0时,读取响应头信息,不为0时读正文 * @time:2016年5月17日 下午6:11:07 */ private static String readLine(InputStream is, int contentLength, String charset) throws IOException { List
lineByte = new ArrayList
(); byte tempByte; int cumsum = 0; if (contentLength != 0) { do { tempByte = (byte) is.read(); lineByte.add(Byte.valueOf(tempByte)); cumsum++; } while (cumsum < contentLength);// cumsum等于contentLength表示已读完 } else { do { tempByte = (byte) is.read(); lineByte.add(Byte.valueOf(tempByte)); } while (tempByte != 10);// 换行符的ascii码值为10 } byte[] resutlBytes = new byte[lineByte.size()]; for (int i = 0; i < lineByte.size(); i++) { resutlBytes[i] = (lineByte.get(i)).byteValue(); } return new String(resutlBytes, charset); } }
以上4种分别可发送get和post请求的方法,第1种:HttpURLConnection、第2种:URLConnection、第3种:HttpClient、第4种:Socket,朋友们要注意的是,使用第3种HttpClient时需要依赖于三个jar包,分别是:apache-httpcomponents-httpclient.jar、commons-logging-1.0.4.jar、httpcore-4.1.1.jar。