1、
開發環境
客戶端:安卓+webview(vuejs)
服務器端:tomcat 8.0
2、問題
使用安卓原生+web(基於webpack+vuejs)的方式開發了一個安卓應用,因爲web的js文件較大,大概有400k左右,每次從app中打開該頁面都要從新從服務器端下載頁面的html、js和圖片等靜態資源,反應速度比較慢了,大概須要三四秒(若是用戶網速慢的話,則須要更久),體驗效果就很很差。
因此就考慮是否是能夠只在第一次打開的時候下載,而後就緩存在客戶端,之後只有有更新的時候才下載,可是開發人員在將安卓的webview的緩存選項設置爲
LOAD_DEFAULT以後,而且在html的head加上以下meta標籤,可是彷佛沒有效果,有時候會緩存,有時候有從新下載,和預期的行爲不一致。
<meta http-equiv="Cache-Control" content="max-age=
604800
"/>
3、分析
首先
安卓的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協議緩存
不過咱們通常都不會單獨使用某一項。css
因此我估計這個meta tag在android的webview中 是沒有做用的。
4、解決方案
在後端代碼中添加了過濾器,而後回覆的http報文頭上就有cache-control,就能夠按照設置的max-age正確緩存了。
Filter的代碼:
- public class ResponseHeaderFilter implements Filter {
- FilterConfig fc;
-
- public void doFilter(ServletRequest req, ServletResponse res,
- FilterChain chain) throws IOException, ServletException {
- HttpServletResponse response = (HttpServletResponse) res;
-
- for (Enumeration e = fc.getInitParameterNames(); e.hasMoreElements();) {
- String headerName = (String) e.nextElement();
- response.addHeader(headerName, fc.getInitParameter(headerName));
- }
-
- chain.doFilter(req, response);
- }
-
- public void init(FilterConfig filterConfig) {
- this.fc = filterConfig;
- }
-
- public void destroy() {
- this.fc = null;
- }
-
- }
web.xml裏的巧妙配置:
- <filter>
- <filter-name>NoCache</filter-name>
- <filter-class>apis.server.common.util.ResponseHeaderFilter</filter-class>
- <init-param>
- <param-name>Cache-Control</param-name>
- <param-value>no-cache, must-revalidate</param-value>
- </init-param>
- </filter>
- <filter>
- <filter-name>CacheForWeek</filter-name>
- <filter-class>apis.server.common.util.ResponseHeaderFilter</filter-class>
- <init-param>
- <param-name>Cache-Control</param-name>
- <param-value>max-age=604800, public</param-value>
- </init-param>
- </filter>
-
- <filter-mapping>
- <filter-name>NoCache</filter-name>
- <url-pattern>*.do</url-pattern>
- </filter-mapping>
- <filter-mapping>
- <filter-name>CacheForWeek</filter-name>
- <url-pattern>/images/*</url-pattern>
- </filter-mapping>
- <filter-mapping>
- <filter-name>CacheForWeek</filter-name>
- <url-pattern>/img/*</url-pattern>
- </filter-mapping>
- <filter-mapping>
- <filter-name>CacheForWeek</filter-name>
- <url-pattern>/icons/*</url-pattern>
- </filter-mapping>
- <filter-mapping>
- <filter-name>CacheForWeek</filter-name>
- <url-pattern>/ext/*</url-pattern>
- </filter-mapping>
- <filter-mapping>
- <filter-name>CacheForWeek</filter-name>
- <url-pattern>*.js</url-pattern>
- </filter-mapping>
- <filter-mapping>
- <filter-name>CacheForWeek</filter-name>
- <url-pattern>*.css</url-pattern>
- </filter-mapping>
附錄、參考資料