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-Controlgzip提升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-Controlgzip提升tomcat应用性能(整理), http://qin686-163-com.iteye.com/blog/287782




原文地址:https://www.cnblogs.com/strinkbug/p/5836534.html