WebApp:如何讓安卓的webview緩存webapp的html、js和圖片等資源


一、 開發環境
    客戶端:安卓+webview(vuejs)
    服務器端:tomcat 8.0

二、問題
    使用安卓原生+web(基於webpack+vuejs)的方式開發了一個安卓應用,由於web的js文件較大,大概有400k左右,每次從app中打開該頁面都要重新從服務器端下載頁面的html、js和圖片等靜態資源,反應速度比較慢了,大概需要三四秒(如果用戶網速慢的話,則需要更久),體驗效果就很不好。
    所以就考慮是不是可以只在第一次打開的時候下載,然后就緩存在客戶端,以后只有有更新的時候才下載,但是開發人員在將安卓的webview的緩存選項設置為 LOAD_DEFAULT之后,並且在html的head加上如下meta標簽,但是似乎沒有效果,有時候會緩存,有時候有重新下載,和預期的行為不一致。
     <meta http-equiv="Cache-Control" content="max-age= 604800 "/>

三、分析
    首先 安卓的webview的緩存選項設置為 LOAD_DEFAULT應該沒錯,這點沒有太大疑問,我們就是想要  根據cache-control決定是否從網絡上取數據。

    然后重點就是在html中的這個Cache-Control設置,分析之后發現這其實是一個http協議范疇的內容,下圖是《http 權威指南》中的描述。

所以現在要驗證這個在html的cache-control meta標簽是否起作用,可以從兩個方面來找原因:
(1) 首先可以看看tomcat是否支持,比如他在遇到html的時候,是否會解析其中的cache-control meta設置,然后在回復的http報文頭上加上Cache-Control,使用wireshark抓取的html頁面響應的報文頭如下,這說明tomcat默認是不支持解析html頁面頭上的cache-control meta標簽的。
 (2) 然后就是看安卓的webview是否支持解析該meta標簽了,這點在android官方的webview說明中沒有招到,可能要去webkit的官方去找。
但是一篇博文上招到如下說明:
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" /><meta http-equiv="Pragma" content="no-cache" /><meta http-equiv="Expires" content="0" />

但,實際情況是,這些meta只能在file:// 本地文件中使用,如果是服務器則默認被覆蓋。現在目前主流的就是使用HTTP1.1協議緩存
不過我們一般都不會單獨使用某一項。

      所以我估計這個meta tag在android的webview中 是沒有作用的。

四、解決方案
    按照: 使用 Cache-Control gzip 提升 tomcat 應用性能 ( 整理 ),  http://qin686-163-com.iteye.com/blog/287782
    在后端代碼中添加了過濾器,然后回復的http報文頭上就有cache-control,就可以按照設置的max-age正確緩存了。

Filter的代碼: 
Java代碼   收藏代碼
  1. public class ResponseHeaderFilter implements Filter {  
  2.     FilterConfig fc;   
  3.   
  4.     public void doFilter(ServletRequest req, ServletResponse res,  
  5.             FilterChain chain) throws IOException, ServletException {  
  6.         HttpServletResponse response = (HttpServletResponse) res;  
  7.         // set the provided HTTP response parameters  
  8.         for (Enumeration e = fc.getInitParameterNames(); e.hasMoreElements();) {  
  9.             String headerName = (String) e.nextElement();  
  10.             response.addHeader(headerName, fc.getInitParameter(headerName));  
  11.         }  
  12.         // pass the request/response on  
  13.         chain.doFilter(req, response);  
  14.     }   
  15.   
  16.     public void init(FilterConfig filterConfig) {  
  17.         this.fc = filterConfig;  
  18.     }   
  19.   
  20.     public void destroy() {  
  21.         this.fc = null;  
  22.     }   
  23.   
  24. }  




web.xml里的巧妙配置: 

Xml代碼   收藏代碼
  1. <filter>  
  2.         <filter-name>NoCache</filter-name>  
  3.         <filter-class>apis.server.common.util.ResponseHeaderFilter</filter-class>  
  4.         <init-param>  
  5.             <param-name>Cache-Control</param-name>  
  6.             <param-value>no-cache, must-revalidate</param-value>  
  7.         </init-param>  
  8.     </filter>  
  9.     <filter>  
  10.         <filter-name>CacheForWeek</filter-name>  
  11.         <filter-class>apis.server.common.util.ResponseHeaderFilter</filter-class>  
  12.         <init-param>  
  13.             <param-name>Cache-Control</param-name>  
  14.             <param-value>max-age=604800, public</param-value>  
  15.         </init-param>  
  16.     </filter>  
  17.   
  18. <filter-mapping>  
  19.         <filter-name>NoCache</filter-name>  
  20.         <url-pattern>*.do</url-pattern>  
  21.     </filter-mapping>  
  22.     <filter-mapping>  
  23.         <filter-name>CacheForWeek</filter-name>  
  24.         <url-pattern>/images/*</url-pattern>  
  25.     </filter-mapping>  
  26.     <filter-mapping>  
  27.         <filter-name>CacheForWeek</filter-name>  
  28.         <url-pattern>/img/*</url-pattern>  
  29.     </filter-mapping>  
  30.     <filter-mapping>  
  31.         <filter-name>CacheForWeek</filter-name>  
  32.         <url-pattern>/icons/*</url-pattern>  
  33.     </filter-mapping>  
  34.     <filter-mapping>  
  35.         <filter-name>CacheForWeek</filter-name>  
  36.         <url-pattern>/ext/*</url-pattern>  
  37.     </filter-mapping>  
  38.     <filter-mapping>  
  39.         <filter-name>CacheForWeek</filter-name>  
  40.         <url-pattern>*.js</url-pattern>  
  41.     </filter-mapping>  
  42.     <filter-mapping>  
  43.         <filter-name>CacheForWeek</filter-name>  
  44.         <url-pattern>*.css</url-pattern>  
  45.     </filter-mapping>   

附錄、參考資料
0)親,你知道緩存是什么嗎? https://segmentfault.com/a/1190000004486640 
1) android Cache —— webview 的緩存處理, http://blog.csdn.net/yehui928186846/article/details/51445894
2) 介紹 Cache-control 來詳解網頁的緩存問題, http://www.56gee.com/Detail/2013/07/22/8A96968D88/
3) 使用 Cache-Control gzip 提升 tomcat 應用性能 ( 整理 ),  http://qin686-163-com.iteye.com/blog/287782





免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM