1. 程式人生 > >HTTP原理(一)

HTTP原理(一)

前言

單純的copy程式碼沒有用,本篇從http請求的基本原理開始為大家講解,後邊有例項,希望大家一步一步看完,這樣無論編寫什麼請求我們都可以得心應手。

HTTP的組成

http訊息由客戶端到服務端的請求以及服務端到客戶端的響應組成

HTTP請求報文的格式

請求頭與請求正文中間有一行空行,是告訴伺服器請求頭到此結束了接下來是請求正文

請求方法:get,post,head,delete等等,告訴伺服器你的具體操作是什麼

URL:可以從網際網路上得到資源的位置和訪問方法的一種簡潔標識。URL結構:協議://域名 or IP地址:埠號/目錄/檔名.檔名字尾?引數=值
協議版本:目前幾乎用的都是http1.1版本,增加了一個很重要的特性它支援長連線,其他具體細微差別不做講述。 請求頭:請求頭部為請求報文添加了一些附加資訊,由“名/值”對組成,每行一對,名和值之間使用冒號分隔。 常用的請求頭包括:
請求正文:新增請求實體即你具體要請求的內容用於POST請求,GET不用

HTTP響應報文格式


HTTP狀態碼


HTTP響應頭


解析

通過上述分析,我們可以發現HTTP請求其實像傳送郵件一樣,我們告訴郵局地址,郵局傳送郵件,請求頭是我們附加的一些資訊,可以告訴收件人,誰發的郵件,誰可以看

,這是一封加密的郵件,你要根據什麼規則把這封郵件翻譯過來等等規則,請求內容當然就是我們要傳送的具體內容,響應就是收件人給我的回信,響應頭會告訴我們一些附加資訊比如他告訴我們,你傳送的那個收件人沒有(404)或者我正確收到了你的來信(200),我給你的響應是什麼加密方式,你要怎麼解碼,響應內容就是他要告訴我們的具體內容,你也可以把郵局當做一個代理,收件人當做伺服器。

實戰

接下來,我們根據以上規則使用JAVA來構造一些請求

POST不帶請求實體請求方法


     
  1. import org.apache.http.HttpEntity;
  2. import org.apache.http.HttpResponse;
  3. import org.apache.http.NameValuePair;
  4. import org.apache.http.client.ClientProtocolException;
  5. import org.apache.http.client.HttpClient;
  6. import org.apache.http.client.entity.UrlEncodedFormEntity;
  7. import org.apache.http.client.methods.HttpGet;
  8. import org.apache.http.client.methods.HttpPost;
  9. import org.apache.http.client.utils.URIBuilder;
  10. import org.apache.http.entity.ContentType;
  11. import org.apache.http.entity.StringEntity;
  12. import org.apache.http.impl.client.CloseableHttpClient;
  13. import org.apache.http.impl.client.DefaultHttpClient;
  14. import org.apache.http.impl.client.HttpClients;
  15. import org.apache.http.message.BasicNameValuePair;
  16. import org.apache.http.util.EntityUtils;
public class TestHttp{
     
	public void postOne(){
     

     
  1. HttpClient client = new DefaultHttpClient();
  2. HttpResponse response = null;
  3. String url = "http://write.blog.csdn.net/postedit";
  4. HttpPost post = new HttpPost(url);
  5. post.setHeader( "Content-Type", "application/json");
  6. response = client.execute(post);
  7. String ret      = EntityUtils.toString(response.getEntity(), "UTF-8");
  8. System.out.println(ret);
}
     
}
     

     
解析: 1,首先我們要構造一個客戶端,apache對HttpClient這個類的解釋是該介面僅表示HTTP請求執行的最基本合同,它不會對請求執行過程施加任何限制或具體細節,並且將狀態管理,身份驗證和重定向處理的細節留給個別實現。具體意思就是我們要傳送HTTP請求就要先構造這個HTTPClient,但是涉及一些具體的細節比如cookies,header,request   body我們不需要用它來實現,這些具體的細節我們留給其他類來實現, 2,我們構造一個請求地址,即我們要把這個請求傳送給誰 3,構建Post請求,HttpPost有一個構造器HttpPost(String uri) ,我們用這個構造器來初始化HttpPost 4,新增header,HttpPost裡有一個setheader和addheader方法,這些方法是它繼承介面org.apache.http.HttpMessage得來的,這裡說一下add和set的區別,首先同名header 可以有多個,執行時使用第一個,當我們使用addheader時,如果同名header已經存在它會追加至原同名header後面,使用setheader時,他會覆蓋同名的header,我在header 中設定了我要傳送的請求體是json形式的(實際上並未攜帶請求體,攜帶請求體的會在下邊給例子) 5,當我們構造好客戶端,請求header,url地址後,此時就可以傳送了,自然就是client.execute即執行這個請求 6,接下來是接受響應,即我們傳送完郵件後,別人給我們回信了,我們要設法獲得這個回信的內容即HttpResponse response = client.execute(post) 來關聯我們的請求和響應,意思就是這個響應是我執行這個請求的響應getEntity是這個類自帶的方法,用來獲取響應實體,即具體的響應內容,它還有很多方法,獲取響應資訊,感興趣可以自行研究 7,EntityUtils這個類主要是用來處理HttpEntity的,它有一些靜態方法,我用的就是將這個響應實體以UTF-8的編碼格式轉換成字串,最後打印出來

具體響應

<html><head><title>Object moved</title></head><body><h2>Object moved to <a href="https://passport.csdn.net/account/login?from=http%3a%2f%2fwrite.blog.csdn.net%2fpostedit">here</a>.</h2></body></html> 解析: 還有一些其他的內容,不在這裡貼上,返回的html程式碼是一個重新登入的地址連結,點選以後告訴我們重新登入,因為我訪問的url是csdn的編輯頁,不登入怎麼可能直接訪問呢,我們可以嘗試使用cookie這裡告訴大家一個進階技巧,我們開啟瀏覽器,啟用開發者模式,然後重新登入一次,找到csdnbi這個介面,然後獲取requestheader中的cookies 具體如圖:

在這裡找到cookie後我們使用post.setheader("Cookie","*****")就可越過登入,直接請求到這個頁面了。感興趣的可以試一下。

具體響應

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head>    <script type="text/javascript" src="//static-blog.csdn.net/scripts/tingyun-rum.js"></script><title>編輯文章 - CSDN部落格</title><meta http-equiv="Content-Type" content="text/html; charset=utf-8" />    <link type="text/css" rel="Stylesheet" href="http://c.csdnimg.cn/pig/blog/write/css/main.css" />    <!--new top-->        <link rel="stylesheet" href="http://c.csdnimg.cn/public/common/toolbar/css/index.css">     <!--new top-->       <script type="text/javascript" src="//static-blog.csdn.net/scripts/jquery.js"></script>    <script type="text/javascript" src="//static-blog.csdn.net/scripts/jquery-version.js"></script><script type="text/javascript" src="//static-blog.csdn.net/scripts/csdn.js"></script><script type="text/javascript" src="http://c.csdnimg.cn/pig/blog/write/scripts/master.js"></script>        <script type="text/javascript">var statichost = "//static-blog.csdn.net";</script>               <link type='text/css' rel='Stylesheet' href='http://c.csdnimg.cn/pig/blog/write/css/write.css' /><script type='text/javascript' src='http://c.csdnimg.cn/pig/blog/write/scripts/jquery.autocomplete.min.js'></script> <script type='text/javascript' src='//static-blog.csdn.net/xheditor/xheditor-1.1.13-zh-cn.js'></script><link type='text/css' rel='Stylesheet' href='http://c.csdnimg.cn/pig/blog/write/css/jquery.autocomplete.css' /></head><body></body></html> body裡包含我的個人資訊在這裡就不給大家展示了

POST帶請求引數和請求實體

前言:如果我們前邊的都掌握了,那麼接下來的就很容易理解了,我們知道post請求時會攜帶一些引數比如 http://www.123.com/index.html?a=123還有一些我們要傳送的報文 其實引數和報文的處理方式是一樣的,那麼我們只要構造這個請求實體不就可以了嗎?

      
  1. List<BasicNameValuePair> nvps = new ArrayList<BasicNameValuePair>();
  2. nvps.add( new BasicNameValuePair( "baowen", "UTF-8"));
  3. post.setEntity( new UrlEncodedFormEntity(nvps, "UTF-8"));

解析: 1,我們加入BasicNameValuePair,這個類是幹嘛用的呢,apache的官方解釋是用作HTTP訊息元素的名稱 - 值對引數。我們就用它來構造引數 2,我為什麼用list,因為有時你的引數可能不止一個,這是它的一個構造器BasicNameValuePair(String name, String value) ,報文一定要是字串格式,UrlEncodedForm   Entity(List<? extends NameValuePair> parameters, String charset) 我要用這個類來構造實體就必須使用list來新增引數,同時這個類實際上是繼承StringEntity,它又實現了 HttpEntity這個介面,知道這一點很重要。 3,public void setEntity(HttpEntity entity)這個方法要傳入一個HttpEntity型別的引數,所以後邊我可以直接用。

GET不帶引數請求


     
  1. HttpGet get = new HttpGet(url);
  2. get.setHeader( "Content-Type", "application/json");
  3. HttpResponse rese = client.execute(get);
  4. String redsa = EntityUtils.toString(rese.getEntity());

GET攜帶引數請求


     
  1. CloseableHttpClient client3 = HttpClients.createDefault();
  2. List<NameValuePair> nvps2 = new ArrayList<NameValuePair>();
  3. nvps2.add( new BasicNameValuePair( "baowen", "213"));
  4. HttpResponse resep = null;
  5. URIBuilder builder = new URIBuilder(url);
  6. builder.setParameters(nvps2);
  7. HttpGet get21312 = new HttpGet(builder.build());
  8. response = client.execute(get21312);
  9. String sdf = EntityUtils.toString(response.getEntity(), "UTF-8");

注意

1,後邊的程式碼我沒有寫完整,我們需要根據自己的需求新增URL 2,header裡我用的都是json,大家可以根據自己需要什麼型別做改變 3,我將返回都轉換成了字串,方便列印 4,我這裡使用的是apache的http包,關於網路程式設計,JAVA也有自帶的java.net包

總結

通過上邊的學習我們明白,只要我們掌握了http請求由什麼組成,哪些類來構造這些東西,然後在解析響應剩下的就對我們來說很簡單了。萬變不離其宗,這次我發這個總結主要是由於之前發的一遍http 傳送 post請求 的貼訪問量很高,感覺有必要指引一下新入坑的同學們,當然我自己也在學習之中,歡迎大家留言,咱們互相探討,共同進步











前言

單純的copy程式碼沒有用,本篇從http請求的基本原理開始為大家講解,後邊有例項,希望大家一步一步看完,這樣無論編寫什麼請求我們都可以得心應手。

HTTP的組成

http訊息由客戶端到服務端的請求以及服務端到客戶端的響應組成

HTTP請求報文的格式

請求頭與請求正文中間有一行空行,是告訴伺服器請求頭到此結束了接下來是請求正文

請求方法:get,post,head,delete等等,告訴伺服器你的具體操作是什麼

URL:可以從網際網路上得到資源的位置和訪問方法的一種簡潔標識。URL結構:協議://域名 or IP地址:埠號/目錄/檔名.檔名字尾?引數=值 協議版本:目前幾乎用的都是http1.1版本,增加了一個很重要的特性它支援長連線,其他具體細微差別不做講述。 請求頭:請求頭部為請求報文添加了一些附加資訊,由“名/值”對組成,每行一對,名和值之間使用冒號分隔。 常用的請求頭包括:
請求正文:新增請求實體即你具體要請求的內容用於POST請求,GET不用

HTTP響應報文格式


HTTP狀態碼


HTTP響應頭


解析

通過上述分析,我們可以發現HTTP請求其實像傳送郵件一樣,我們告訴郵局地址,郵局傳送郵件,請求頭是我們附加的一些資訊,可以告訴收件人,誰發的郵件,誰可以看

,這是一封加密的郵件,你要根據什麼規則把這封郵件翻譯過來等等規則,請求內容當然就是我們要傳送的具體內容,響應就是收件人給我的回信,響應頭會告訴我們一些附加資訊比如他告訴我們,你傳送的那個收件人沒有(404)或者我正確收到了你的來信(200),我給你的響應是什麼加密方式,你要怎麼解碼,響應內容就是他要告訴我們的具體內容,你也可以把郵局當做一個代理,收件人當做伺服器。

實戰

接下來,我們根據以上規則使用JAVA來構造一些請求

POST不帶請求實體請求方法


   
  1. import org.apache.http.HttpEntity;
  2. import org.apache.http.HttpResponse;
  3. import org.apache.http.NameValuePair;
  4. import org.apache.http.client.ClientProtocolException;
  5. import org.apache.http.client.HttpClient;
  6. import org.apache.http.client.entity.UrlEncodedFormEntity;
  7. import org.apache.http.client.methods.HttpGet;
  8. import org.apache.http.client.methods.HttpPost;
  9. import org.apache.http.client.utils.URIBuilder;
  10. import org.apache.http.entity.ContentType;
  11. import org.apache.http.entity.StringEntity;
  12. import org.apache.http.impl.client.CloseableHttpClient;
  13. import org.apache.http.impl.client.DefaultHttpClient;
  14. import org.apache.http.impl.client.HttpClients;
  15. import org.apache.http.message.BasicNameValuePair;
  16. import org.apache.http.util.EntityUtils;
public class TestHttp{
   
	public void postOne(){
   

   
  1. HttpClient client = new DefaultHttpClient();
  2. HttpResponse response = null;
  3. String url = "http://write.blog.csdn.net/postedit";
  4. HttpPost post = new HttpPost(url);
  5. post.setHeader( "Content-Type", "application/json");
  6. response = client.execute(post);
  7. String ret      = EntityUtils.toString(response.getEntity(), "UTF-8");
  8. System.out.println(ret);
}
   
}
   

   
解析: 1,首先我們要構造一個客戶端,apache對HttpClient這個類的解釋是該介面僅表示HTTP請求執行的最基本合同,它不會對請求執行過程施加任何限制或具體細節,並且將狀態管理,身份驗證和重定向處理的細節留給個別實現。具體意思就是我們要傳送HTTP請求就要先構造這個HTTPClient,但是涉及一些具體的細節比如cookies,header,request   body我們不需要用它來實現,這些具體的細節我們留給其他類來實現, 2,我們構造一個請求地址,即我們要把這個請求傳送給誰 3,構建Post請求,HttpPost有一個構造器HttpPost(String uri) ,我們用這個構造器來初始化HttpPost 4,新增header,HttpPost裡有一個setheader和addheader方法,這些方法是它繼承介面org.apache.http.HttpMessage得來的,這裡說一下add和set的區別,首先同名header 可以有多個,執行時使用第一個,當我們使用addheader時,如果同名header已經存在它會追加至原同名header後面,使用setheader時,他會覆蓋同名的header,我在header 中設定了我要傳送的請求體是json形式的(實際上並未攜帶請求體,攜帶請求體的會在下邊給例子) 5,當我們構造好客戶端,請求header,url地址後,此時就可以傳送了,自然就是client.execute即執行這個請求 6,接下來是接受響應,即我們傳送完郵件後,別人給我們回信了,我們要設法獲得這個回信的內容即HttpResponse response = client.execute(post) 來關聯我們的請求和響應,意思就是這個響應是我執行這個請求的響應getEntity是這個類自帶的方法,用來獲取響應實體,即具體的響應內容,它還有很多方法,獲取響應資訊,感興趣可以自行研究 7,EntityUtils這個類主要是用來處理HttpEntity的,它有一些靜態方法,我用的就是將這個響應實體以UTF-8的編碼格式轉換成字串,最後打印出來

具體響應

<html><head><title>Object moved</title></head><body><h2>Object moved to <a href="https://passport.csdn.net/account/login?from=http%3a%2f%2fwrite.blog.csdn.net%2fpostedit">here</a>.</h2></body></html> 解析: 還有一些其他的內容,不在這裡貼上,返回的html程式碼是一個重新登入的地址連結,點選以後告訴我們重新登入,因為我訪問的url是csdn的編輯頁,不登入怎麼可能直接訪問呢,我們可以嘗試使用cookie這裡告訴大家一個進階技巧,我們開啟瀏覽器,啟用開發者模式,然後重新登入一次,找到csdnbi這個介面,然後獲取requestheader中的cookies 具體如圖:

在這裡找到cookie後我們使用post.setheader("Cookie","*****")就可越過登入,直接請求到這個頁面了。感興趣的可以試一下。

具體響應

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head>    <script type="text/javascript" src="//static-blog.csdn.net/scripts/tingyun-rum.js"></script><title>編輯文章 - CSDN部落格</title><meta http-equiv="Content-Type" content="text/html; charset=utf-8" />    <link type="text/css" rel="Stylesheet" href="http://c.csdnimg.cn/pig/blog/write/css/main.css" />    <!--new top-->        <link rel="stylesheet" href="http://c.csdnimg.cn/public/common/toolbar/css/index.css">     <!--new top-->       <script type="text/javascript" src="//static-blog.csdn.net/scripts/jquery.js"></script>    <script type="text/javascript" src="//static-blog.csdn.net/scripts/jquery-version.js"></script><script type="text/javascript" src="//static-blog.csdn.net/scripts/csdn.js"></script><script type="text/javascript" src="http://c.csdnimg.cn/pig/blog/write/scripts/master.js"></script>        <script type="text/javascript">var statichost = "//static-blog.csdn.net";</script>               <link type='text/css' rel='Stylesheet' href='http://c.csdnimg.cn/pig/blog/write/css/write.css' /><script type='text/javascript' src='http://c.csdnimg.cn/pig/blog/write/scripts/jquery.autocomplete.min.js'></script> <script type='text/javascript' src='//static-blog.csdn.net/xheditor/xheditor-1.1.13-zh-cn.js'></script><link type='text/css' rel='Stylesheet' href='http://c.csdnimg.cn/pig/blog/write/css/jquery.autocomplete.css' /></head><body></body></html> body裡包含我的個人資訊在這裡就不給大家展示了

POST帶請求引數和請求實體

前言:如果我們前邊的都掌握了,那麼接下來的就很容易理解了,我們知道post請求時會攜帶一些引數比如 http://www.123.com/index.html?a=123還有一些我們要傳送的報文 其實引數和報文的處理方式是一樣的,那麼我們只要構造這個請求實體不就可以了嗎?

    
  1. List<BasicNameValuePair> nvps = new ArrayList<BasicNameValuePair>();
  2. nvps.add( new BasicNameValuePair( "baowen", "UTF-8"));
  3. post.setEntity( new UrlEncodedFormEntity(nvps, "UTF-8"));

解析: 1,我們加入BasicNameValuePair,這個類是幹嘛用的呢,apache的官方解釋是用作HTTP訊息元素的名稱 - 值對引數。我們就用它來構造引數 2,我為什麼用list,因為有時你的引數可能不止一個,這是它的一個構造器BasicNameValuePair(String name, String value) ,報文一定要是字串格式,UrlEncodedForm   Entity(List<? extends NameValuePair> parameters, String charset) 我要用這個類來構造實體就必須使用list來新增引數,同時這個類實際上是繼承StringEntity,它又實現了 HttpEntity這個介面,知道這一點很重要。 3,public void setEntity(HttpEntity entity)這個方法要傳入一個HttpEntity型別的引數,所以後邊我可以直接用。

GET不帶引數請求


   
  1. HttpGet get = new HttpGet(url);
  2. get.setHeader( "Content-Type", "application/json");
  3. HttpResponse rese = client.execute(get);
  4. String redsa = EntityUtils.toString(rese.getEntity());

GET攜帶引數請求


   
  1. CloseableHttpClient client3 = HttpClients.createDefault();
  2. List<NameValuePair> nvps2 = new ArrayList<NameValuePair>();
  3. nvps2.add( new BasicNameValuePair( "baowen", "213"));
  4. HttpResponse resep = null;
  5. URIBuilder builder = new URIBuilder(url);
  6. builder.setParameters(nvps2);
  7. HttpGet get21312 = new HttpGet(builder.build());
  8. response = client.execute(get21312);
  9. String sdf = EntityUtils.toString(response.getEntity(), "UTF-8");

注意

1,後邊的程式碼我沒有寫完整,我們需要根據自己的需求新增URL 2,header裡我用的都是json,大家可以根據自己需要什麼型別做改變 3,我將返回都轉換成了字串,方便列印 4,我這裡使用的是apache的http包,關於網路程式設計,JAVA也有自帶的java.net包

總結

通過上邊的學習我們明白,只要我們掌握了http請求由什麼組成,哪些類來構造這些東西,然後在解析響應剩下的就對我們來說很簡單了。萬變不離其宗,這次我發這個總結主要是由於之前發的一遍http 傳送 post請求 的貼訪問量很高,感覺有必要指引一下新入坑的同學們,當然我自己也在學習之中,歡迎大家留言,咱們互相探討,共同進步