Open fred-ye opened 9 years ago
在做Web的时候,有这么一个体会。当我们第二次开一个网页的速度通常比第一次要快。举个例子,当我们用浏览器打开百度时,第一次打开百度,从浏览器开发者工具中我们可以看到(下面的图片太小了,点击才能看得清) 对于很多资源,服务器端返回的响应状态码是200。以bd_logo1.png资源为例,我们看它的响应状态:
bd_logo1.png
但是,当我们再一次访问百度时(刷新页面), 我们发现此时大部份资源的状态码是304. 如下图:
同样,看我们关注的那个bd_logo1.png资源,其状态
比对上面的两次操作。对于第一次操作,浏览器在向服务器请求这个图片资源时,http请求返回的状态码是200,其http request的header中没有太多的信息,其http response的header中有了两个我们比较关心的属性。
ETag:"1ec5-502264e2ae4c0" Last-Modified:Wed, 03 Sep 2014 10:00:27 GMT
在第二次请求时,其http request的header中添加了两个属性
If-Modified-Since:Wed, 03 Sep 2014 10:00:27 GMT If-None-Match:"1ec5-502264e2ae4c0"
第二次的请求,http response的header中,有一个 ETag:"1ec5-502264e2ae4c0", 但是并没有Last-Modified属性,同时第二次的http请求返回状态码是304
总结一下,对于第一次的http请求,服务器返回的状态码是200, 在返回我们需要的资源的同时会返回两个属性ETag和Last-Modified。在第二次请求时,虽说请求的是同一个资源,但会在http请求头中加入两个属性If-Modified-Since和If-None-Match。其中If-Modified-Since的值便是第一次请求资源时拿到的Last-Modified属性值,If-None-Match的值便是第一次请求资源时拿到的ETag值。当服务器拿到这两个属性后会再次和所请求的资源进行一个匹配,如果请求的资源这两个属性没有任何变化,便会返回一个304状态码给客户端,不会返回资源实体的内容,从而节省带宽,提高响应速度。
ETag
Last-Modified
If-Modified-Since
If-None-Match
在Android程序开发中,偶尔我们也需要利用这个原理。比如,由于某个特定业务需求,我们程序偶尔需要从服务器上的某个路径下载一个文本文件,而这个文本文件中内容变化不是非常频繁,可能几个月变一次,此时我们便可以利用这个机制了。以下给出一段简单的代码:
import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import com.aug.summary.R; import java.io.IOException; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; public class TestVolleyActivity extends Activity { private Button btnSend; private static String lastModified; private static String eTag; private static String date; private static final String TAG = "TestVolley"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test_volley); intView(); } private View.OnClickListener listener = new View.OnClickListener() { @Override public void onClick(View v) { new Thread() { public void run() { try { URL url = new URL("https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/static/protocol/https/global/img/icons_f0338722.png"); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); if (lastModified != null) { connection.addRequestProperty("If-Modified-Since", lastModified); } if(eTag != null) { connection.addRequestProperty("If-None-Match", eTag); } String responseMessage = connection.getResponseMessage(); lastModified = connection.getHeaderField("Last-Modified"); eTag = connection.getHeaderField("ETag"); Log.i(TAG, "last-modified:" + lastModified); Log.i(TAG, "eTag:" + eTag); Log.i(TAG, connection.getResponseCode() + " " + connection.getResponseMessage() + " content length:" + connection.getContentLength()); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }.start(); } }; public void intView() { btnSend = (Button) findViewById(R.id.btn_send_http_by_volly); btnSend.setOnClickListener(listener); } }
第一次点击按钮时Log如下
07-21 10:50:12.320 2075-2198/com.aug.summary I/TestVolley﹕ last-modified:Tue, 23 Jun 2015 08:24:13 GMT 07-21 10:50:12.320 2075-2198/com.aug.summary I/TestVolley﹕ eTag:"37a6-5192b1d838540" 07-21 10:50:12.320 2075-2198/com.aug.summary I/TestVolley﹕ 200 OK content length:14246
第二次点击按钮时Log如下
07-21 10:51:33.837 2075-2611/com.aug.summary I/TestVolley﹕ last-modified:Tue, 23 Jun 2015 08:24:13 GMT 07-21 10:51:33.837 2075-2611/com.aug.summary I/TestVolley﹕ eTag:"37a6-5192b1d838540" 07-21 10:51:33.837 2075-2611/com.aug.summary I/TestVolley﹕ 304 Not Modified content length:0
在做Web的时候,有这么一个体会。当我们第二次开一个网页的速度通常比第一次要快。举个例子,当我们用浏览器打开百度时,第一次打开百度,从浏览器开发者工具中我们可以看到(下面的图片太小了,点击才能看得清) 对于很多资源,服务器端返回的响应状态码是200。以
bd_logo1.png
资源为例,我们看它的响应状态:但是,当我们再一次访问百度时(刷新页面), 我们发现此时大部份资源的状态码是304. 如下图:
同样,看我们关注的那个
bd_logo1.png
资源,其状态比对上面的两次操作。对于第一次操作,浏览器在向服务器请求这个图片资源时,http请求返回的状态码是200,其http request的header中没有太多的信息,其http response的header中有了两个我们比较关心的属性。
在第二次请求时,其http request的header中添加了两个属性
第二次的请求,http response的header中,有一个 ETag:"1ec5-502264e2ae4c0", 但是并没有Last-Modified属性,同时第二次的http请求返回状态码是304
当服务器返回的状态码是304时,则是告诉客户端,请求的资源没有任何变化,直接从本地缓存中取。
总结一下,对于第一次的http请求,服务器返回的状态码是200, 在返回我们需要的资源的同时会返回两个属性
ETag
和Last-Modified
。在第二次请求时,虽说请求的是同一个资源,但会在http请求头中加入两个属性If-Modified-Since
和If-None-Match
。其中If-Modified-Since
的值便是第一次请求资源时拿到的Last-Modified
属性值,If-None-Match
的值便是第一次请求资源时拿到的ETag
值。当服务器拿到这两个属性后会再次和所请求的资源进行一个匹配,如果请求的资源这两个属性没有任何变化,便会返回一个304状态码给客户端,不会返回资源实体的内容,从而节省带宽,提高响应速度。在Android程序开发中,偶尔我们也需要利用这个原理。比如,由于某个特定业务需求,我们程序偶尔需要从服务器上的某个路径下载一个文本文件,而这个文本文件中内容变化不是非常频繁,可能几个月变一次,此时我们便可以利用这个机制了。以下给出一段简单的代码:
第一次点击按钮时Log如下
第二次点击按钮时Log如下