HttpWebRequest:
命名空間: System.Net,這是.NET創建者最初開發用於使用HTTP請求的標准類。使用HttpWebRequest可以讓開發者控制請求/響應流程的各個方面,如 timeouts, cookies, headers, protocols。另一個好處是HttpWebRequest類不會阻塞UI線程。例如,當您從響應很慢的API服務器下載大文件時,您的應用程序的UI不會停止響應。HttpWebRequest通常和WebResponse一起使用,一個發送請求,一個獲取數據。HttpWebRquest更為底層一些,能夠對整個訪問過程有個直觀的認識,但同時也更加復雜一些。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
//POST方法
public
static
string
HttpPost(
string
Url,
string
postDataStr)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
request.Method =
"POST"
;
request.ContentType =
"application/x-www-form-urlencoded"
;
Encoding encoding = Encoding.UTF8;
byte
[] postData = encoding.GetBytes(postDataStr);
request.ContentLength = postData.Length;
Stream myRequestStream = request.GetRequestStream();
myRequestStream.Write(postData, 0, postData.Length);
myRequestStream.Close();
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream myResponseStream = response.GetResponseStream();
StreamReader myStreamReader =
new
StreamReader(myResponseStream, encoding);
string
retString = myStreamReader.ReadToEnd();
myStreamReader.Close();
myResponseStream.Close();
return
retString;
}
//GET方法
public
static
string
HttpGet(
string
Url,
string
postDataStr)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url + (postDataStr ==
""
?
""
:
"?"
) + postDataStr);
request.Method =
"GET"
;
request.ContentType =
"text/html;charset=UTF-8"
;
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream myResponseStream = response.GetResponseStream();
StreamReader myStreamReader =
new
StreamReader(myResponseStream, Encoding.GetEncoding(
"utf-8"
));
string
retString = myStreamReader.ReadToEnd();
myStreamReader.Close();
myResponseStream.Close();
return
retString;
}
|
WebClient:
命名空間System.Net,WebClient是一種更高級別的抽象,是HttpWebRequest為了簡化最常見任務而創建的,使用過程中你會發現他缺少基本的header,timeoust的設置,不過這些可以通過繼承httpwebrequest來實現。相對來說,WebClient比WebRequest更加簡單,它相當於封裝了request和response方法,不過需要說明的是,Webclient和WebRequest繼承的是不同類,兩者在繼承上沒有任何關系。使用WebClient可能比HttpWebRequest直接使用更慢(大約幾毫秒),但卻更為簡單,減少了很多細節,代碼量也比較少。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
public
class
WebClientHelper
{
public
static
string
DownloadString(
string
url)
{
WebClient wc =
new
WebClient();
//wc.BaseAddress = url; //設置根目錄
wc.Encoding = Encoding.UTF8;
//設置按照何種編碼訪問,如果不加此行,獲取到的字符串中文將是亂碼
string
str = wc.DownloadString(url);
return
str;
}
public
static
string
DownloadStreamString(
string
url)
{
WebClient wc =
new
WebClient();
wc.Headers.Add(
"User-Agent"
,
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36"
);
Stream objStream = wc.OpenRead(url);
StreamReader _read =
new
StreamReader(objStream, Encoding.UTF8);
//新建一個讀取流,用指定的編碼讀取,此處是utf-8
string
str = _read.ReadToEnd();
objStream.Close();
_read.Close();
return
str;
}
public
static
void
DownloadFile(
string
url,
string
filename)
{
WebClient wc =
new
WebClient();
wc.DownloadFile(url, filename);
//下載文件
}
public
static
void
DownloadData(
string
url,
string
filename)
{
WebClient wc =
new
WebClient();
byte
[] bytes = wc.DownloadData(url);
//下載到字節數組
FileStream fs =
new
FileStream(filename, FileMode.Create);
fs.Write(bytes, 0, bytes.Length);
fs.Flush();
fs.Close();
}
public
static
void
DownloadFileAsync(
string
url,
string
filename)
{
WebClient wc =
new
WebClient();
wc.DownloadFileCompleted += DownCompletedEventHandler;
wc.DownloadFileAsync(
new
Uri(url), filename);
Console.WriteLine(
"下載中。。。"
);
}
private
static
void
DownCompletedEventHandler(
object
sender, AsyncCompletedEventArgs e)
{
Console.WriteLine(sender.ToString());
//觸發事件的對象
Console.WriteLine(e.UserState);
Console.WriteLine(e.Cancelled);
Console.WriteLine(
"異步下載完成!"
);
}
public
static
void
DownloadFileAsync2(
string
url,
string
filename)
{
WebClient wc =
new
WebClient();
wc.DownloadFileCompleted += (sender, e) =>
{
Console.WriteLine(
"下載完成!"
);
Console.WriteLine(sender.ToString());
Console.WriteLine(e.UserState);
Console.WriteLine(e.Cancelled);
};
wc.DownloadFileAsync(
new
Uri(url), filename);
Console.WriteLine(
"下載中。。。"
);
}
}
|
HttpClient:
HttpClient是.NET4.5引入的一個HTTP客戶端庫,其命名空間為 System.Net.Http ,.NET 4.5之前我們可能使用WebClient和HttpWebRequest來達到相同目的。HttpClient利用了最新的面向任務模式,使得處理異步請求非常容易。它適合用於多次請求操作,一般設置好默認頭部后,可以進行重復多次的請求,基本上用一個實例可以提交任何的HTTP請求。HttpClient有預熱機制,第一次進行訪問時比較慢,所以不應該用到HttpClient就new一個出來,應該使用單例或其他方式獲取HttpClient的實例
單例模式:
單例模式(Singleton Pattern)這種類型的設計模式屬於創建型模式,它提供了一種創建對象的最佳方式。
這種模式涉及到一個單一的類,該類負責創建自己的對象,同時確保只有單個對象被創建。這個類提供了一種訪問其唯一的對象的方式,可以直接訪問,不需要實例化該類的對象。
單例創建步驟:1、定義靜態私有對象;2、定義私有構造函數;3、提供公共獲取對象方法;
單例模式一般分為兩種實現模式:懶漢模式、餓漢模式(以下為Java代碼實現)
懶漢模式: 默認不會實例化,什么時候用什么時候new
1
2
3
4
5
6
7
8
9
10
11
|
public
class
Singleton {
private
static
Singleton instance =
null
;
private
Singleton (){}
public
static
Singleton getInstance() {
if
(instance ==
null
) {
instance =
new
Singleton();
}
return
instance;
}
}
|
這種方式是最基本的實現方式,這種實現最大的問題就是不支持多線程。因為沒有加鎖 synchronized,所以嚴格意義上它並不算單例模式。
這種方式 lazy loading 很明顯,不要求線程安全,在多線程不能正常工作。
餓漢模式: 類初始化時,會立即加載該對象,線程天生安全,調用效率高
1
2
3
4
5
6
7
|
public
class
Singleton {
private
static
Singleton instance =
new
Singleton();
private
Singleton (){}
public
static
Singleton getInstance() {
return
instance;
}
}
|
雙檢鎖/雙重校驗鎖(DCL,即 double-checked locking):這種方式采用雙鎖機制,安全且在多線程情況下能保持高性能
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
public
class
Singleton {
private
volatile
static
Singleton singleton;
private
Singleton (){}
public
static
Singleton getSingleton() {
if
(singleton ==
null
) {
synchronized (Singleton.
class
) {
if
(singleton ==
null
) {
singleton =
new
Singleton();
}
}
}
return
singleton;
}
}
|
HttpClient:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
public
class
HttpClientHelper
{
private
static
readonly
object
LockObj =
new
object
();
private
static
HttpClient client =
null
;
public
HttpClientHelper() {
GetInstance();
}
public
static
HttpClient GetInstance()
{
if
(client ==
null
)
{
lock
(LockObj)
{
if
(client ==
null
)
{
client =
new
HttpClient();
}
}
}
return
client;
}
public
async Task<
string
> PostAsync(
string
url,
string
strJson)
//post異步請求方法
{
try
{
HttpContent content =
new
StringContent(strJson);
content.Headers.ContentType =
new
System.Net.Http.Headers.MediaTypeHeaderValue(
"application/json"
);
//由HttpClient發出異步Post請求
HttpResponseMessage res = await client.PostAsync(url, content);
if
(res.StatusCode == System.Net.HttpStatusCode.OK)
{
string
str = res.Content.ReadAsStringAsync().Result;
return
str;
}
else
return
null
;
}
catch
(Exception ex)
{
return
null
;
}
}
public
string
Post(
string
url,
string
strJson)
//post同步請求方法
{
try
{
HttpContent content =
new
StringContent(strJson);
content.Headers.ContentType =
new
System.Net.Http.Headers.MediaTypeHeaderValue(
"application/json"
);
//client.DefaultRequestHeaders.Connection.Add("keep-alive");
//由HttpClient發出Post請求
Task<HttpResponseMessage> res = client.PostAsync(url, content);
if
(res.Result.StatusCode == System.Net.HttpStatusCode.OK)
{
string
str = res.Result.Content.ReadAsStringAsync().Result;
return
str;
}
else
return
null
;
}
catch
(Exception ex)
{
return
null
;
}
}
public
string
Get(
string
url)
{
try
{
var responseString = client.GetStringAsync(url);
return
responseString.Result;
}
catch
(Exception ex)
{
return
null
;
}
}
}
|
HttpClient有預熱機制,第一次請求比較慢;可以通過初始化前發送一次head請求解決:
1
2
3
4
5
6
7
|
_httpClient =
new
HttpClient() { BaseAddress =
new
Uri(BASE_ADDRESS) };
//幫HttpClient熱身
_httpClient.SendAsync(
new
HttpRequestMessage {
Method =
new
HttpMethod(
"HEAD"
),
RequestUri =
new
Uri(BASE_ADDRESS +
"/"
) })
.Result.EnsureSuccessStatusCode();
|
三者區別列表: