1. 程式人生 > >Html5離線儲存和資料同步

Html5離線儲存和資料同步

一、整體流程設計

流程細節如下:

(1)WebSQL用於儲存本地資料。

(2)LocalStroage用於暫存需要同步資料。

(3)XML用於儲存所有操作過程和數操作據。

(4)將localStroage的資料同步伺服器(資料衝突手動操作)。

(5)通過XML將伺服器資料同步本地。

(6)本地沒有資料直接同步伺服器。

(7)伺服器沒有資料直接同步本地。

二、資料結構設計

WebSQL:資料庫表。格式:items(id,name,num,user)

localStroage:Json陣列物件。格式:

    [  {id:(new Date()).getTime(),table:'items',op:"insert",name:' ',num:' ',user:' '},

    {id:(new Date()).getTime(),table:'items',op:"update",name:' ',num:' ',user:' '},

    {id:(new Date()).getTime(),table:'items',op:"delete",name:' ',num:' ',user:' '}}    ……]

     其中,josns[0]代表同步資料的起點,josns[josns.length-1]代表資料同步的終點

XML:

    <store dtatbase="Item">
    <op id="0"/>
    <op id="1366526718040" table="items" action="insert">
        <data name="name">測試2   </data>
        <data name="user">    </data>
        <data name="num"> 測試2</data>
        <data name="spell">T</data>
   </op>
  <op id="1366526728408" table="items" action="update">
     <data name="name">測試3</data>
   </op>
</store>

三、同步順序圖


分析說明:

(1)LastSynTime:標識使用者使用情況

  -1:表示使用者在該瀏覽器中第一次使用。然後獲取伺服器是否有該使用者資訊,如果有則直接將伺服器的資料更新到本地資料庫。

不等於-1:表示使用者已經操作過該瀏覽器。然後對syndata進行判斷。

(2)syndata:表示需要同步的資料

-1:表示使用者當前在該瀏覽器中沒有同步資料。然後獲取伺服器是否有該使用者資訊,如果有則直接將伺服器的資料更新到本地資料庫。

不等於-1:表示使用者在該瀏覽器中有同步資料。然後在進一步判斷。

(3)id_start::為syndata[0].id,表示需要同步資料中第一個資料的操作時間戳。

id_end:為syndata[syndata.length-1],表示需要同步資料中最後一個數據的操作時間戳。

ID_END:為XML中最後一個操作資料的時間戳。

(1)若ID_End<id_start,,則將本地同步資料更新伺服器資料庫。

(2)若ID_End>id_end,則提取上一次同步運算元的最後一個操作時間戳id_end,從伺服器獲取id_end到ID_End的資料操作並更新到瀏覽器的webBD資料庫。

(3)若id_start<ID_END<id_end,則id_start到ID_END為衝突資料需要使用者手工矯正,並將ID_END到id_end更新伺服器。

四、系統結構


五、使用者介面






















六、程式碼設計

1、服務端

1)、XML解析(dom4j)

(1)、獲取XM儲存的最後一個操作資料的時間戳(ID_END)

Element opElement = (Element) document.selectSingleNode("/store/op[last()]");
return opElement.attributeValue("id");

(2)、將JSON陣列轉化為XML:CretateOpXml(String json, String op, String table,String ID,String user)

        Element rootElement = dom.getRootElement();
Element opElement = rootElement.addElement("op");
opElement.addAttribute("id", ID);
opElement.addAttribute("table", table);
if (op != "delete") {
if (op == "insert") {
opElement.addAttribute("action", "insert");
} else if (op == "update") {
opElement.addAttribute("action", "update");
}
String[] items = json.split(",");
for (String item : items) {
Element dataElement = opElement.addElement("data");
String[] content = item.split(":");
dataElement.addAttribute("name", content[0]);
dataElement.setText(content[1]);
}
} else {
opElement.addAttribute("action", "delete");
Element dataElement = opElement.addElement("data");
String[] content = json.split(":");
dataElement.addAttribute("name", content[0]);
dataElement.setText(content[1]);
}

(3)、將XML轉換為SQL語句: String ParseSql(String id,String user)

               StringBuffer sql = new StringBuffer();
Document document = load(fileName+user+".xml");
Element opIdElement = (Element) document.selectSingleNode("/store/op[last()]");
sql.append(opIdElement.attributeValue("id")+"|");
List list = document.selectNodes("/store/op[@id>=" + id + "]");
Iterator iter = list.iterator();
int j=0;
while (iter.hasNext()) {
Element opElement = (Element) iter.next();
String table = opElement.attributeValue("table");
Iterator<Element> dataElement = opElement.elementIterator();
StringBuffer col = new StringBuffer();
StringBuffer val = new StringBuffer();
int i = 0;
while (dataElement.hasNext()) {
Element nameElemnt = (Element) dataElement.next();
if (i == 0) {
col.append(nameElemnt.attributeValue("name"));
val.append("'" + nameElemnt.getText() + "'");
} else {
col.append("," + nameElemnt.attributeValue("name"));
val.append(",'" + nameElemnt.getText() + "'");
}


i++;
}
if (j == 0) {
if (opElement.attributeValue("action").equals("insert")) {
sql.append("incao zuosert into " + table + " (" + col.toString()+ ") values (" + val.toString() + ")");
} else if (opElement.attributeValue("action").equals("update")) {
String[] colSplit= col.toString().split(",");
String[] valSplit= val.toString().split(",");
String idUpdate=null;
StringBuffer update=new StringBuffer();
for(int ii=0;ii<colSplit.length;ii++){
if(ii==1){
update.append(colSplit[ii]+"="+valSplit[ii]);
}else if(ii>1){
update.append(","+colSplit[ii]+"="+valSplit[ii]);
}else{
idUpdate=colSplit[ii]+"="+valSplit[ii];
}
}
sql.append("update "+table+" set " + update.toString()+" where "+idUpdate);
} else {// delete
sql.append("delete from " + table + " where "+ col.toString() + "=" + val.toString());
}
}else{
if (opElement.attributeValue("action").equals("insert")) {
sql.append(";insert into " + table + " (" + col.toString() + ") values (" + val.toString() + ")");
} else if (opElement.attributeValue("action").equals("update")) {
String[] colSplit= col.toString().split(",");
String[] valSplit= val.toString().split(",");
String idUpdate=null;
StringBuffer update=new StringBuffer();
for(int ii=0;ii<colSplit.length;ii++){
if(ii==1){
update.append(colSplit[ii]+"="+valSplit[ii]);
}else if(ii>1){
update.append(","+colSplit[ii]+"="+valSplit[ii]);
}else{
idUpdate=colSplit[ii]+"="+valSplit[ii];
}
}
sql.append(";update "+table+" set " + update.toString()+" where "+idUpdate);
} else {// delete
sql.append(";delete from " + table + " where "+ col.toString() + "=" + val.toString());
}
}
j++;
}
return sql.toString();

2)、服務端資料解析(將ajax傳遞的JSON陣列物件轉換為JSON物件,同時更新資料庫)

String synClientData(String userName){

Long ID=(long) 0;//Long.parseLong(OpStoreService.GetLastTime());
JSONArray array = JSONArray.fromObject(getJsonData());
StringBuffer sql=new StringBuffer();
try {
int j=0;
for (int i = 0; i < array.size(); i++) {
Map o = (Map) array.get(i);
String table=o.get("table").toString();
String clientID=o.get("ID").toString();
if(Long.parseLong(clientID)>ID){
if(o.get("op").equals("insert")){
if(j==0){
sql.append("insert into "+table+" (");
}else{
sql.append(";insert into "+table+" (");
}
Iterator iter = o.entrySet().iterator();
StringBuffer col=new StringBuffer();
StringBuffer val=new StringBuffer();
StringBuffer xml=new StringBuffer();
int k=0;
while (iter.hasNext()) {
Map.Entry<String, String> param = null;
param = (Entry<String, String>) iter.next();
if(param.getKey().equals("ID")||param.getKey().equals("op")||param.getKey().equals("table")){
continue;
}else{
if(k==0){
col.append(param.getKey());
val.append("'"+param.getValue()+"'");
xml.append(param.getKey()+":"+param.getValue());
}else{
col.append(","+param.getKey());
val.append(",'"+param.getValue()+"'");
xml.append(","+param.getKey()+":"+param.getValue());
}
}
k++;
}
j++;
OpStoreService os=new OpStoreService();
os.CretateOpXml(xml.toString(), "insert", table,clientID,userName);
sql.append(col.toString()+") values (" +val.toString()+")");
}else if(o.get("op").equals("update")){
if(j==0){
sql.append("update "+table+" set ");
}else{
sql.append(";update "+table+" set ");
}
Iterator iter = o.entrySet().iterator();
String id=null;
StringBuffer xml=new StringBuffer();
int k=0;
while (iter.hasNext()) {
Map.Entry<String, String> param = null;
param = (Entry<String, String>) iter.next();
if(param.getKey().equals("ID")||param.getKey().equals("op")||param.getKey().equals("table")){
continue;
}else{
if(param.getKey().equals("id"))
{
id=param.getValue().toString();
xml.append("id:"+id);
}else{
xml.append(","+param.getKey()+":"+param.getValue());
if(k==0){
sql.append(param.getKey()+"='"+param.getValue()+"'");
}else{
sql.append(","+param.getKey()+"='"+param.getValue()+"'");
}
k++;
}
}
}
j++;
OpStoreService os=new OpStoreService();
os.CretateOpXml(xml.toString(), "update", table,clientID,userName);
sql.append(" where id='"+id+"'");
}else{
if(j==0){
sql.append("delete from "+table+" where id='"+o.get("id").toString()+"'");
}else{
sql.append(";delete from "+table+" where id='"+o.get("id").toString()+"'");
}
OpStoreService os=new OpStoreService();
os.CretateOpXml("id:"+o.get("id").toString(), "delete", table,clientID,userName);
j++;
}
}
}
}finally{
}
return sql.toString();

}

2、瀏覽器

1)js資料儲存結構localStorage.getItem(item,value)

username:記錄登陸使用者名稱                                       username+"LastSynTime":該使用者本地操作資料的最後一次時間戳       

username+"Syn":記錄該使用者需要同步的              username+"LastSyn":該使用者同步操作資料的最後一次時間戳        

2)使用者點選同步

$("#commitSynData").bind("vclick",function(e){
if(localStorage.getItem("LastSynTime")==null){//無,若伺服器有資料,則獲取全部資料
LoadServAllData();
} else{//有,根據更新時間先後對比伺服器和客戶端,若有資料變化,將此資料傳送伺服器
//判斷本地資料是否變化
SendLastSynTime();
}
});

function SendLastSynTime(){
$.ajax({  
        url:'/DiscreteCourse/DoAction_SendLastSynTime.do',  
        type:'POST',  
        data:{json:LastSynTime()},  
        dataType:'json',  
        success:function (data) {
        if(data.json.trim().length<3){
        }else if(data.json.trim().length==3){
        LoadServAllData();
        }else if(data.json.trim().length==4){
        sendLoalAllData();
        }else if(data.json.trim().length==13){
        sendLocalPartData(data.json.trim());
        }else{
        var sqls=data.json.split('|');
        doSql(sqls[1]);
        upLastTime(sqls[0]);
        }
        }  
    }); 
}

2)webSQL全部更新

function doSql(sql){
var sqlItems=sql.split(";");
try {
localDB.transaction(function(transaction){
            for(var i in sqlItems){
            transaction.executeSql(sqlItems[i]);
            }
            });
        } catch (e) {
            updateStatus("很抱歉,資料庫出錯!");
        }
}

七、存在的不足和優化

相關推薦

Html5離線儲存資料同步

一、整體流程設計 流程細節如下: (1)WebSQL用於儲存本地資料。 (2)LocalStroage用於暫存需要同步資料。 (3)XML用於儲存所有操作過程和數操作據。 (4)將localStroage的資料同步伺服器(資料衝突手動操作)。 (5)通過XML將伺服器資料

s5 Docker的持久化儲存資料共享

資料庫容器的資料如何才能不會丟失?Docker的持久化儲存技術。Docker的資料共享技術能極大提高開發人員的開發效率,邊寫程式碼,邊看執行結果。 資料持久化之Data Volume   Docker持久化資料的方案 ·基於本地檔案系統的Volume。可以在執行Docker create

定時任務資料同步備份

1 定時任務 1.1 linux定時任務排程分為兩種 1、系統自動執行的任務工作 2、使用者執行的任務工作 crontab  適合週期性的執行任務 at 適合僅執行一次就結束的任務排程命令  對應的服務是atd,一般沒用,關閉 [[email protected]

zookeeper負載均衡資料同步

如何利用zookeeper做負載均衡呢,並且能夠讓客戶端動態監控服務端的狀態,一旦有的伺服器掛掉,客戶端能夠迅速感知,從而做出調整。 先演示一遍:注意,本地要執行一個zookeeper,讓客戶端和服務端分別和zookeeper進行連線,能實時跟zookeeper保持聯絡。 import ja

redis資料一致性,開發中關於快取資料同步問題

在開發中出現很多關於快取和資料共存問題,本小G網上翻閱cache aside pattern 一些資料,加上專案體驗寫下 寫下這一小簡,大家一塊來探討: 使用場景:在使用redis來做資料快取,減輕資料壓力和速度,但是有一個問題就是快取和my

資料庫系統概念(機械工業出版社,第六版)複習——第十章:資料儲存資料存取

第十章 資料儲存和資料存取 檔案組織 每個檔案分成定長的儲存單元,稱作塊(block),塊是儲存分配和資料傳輸的基本單元。 變長記錄 分槽頁結構: 分槽的頁結構一般用於在塊中組織記錄。 分槽頁頁頭,在

[html5]離線儲存

H5的一個重要特性就是離線儲存,所謂的離線儲存就是將一些資原始檔儲存在本地,這樣後續的頁面重新載入將使用本地資原始檔,在離線情況下可以繼續訪問web應用,同時通過一定的手法(更新相關檔案或者使用相關API),可以更新、刪除離線儲存等操作; H5的離線儲存使用一個manife

從零開始學習docker(九)持久化儲存資料共享

有些時候容器會產生一些資料,而我們不希望這些資料隨著容器的刪除而刪除。想保證資料的安全,一般用在資料庫。 首先看一下contai

從零開始學習docker(九)持久化儲存資料共享之 bind Mounting

資料持久化的第一種方式Data Volume 使用Data Volume: 首先在Dockerfile中定義 Volu

利用Node實現HTML5離線儲存

### 前言 支援離線Web應用開發是HTML5的一個重點。離線Web應用就是在裝置不能上網的時候仍然可以執行的應用。開發離線Web應用需要幾個步驟,其中一個就是離線下必須能訪問一定的資源(影象 JS css等) HTML5引入了應用程式快取,這意味著 web 應用可進行快取,並可在離線時進行訪問。

離線資料儲存上傳方案

QQ技術交流群:129518033解決方案下載地址:Github相關專案:引言在網路廣泛普及的今天,各行各業的發展都對網路產生了很大的依賴性.瞬時的斷網可能會對一些行業造成巨大的損失,如銀行,金融等資料量較大的行業.斷網或者網路傳輸失敗都可能會使一些即時產生的關鍵資料丟失,導

hadoop離線資料儲存挖掘架構

前序:     當你把你知道的東西,寫下來,讓人看明白是一種境界;當你能把自己寫下來的東西給人講明白,又是另一種境界。在這個過程中,我們都需要歷練。基於hadoop叢集下海量離線資料儲存和挖掘分析架構:       架構圖採用主流的Hadoop+Hive+Hbase叢集架構平

HTML5離線儲存

0.11 logo 頭部 locals style session .html ani 新建 localStorage 長期存儲數據,瀏覽器關閉後數據不丟失;sessionStorage 數據在瀏覽器關閉後自動刪除。 在用戶沒有與因特網連接時,可以正常訪問站點或應用,在用戶

Atitit 儲存方法大總結 目錄 1. 儲存方式分類 2 1.1. 按照資料分類為 結構化 半結構化 非結構化 2 1.2. 按照內外部可分類 內部儲存外部儲存持久化 2 1.3. 按照本地遠

Atitit 儲存方法大總結   目錄 1. 儲存方式分類 2 1.1. 按照資料分類為  結構化 半結構化 非結構化 2 1.2. 按照內外部可分類 內部儲存和外部儲存持久化 2 1.3. 按照本地遠端分類 分散式儲存等 2 1.4. 臨時性cach

微信小程式中資料儲存獲取

/儲存資料     try {       wx.setStorageSync('key',this.data.radioCheckVal2)  //key表示data中的引數

學習大資料技術,Hive實踐分享之儲存壓縮的坑

在學習大資料技術的過程中,HIVE是非常重要的技術之一,但我們在專案上經常會遇到一些儲存和壓縮的坑,本文通過科多大資料的武老師整理,分享給大家。 大家都知道,由於叢集資源有限,我們一般都會針對資料檔案的「儲存結構」和「壓縮形式」進行配置優化。在我實際檢視以後,發現叢集的檔案儲存格式為Parque

使用HTML5 IndexDB儲存影象檔案

使用IndexDB儲存影象和檔案 有一天,我們寫了關於如何在localStorage中儲存影象和檔案的文章,它是關於我們今天可用的實用主義。 然而,localStorage有一些效能影響 - 我們將在稍後的部落格中討論這個問題 - 並且未來期望的方法是使用IndexedDB。 在這裡,我將向您介紹如何在In

pickle模組以特殊的二進位制格式儲存恢復資料物件

先用pickle模組進行資料物件的儲存 1 import pickle 2 3 data1 = {'a': [1, 2, 3, 9], 4 'b': ('string', 'Unicode string'), 5 'c': ('True',

MySQL資料同步,出現Slave_SQL_Running:noslave_io_running:no問題的解決方法

一、問題描述: 當我們配置好MySQL主主同步時,是可以實現主主同步,但是重啟機器後就發現無法同步了。 二、Slave兩個關鍵程序: mysql replication 中slave機器上有兩個關鍵的程序,死一個都不行,一個是slave_sql_running,一個是Slave_IO_Running,一

日期型別的資料在Oracle資料庫中的儲存查詢

使用Oracle資料庫,mybatis的對映檔案中日期型別的資料,如果定義為<result column =“UPDATED_DATE" jdbcType =“DATE” property =“updatedDate”/>,即使在後臺你為日期賦予年月日時分秒,但儲存到資料庫中將只