HTML5也提供基于SQL的数据库存储机制,用于存储适合数据库的结构化数据。根据官方的标准文档,Web SQL Database存储机制不再推荐使用,将来也不再维护,而是推荐使用AppCache和IndexedDB。
现在主流的浏览器都还是支持Web SQL Database存储机制的。Web SQL Database存储机制提供了一组API供Web App创建、存储、查询数据库。
下面通过简单的例子,演示下Web SQL Database的使用。
<script> if(window.openDatabase){ //打开数据库,如果没有则创建 var db = openDatabase('mydb', '1.0', 'Test DB', 2 * 1024); //通过事务,创建一个表,并添加两条记录 db.transaction(function (tx) { tx.executeSql('CREATE TABLE IF NOT EXISTS LOGS (id unique, log)'); tx.executeSql('INSERT INTO LOGS (id, log) VALUES (1, "foobar")'); tx.executeSql('INSERT INTO LOGS (id, log) VALUES (2, "logmsg")'); }); //查询表中所有记录,并展示出来 db.transaction(function (tx) { tx.executeSql('SELECT * FROM LOGS', [], function (tx, results) { var len = results.rows.length, i; msg = "<p>Found rows: " + len + "</p>"; for(i=0; i<len; i++){ msg += "<p>" + results.rows.item(i).log + "</p>"; } document.querySelector('#status').innerHTML = msg; }, null); }); } </script> <div id="status" name="status">Status Message</div><br>
将上面代码复制到sql_database.html中,用浏览器打开,可看到下面的内容。
官方建议浏览器在实现时,对每个Host的数据库存储空间作一定限制,建议默认是5MB(分Host)的配额;达到上限后,可以申请更多存储空间。另外,现在主流浏览器SQLDatabase的实现都是基于SQLite。
分析:SQL Database的主要优势在于能够存储结构复杂的数据,能充分利用数据库的优势,可方便对数据进行增加、删除、修改、查询。由于SQL语法的复杂性,使用起来麻烦一些。SQLDatabase也不太适合做静态文件的缓存。
在Android内嵌Webview 中,需要通过Webview设置接口启用SQL Database,同时还要设置数据库文件的存储路径。
WebView myWebView = (WebView) findViewById(R.id.webview); WebSettings webSettings = myWebView.getSettings(); webSettings.setDatabaseEnabled(true); final String dbPath = getApplicationContext().getDir("db", Context.MODE_PRIVATE).getPath(); webSettings.setDatabasePath(dbPath); <br>
Android系统也使用了大量的数据库用来存储数据,比如联系人、短消息等;数据库的格式也SQLite。Android也提供了API来操作SQLite。WebSQL Database存储机制就是通过提供一组API,借助浏览器的实现,将这种Native的功能提供给了Web App。
Application Cache(简称AppCache)似乎是为支持Web App离线使用而开发的缓存机制。它的缓存机制类似于浏览器的缓存(Cache-Control和Last-Modified)机制,都是以文件为单位进行缓存,且文件有一定更新机制。但AppCache是对浏览器缓存机制的补充,不是替代。
先拿W3C官方的一个例子,说下AppCache机制的用法与功能。
<!DOCTYPE html> <html manifest="demo_html.appcache"> <body> <script src="demo_time.js"></script> <p id="timePara"><button onclick="getDateTime()">Get Date and Time</button></p> <p><img data-original="img_logo.gif" width="336" height="69"></p> <p>Try opening <a href="tryhtml5_html_manifest.htm" target="_blank">this page</a>, then go offline, and reload the page. The script and the image should still work.</p> </body> </html>
上面HTML文档,引用外部一个JS文件和一个GIF图片文件,在其HTML头中通过manifest属性引用了一个appcache结尾的文件。
我们在Google Chrome浏览器中打开这个HTML链接,JS功能正常,图片也显示正常。禁用网络,关闭浏览器重新打开这个链接,发现JS工作正常,图片也显示正常。当然也有可能是浏览缓存起的作用,我们可以在文件的浏览器缓存过期后,禁用网络再试,发现HTML页面也是正常的。
通过Google Chrome浏览器自带的工具,我们可以查看已经缓存的AppCache(分Host)。
上面截图中的缓存,就是我们刚才打开HTML的页面AppCache。从截图中看,HTML页面及HTML引用的JS、GIF图像文件都被缓存了;另外HTML头中manifest属性引用的appcache文件也缓存了。
AppCache的原理有两个关键点:manifest属性和manifest文件。
HTML在头中通过manifest属性引用manifest文件。manifest文件,就是上面以appcache结尾的文件,是一个普通文件文件,列出了需要缓存的文件。
上面截图中的manifest文件,就HTML代码引用的manifest文件。文件比较简单,第一行是关键字,第二、三行就是要缓存的文件路径(相对路径)。这只是最简单的manifest文件,完整的还包括其他关键字与内容。引用manifest文件的HTML和manifest文件中列出的要缓存的文件最终都会被浏览器缓存。
完整的manifest文件,包括三个Section,类型Windows中ini配置文件的Section,不过不要中括号。
完整的manifest文件,如:
CACHE MANIFEST # 2012-02-21 v1.0.0 /theme.css /logo.gif /main.js NETWORK: login.asp FALLBACK: /html/ /offline.html <br>
总的来说,浏览器在首次加载HTML文件时,会解析manifest属性,并读取manifest文件,获取Section:CACHE MANIFEST下要缓存的文件列表,再对文件缓存。
AppCache的缓存文件,与浏览器的缓存文件分开存储的,还是一份?应该是分开的。因为AppCache在本地也有5MB(分Host)的空间限制。
AppCache在首次加载生成后,也有更新机制。被缓存的文件如果要更新,需要更新manifest文件。因为浏览器在下次加载时,除了会默认使用缓存外,还会在后台检查manifest文件有没有修改(byteby byte)。发现有修改,就会重新获取manifest文件,对Section:CACHE MANIFEST下文件列表检查更新。manifest文件与缓存文件的检查更新也遵守浏览器缓存机制。
如用用户手动清了AppCache缓存,下次加载时,浏览器会重新生成缓存,也可算是一种缓存的更新。另外,Web App也可用代码实现缓存更新。
分析:AppCache看起来是一种比较好的缓存方法,除了缓存静态资源文件外,也适合构建Web离线 App。在实际使用中有些需要注意的地方,有一些可以说是”坑“。
另外,根据官方文档,AppCache已经不推荐使用了,标准也不会再支持。现在主流的浏览器都是还支持AppCache的,以后就不太确定了。
在Android内嵌Webview中,需要通过Webview设置接口启用AppCache,同时还要设置缓存文件的存储路径,另外还可以设置缓存的空间大小。
WebView myWebView = (WebView) findViewById(R.id.webview); WebSettings webSettings = myWebView.getSettings(); webSettings.setAppCacheEnabled(true); final String cachePath = getApplicationContext().getDir("cache", Context.MODE_PRIVATE).getPath(); webSettings.setAppCachePath(cachePath); webSettings.setAppCacheMaxSize(5*1024*1024);<br>