羅偉雄++時東曉++曾紀霞++劉嵐++郭柏喬



摘要:為了讓企業能夠把所有員工的通訊錄信息進行統一管理,實現數據的高度共享,讓每個用戶都能自主、自動、及時地維護自己在云端的通訊錄信息,以提高數據的時效性、準確性、可靠性和可用性,減輕企業對員工通訊錄的維護工作量,降低維護成本。于此提出并已成功開發了以云計算技術為基礎,以HJO(HTTP+JSON+OAuth)為架構的企業共享型移動通訊錄,并在客戶中試用得到了好評。系統利用智能移動終端使用和攜帶方便的特點,使系統突破了時間和地點的限制,充分顯現移動應用方便、快捷等特色。
關鍵詞:云計算;共享型;移動通訊錄;HTTP;JSON;OAuth
中圖分類號:TP311
文獻標識碼:A
DOI: 10.3969/j.issn.1003-6970.2015.07.019
0 引言
當今的通訊錄可以涵蓋多項內容,如:姓名、單位電話、移動電話、電子郵件、QQ等等],其準確性非常重要。而作為企業使用的通訊錄更要求它具有良好的共享能力。傳統的紙質通訊錄成本高,攜帶不方便,查找速度慢,難以更新維護。而電子版通訊錄大致分為遠程通訊錄和本地通訊錄。遠程通訊錄就是把通訊錄信息存放在云端服務器,比較典型的有Gmail、騰訊等提供的電子郵件系統中的通訊錄,金山、百度等提供的云盤通訊錄,這類通訊錄往往是一種數據同步工具,用于把個人手機和電腦上的通訊錄備份到云端,當需要時再從云端把數據恢復到手機或電腦的本地通訊錄中。而手機通訊錄、Outlook、Foxmail等郵件客戶端上的地址簿等則屬于本地通訊錄,這類通信錄的信息都是存放在本地的設備上。以上這些通訊錄以私有化的居多,共享能力有限,而且大多要管理員維護,用戶自行更新操作繁瑣,其更新效率和準確性也不盡如人意。
而隨著智能移動終端功能的增強和價格的下降,其普及率越來越高,據統計2014年中國智能手機用戶已超過5億。如果電子通訊錄能以智能移動設備為平臺,并結合云計算技術,那將會很好地解決上面的問題,同時也給用戶帶來更好的使用體驗。基于以上的環境和需求,筆者設計和開發了一套以云計算技術為基礎,以HJO(HTTP+JSON+OAuth)為架構的企業共享型云通訊錄,并已投入使用。系統通過把通訊錄信息云化,實現了數據的共享,消除用戶對數據訪問的地理局限性;通過運用HJO架構,減輕了數據的傳輸量,為Web應用、桌面應用和移動應用提供了統一的接口,簡化了應用的開發。通過該系統用戶可以便捷地使用智能移動終端設備來查詢云端的通訊錄信息,并能自主地維護自己的通訊錄,保證了信息的準確性和共享能力,同時還降低了管理員的維護工作量。利用來電提示功能,用戶不需要維護手機本身的通訊錄,也能對同事的來電一目了然;使用離線數據同步技術方便了用戶離線使用,節省了通訊流量。這些都給用戶帶來了更好的使用體驗。
1 總體架構
本系統以云計算技術為基礎,以HJO(HTTP+JSON+OAuth)的架構來進行系統設計。系統分為三個部分,分別是云端數據、客戶端和管理端。其中云端數據分為數據存儲層、數據處理層和數據訪問層。該部分主要使用云計算技術對數據進行存儲和處理,消除用戶對數據訪問的地理局限性。
(1)數據存儲層。這里可以選擇通用的關系型數據庫作為數據持久化,如Oracle、MS SQL Server、MySQL等等。
(2)數據處理層。這是數據的邏輯處理器,主要負責數據的存取操作,對上層提供統一的數據訪問接口,屏蔽下層數據庫的存取操作差異。任何對數據庫的操作都必須通過該層的接口實現。
(3)數據訪問層。這是面向UI應用的接口層.實現對不同種類的UI應用提供統一的接口調用方式。
云端的這三個層次結構可以有效地消除底層數據庫對上層應用的影響,以適應不同企業對數據存儲的要求。同時也為各種不同的應用模式提供統一的調用方式,提高了系統的擴展能力。
(4)客戶端。這是提供給用戶訪問云端數據的操作界面。根據設備的不同又分為智能終端App應用和Web網站應用。智能終端App應用使用的是Native App原生系統的開發模式。原因是系統需要讀取設備的某些硬件信息,因此不適合使用基于網頁的Web App開發模式。Web網站應用模式是為了讓系統有更好的擴展性和延伸性。例如用戶可以通過電腦或智能終端的瀏覽器使用本系統。另外筆者已經把Web網站應用接人微信平臺,通過微信,用戶便可使用該系統,這樣有效提高了系統的使用率。
(5)管理端。這是提供給管理員對云端數據進行統一管理的操作界面。這里主要以Web訪問方式為主。
整個系統的架構如圖1所示。
2 實現方法
2.1 數據存儲層
這里選擇MS SQL Server 2008作為數據庫。該數據庫可以將結構化、半結構化和非結構化文檔的數據(例如圖像和音樂)直接存儲到數據庫中,并提供一系列豐富的集成服務,可以對數據進行查詢、搜索、同步、報告和分析等操作,另外數據可以存儲在服務器、PC機、移動設備等各種設備上。
系統共設計了9張數據表,用于存放用戶、部門、電話和日志等信息。
Departments部門信息表
該表用于保存企業的組織和部門架構信息。其中OID為系統分配的部門編號;ParentID記錄其直屬上級部門的OID值,如果沒有上級部門則此字段值為0;DepartmentID是由各企業自行編制的編號,主要目的是用于與其他系統同步信息。整個表的結構如表1所示。
Users用戶信息表
該表用于保存用戶的基本信息,每個用戶占用一行。其中DepartmentID記錄用戶所在部門的部門編號,取自于Departments表的OID值。另外考慮到各個企業都有自己的中央認證系統,因此本系統在用戶登錄認證方面直接調用第三方的用戶認證接口,所以在用戶信息表中沒有設計用戶密碼字段。整個表的結構如表2所示。endprint
Telephones電話號碼表
該表用于保存用戶的電話號碼信息,每個電話號碼占用一行,每個用戶可以有多條記錄。其中PhoneType標識該記錄的電話號碼是手機還是固定電話,如果為手機則填m,如果為固定電話則填t。整個表的結構如表3所示。
SimCard手機Sim卡信息表
該表用于記錄用戶的Sim卡信息,以便判斷用戶是否更換了手機卡。其中UserOID表示用戶的系統編號,取之于Users表的OID值。整個表的結構如表4所示。
Managers管理員信息表
該表用于記錄系統管理員信息。其中保存的密碼信息必須進行加密存儲。整個表的結構如表5所示。
DataChangelnfo數據修改信息
該表用于存放數據修改信息。其中TableName表示被修改的表名稱,RecordOID表示所修改的記錄的OID值,Action表示修改動作,插入用i表示,更新用u表示,刪除用d表示。整個表的結構如表6所示。
DepartmentsLog部門信息修改日志表
該表用于記錄部門信息的修改日志,即記錄某條記錄被修改前的原始信息,以便追蹤數據的修改歷史,并在發生錯誤時能恢復原始數據。其中Action表示記錄的操作類型,插入用i表示,更新用u表示,刪除用d表示。整個表的結構如表7所示。
UsersLog用戶信息修改日志表
該表用于記錄用戶信息的修改日志,作用與DepartmentsLog類似。整個表的結構如表8所示。
TelephonesLog電話號碼修改日志表
該表用于記錄電話號碼信息的修改日志,作用同樣類似于表DepartmentsLog。整個表的結構如表9所示。
另外,客戶端系統是通過讀取DataChangelnfo表的信息來感知需要同步的數據并下載對應的信息。各數據表的修改信息是通過各表的Insert、Update和Delete觸發器來收集的。這樣做的優點是處理起來比較簡單,簡化了上層應用的開發。由于這里三個觸發器要完成的任務都是記錄哪個表的哪個記錄進行了哪項操作,因此這里把三個觸發器的代碼寫在一起。接下來就是判斷當前是觸發了Insert、Update還是Delete操作。邏輯上的判斷是:如果存在inserted表,但不存在deleted表,則此時為Insert操作;如果同時存在inserted表和deleted表,則此時為Update操作;如果不存在inserted表,但存在deleted表,則此時為Delete操作。然后,如果是Update或Delete操作,則要先刪除該記錄的舊的修改信息,因為用戶只需下載該記錄的最終版本,因此舊的修改信息就可以刪除掉。最后是把原始的記錄登記在對應的日志表中,然后在DataChangelnfo表中登記該記錄當前的操作類型。其核心代碼如下。
判斷當前是何種操作
IF EXISTS(SELECT l FROM inserted) AND NOT EXISTS(SELECT l FROM deleted)
BEGIN
SET CIAction 2'i'
SELECT ClOID 2 0ID FROM INSERTED
END
ELSE IF EXISTS(SELECT l FROM inserted) AND EXISTS(SELECT l FROM deleted)
BEGIN
SET CIAction='u'
SELECT @OID=0ID FROM INSERTED
END
ELSE IF NOT EXISTS(SELECT l FROM inserted) AND EXISTS(SELECT l FROM deleted)
BEGIN
SET @Action ='d'
SELECT @OID=0ID FROM DELETED
END
一如果是Update或Delete操作,則刪除舊的修改日志
IF @Action<>il
BEGIN
INSERT INTO TelephonesLog
([Action], OID, UsersOID, PhoneType, PhoneNumber)
SELECT @Action, OID, UsersOID, PhoneType, PhoneNumber FROM DELETED
DELETE FROM DataChangelnfo
WHERE TableName=@TableName
AND RecordOID=@OID
END
——記錄當前的修改的日志
INSERT INTO DataChangelnfo
(TableName, RecordOID, [Action])
VALUES
(@TableName,@OID,@Action)
2.2 數據處理層
由于不同的數據庫其存取操作存在一定的差異,考慮到不同的企業所使用的數據庫不盡相同,為了提高系統的適應能力,筆者首先設計了一套函數接口,然后因應不同的數據庫再編寫對應的操作類,而這些類繼承上面的接口。這樣就可以為數據訪問層提供統一的接口函數,同時又屏蔽了數據存儲層的操作差異。
例如用戶管理模塊。系統首先設計了類庫DBControllerlnterface,里面聲明了IUsersController接口,該接口包含了對用戶數據操作的所有函數聲明。如下面的代碼所示。endprint
name space AddressBo ok.DB Controllerlnterface
{
///
///用戶管理接口
///
public interface IUsersController
{
,//
///根據賬號獲取用戶ID和姓名
///
///賬號< /param>
///用戶ID
///姓名
///
bool GetUserlnfo(string account, out int userOID, out string userName);
///
///根據手機號碼獲取用戶ID
///
///手機號碼
///用戶ID
///
bool GetUserlnfo(string phoneNumber, out int userOID);
///
///檢查是否存在某個賬號
///
///賬號< /param>
///
bo ol IsExistAccount(string account);
///
///檢查是否存在某個用戶ID
///
///用戶ID
///
bool IsExistUserOID(int userOID);
///
///增加用戶
///
///賬號
///姓名
///部門編號
///
int Insert(string account, string userName, int departmentID);
///
///修改鳧戶
///
///用戶ID
///部門編號
///
int Update(int oID, string userName, int departmentID);
///
/// Anil除用戶
///
///用戶 ID
///
int Delete(int oID);
///
///獲取所有用戶的基本信息
///
///
DataTable GetAllUsers();
///
///獲取某個部門的用戶基本信息
///
///部門編號
///分頁索引
///分頁大小
///總記錄數
///
DataTable GetDepartmentUsers(int departmentID, int pageldx, int pageSize, out int recordCount);
}
}
接著系統創建了類庫SQLDBController,這是實現對SQL Server數據庫操作的,里面實現了UsersController類,該類繼承上面的IUsersController接口并實現其方法。其核心代碼如下。
name space Addres sBo ok. SQLDB Co ntroller
{
public class UsersController: IUsersController
{
public bool GetUserlnfo(string account, out int userOID, out string userName)
{
using (AddressBookEntities db=new AddressBookEntities(》
{
var data= (from record in db.Users
where record.Account==account
select record).FirstOrDefault
if (data!=null)
{
userOID=data.OID;
userName=data.UserName;
return true;
}
else
{
userOID=0:
userName=string.Empty;
return false;
}
}
}
//其它對IUsersController接口函數的具體實現
}
}
這里使用了ADO.NET實體數據模型來連接數據庫。通過該模型可以很方便的與底層數據庫進行強類型的數據互操作,既方便了系統的設計也提高了數據庫操作的安全性。另外對于查詢到的數據集合,需要轉換為DataTable類型對象,目的是便于數據訪問層將其轉換為JSON數據格式,因此這里使用了另一個自定義函數ConvertToDataTable。該函數是根據數據集創建數據表,然后再進行數據填充。轉換時有一個需要注意的地方就是,通過ADO.NET實體數據模型查詢到的數據集是包含外鍵關聯表信息的,而且是作為一個獨立的字段存在,而在這里該值是不需要的,因此進行數據轉換時,需要先檢測數據的類型是否為System.Data.EntityKey或System.Data.EntityState,如果是則丟棄該信息。其核心代碼如下。
public class Common
{
public static DataTable ConvertToDataTable
{
DataTable table=new DataTable();
ff字段名稱
Propertylnfo[] oProps= null;
if (varlist==null) return table;
foreach(T rec in varlist)
{
if (oProps==null)
{
oProps=《Type)rec.GetType(》.GetProperties();
foreach (Propertylnfo piin oProps)
{
Type colType=pi.PropertyType;
//去除外鍵關聯表
if (colType.FullName.Co ntains("AddressBo ok.SQLDBHelper"))co ntinue;
if《colType.FullName=="System.Data.EntityKey") II (colType.FullName=="System.Data.EntityState"》
continue;
if《colType.IsGenericType) && (colType.GetGenericTypeDefinitio n() ==typeof(Nullable<》》
{
colType=colType.GetGenericArguments() [0];
}
table.Columns.Add(new DataColumn(pi.Name, colType》;
}
}
DataRow row= table.NewRow();
foreach (Propertylnfo piin oProps)
{
//去除外鍵關聯表
if (pi.PropertyType.FullName.Co ntains(”AddressBo ok. SQLDBHelper.”))co ntinue;
if《pi.PropertyType.FullName="System.Data.EntityKey")||(pi.PropertyType.FullName=="System.Data.EntityState"》
co ntinue:
row[pi.Name]=pi.GetValue(rec, null)==null? DBNull.Value: pi.GetValue(rec, null);
}
table.Rows.Add(row);
}
return table:
}
}
類似的,再創建對Oracle數據庫操作的OracleDBController類庫,里面同樣實現了UsersController類,同樣該類也繼承IUsersController接口并實現其方法。要注意的是,如果使用ADO.NET實體數據模型來連接Oracle數據庫,需要先安裝Oracle Data Provider for .NET (ODP.NET)驅動程序。其他的操作和代碼與操作SQL Server數據庫的類似,這里就不再贅述。
這三個類庫以及類和接口的繼承關系如圖2所示。這樣數據訪問層只要聲明IUsersController接口變量,就可實現對SQL Server和Oracle數據庫的存取操作,而不需要考慮具體的底層數據庫的類型。同樣如果需要使用其它數據庫也可以按相同的方式進行編寫。
2.3 數據訪問層
為了統一各種UI應用的調用方式,該層采用了HJO(HTTP協議+JSON格式+OAuth2.0認證)架構模式。
HTTP協議(HypertextTransfer Protocol)是一個客戶端和服務器端請求和應答的標準,它是無狀態的應用層協議,由于其簡捷、快速的方式,因此特別適合于分布式超媒體信息系統的應用。因此,本系統可以直接把該層部署在IIS服務器上,使用Windows Server的Web服務,這樣即方便了系統的開發,也方便了系統的部署,同時由于HTTP協議是使用標準的80端口,因此也無需對網絡防火墻進行特殊的配置。
JSON(JavaScript Object Notation)是一種輕量級的數據交換格式,它較XML有更高的傳輸效率,同一個數據使用JSON格式傳輸的數據量要比XML格式小很多。例如一條用戶信息,使用JSON格式表示如下,只需166個字符。
[
{
"Account":"moc".
"UserName":"Micheal O'Ciardubhain".
"DepartmentID":41,
"DepartmentName":”應用外語系”,
"PhoneType":"m",
"PhoneNumber":"1 8926549871".
"OID":1003,
"UserOID":5015
}
]
而同樣的記錄使用XML格式來表示,如下所示,卻需要330個字符,所占用的空間是JSON格式的兩倍。
<?xml version="1.0"standalone="yes"?>
對當前的移動應用來說,用戶對數據傳輸所占帶寬還是比較敏感的,而通過使用JSON格式,可以有效減少數據傳輸量,節省用戶帶寬。因此當前特別適合使用JSON來作為移動應用的數據傳輸格式。
OAuth(Open Authorization)是一個開放標準,允許用戶讓第三方應用訪問該用戶在某一網站上存儲的私密資源(如照片,視頻,聯系人列表),而無需將用戶名和密碼提供給第三方應用。而OAuth2.0是OAuth協議的下一版本,它關注客戶端開發者的簡易性,同時為Web應用、桌面應用、手機和起居室設備提供專門的認證流程。
OAuthl.0的認證流程如下:
(1)客戶端向服務器端請求臨時令牌(Temp Token);
(2)客戶端使用返回的Temp Token向服務器端請求認證令牌(Auth Token);
(3)客戶端使用返回的Auth Token向服務器端獲取訪問令牌(Access Token);
(4)客戶端使用返回的Access Token訪問服務器上的接口。
相比之下OAuth2.0的認證流程簡化如下:
(1)客戶端向服務器端請求授權碼(Auth Code);
(2)客戶端使用返回的Auth Code向服務器端請求訪問令牌(Access Token);
(3)客戶端使用返回的Access Token訪問服務器上的接口。
通過上面的流程可以看到,OAuth2.0節省了OAuthl.0中獲取臨時令牌的環節,另外出于安全考慮OAuth2.0中的授權碼是有有效期的。另外OAuthl.0中每個令牌都需要加密,而OAuth2.0則通過使用https協議簡化了這一步驟,這樣服務器端和客戶端代碼都得到了簡化,而且安全性更高。此外OAuth2.0考慮到客戶端的多樣性,因此對獲取訪問令牌提供了多種途徑,如授權碼、客戶端私有證書、資源擁有者密碼證書、斷言證書等等。因此本系統選擇使用OAuth2.0作為認證方式。endprint
通過上面的架構,即可把數據處理層提供的函數調用轉換為HTIP調用,這樣不管是傳統的Web網站還是新興的移動應用,都可以方便、安全地使用這些接口。
下面以用戶管理模塊為例進行詳細的說明。
系統首先設計了Credential類,用于實現OAuth2.0認證。該類主要包括檢查請求的鏈接是否使用HTTPS協議,產生Access Token值,校驗Access Token值等功能,關鍵的地方是產生Access Token值。為了防止重現攻擊,Access Token必須具有有效期,因此該值包含時間信息;另外系統還對Access Token進行了數字簽名,目的是防止信息被非法篡改和假冒。其核心代碼如下。
public static string GetAccessToken(string authKey)
{
if (authKey!=Config.Security.AuthKey) return string.Empty;
string rndString=FSMCrypt.FSMHash.GetRando mString(Config. Security.Rando mStringSize);
string hash= FSMCrypt.FSMHash.MD5(rndString, Config.Security.SALT);
string now=DateTime.Now.ToString();
string sourceString=string.Format(“{0};{1};{2}”,rndString,now, hash);
using (FSMCrypt.FSMEncryption crypt= new FSMCrypt.FSMEncryption(》
{
return
HttpUtility.UrlE nco de(c rypt.Enc rypt2(F SMCrypt.Enc ryptio nAlgo rithm.TripleDes,sourceString。
Config.Security.KEY, Config.Security.IV false, false》;
}
}
接著系統使用ASP.NET頁面作為接收服務請求的通道,這樣做的好處是可以更好地兼容桌面開發和移動應用開發。按照OAuth2.0的流程,每個頁面的服務流程都是相同的,因此系統抽象出BasePage類,作為所有服務頁面的基類。在BasePage類的Page_Lo ad事件中系統先檢查當前是否使用HTTPS鏈接,然后再檢查Access Token是否合法,都通過后再執行抽象方法Analyze。每個繼承BasePage類的服務頁面都需要實現Analyze方法,這是每個服務頁面具體的服務功能。BasePage類的Page_Load事件的代碼如下。
protected virtual void Page_Load(object sender, EventArgs e)
{
if (lAllowConnect(》
return;
else
Analyze();
}
其中AllowConnect函數就是用于檢測當前請求是否使用了HTTPS鏈接,以及對Access Token進行合法性校驗的。
前面的數據處理層因應不同的數據庫設計了不同的數據處理模塊,而對于服務頁面就要根據相應的配置參數對接口進行實例化。為此在該層,系統實現了DB ControllerFactory工廠類,該類會自動根據配置參數產生相應的數據控制對象實例。例如要實例化上面的IUsersController接口,DBControllerFactory類會執行CreateUsersController函數,該函數會根據配置參數生成SQLDBController.UsersController實例或OracleDB Controller.UsersController實例。其核心代碼如下。
public class DBControllerFactory
{
public static IUsersController CreateUsersController()
{
//獲取配置是數據庫類型
Config.DBStyle dbStyle=Config.GetDBStyle();
//根據配置參數返回相應的對象實例
switch (dbStyle)
{
case Config.DBStyle.SQLSERVER:
return new SQLDBController.UsersController();
case Config.DBStyle.ORACLE:
return new OracleDB Co ntroller.UsersCo ntroller();
default:
return null;
}
}
}
而服務頁面對接口進行實例化時,只需調用DBControllerFactory類的相應方法即可。例如要實例化IUsersController接口,其代碼如下。
IUsersController users Co ntroller= DB Co ntrollerFactory.CreateUsersController();endprint
這樣不管使用哪類數據庫,都無需修改任何代碼,只要修改配置參數即可,有效提高了系統的適應能力和可擴展能力。
2.4 客戶端
2.4.1 智能終端App應用
智能終端App應用使用了離線數據同步技術,實現了App的離線使用和數據的自動同步。這里采用了SQLite數據庫作為離線數據的存儲服務。SQLite是一款輕型的數據庫,是遵守ACID的關系型數據庫管理系統,具有輕量級、單一文件存儲、跨平臺、可移植的特性,非常適合嵌入式系統。而且iOS、Android和Windows Phone系統中都有相應的類庫支持,使用起來非常方便。
作為離線存儲,客戶端只需要保存部門信息、用戶信息、電話號碼信息和數據修改信息即可,對應的就是Departments、Users、Telephones和DataChangelnfo這四個表,其他表的修改日志無需存儲。這四個表的結構與數據存儲層中的表結構相同,這里就不再贅述。
智能終端App的主要功能如圖3所示。
(1)登錄。考慮到各個企業基本上都有自己的中央認證系統,因此這里可以使用企業自己的認證接口。另外,為了免除用戶每次都要輸入認證信息,系統還實現了自動登錄功能。在首次登錄時可以選擇下次是否自動登錄,若已選擇,則第一次登錄成功后,系統會把用戶的相關信息保存到本地,下次打開客戶端時,系統會先檢查本地是否存有用戶信息,若有則再檢查賬號是否異常,如果正常則進入系統,否則跳轉到登錄界面等待用戶登錄。其登錄的流程如圖4所示。
其中“檢查賬號是否異常”的目的是確認服務端沒有暫停或刪除該賬號。另外除了登錄之外,在用戶使用其他功能之前,系統都會進行賬號異常檢查,以提高服務端對賬號的控制能力。
(2)瀏覽通訊錄。用戶可以按組織架構來查閱用戶信息。對查詢到的信息可以直接撥打電話或發送短信。為了留給用戶更多的控制權,用戶點擊撥打電話或發送短信時,系統只是打開撥號軟件或短信發送軟件,然后自動輸入接收者的電話號碼,并沒有撥打電話或發送短信,這樣用戶可以根據需要進行調整,例如是否使用IP撥號等等。
(3)查詢通訊錄。用戶可以按電話、姓名、賬號或部門等條件來快速搜索用戶信息。同樣對搜索到的信息可以直接撥打電話或發送短信。為了減少用戶的輸入量,在輸入查詢條件時,系統支持自動完成功能。例如輸入王字,則會自動列出所有姓王的列表讓用戶選擇。另外系統還支持模糊查詢,例如輸入8632,則系統會查詢所有電話號碼以8632開頭的信息。
(4)個人通訊錄。通過該功能用戶可以增、刪、改自己的通訊錄。修改后,數據會自動同步到云端,然后其他用戶會自動下載此更新信息。為方便用戶在更換手機卡后及時更新通訊錄,系統實現了自動檢測功能。當發現手機卡更換后會及時提醒用戶,如圖5所示。另外考慮到當下有不少用戶有多臺手機多個聯系電話,因此本系統對用戶的聯系方式沒有數量上的限制,不論有多少個聯系電話都可以添加進去。
(5)來電提示。來電提示是本系統的一大特色。當有來電時系統會查詢來電者的信息,如果來電號碼只對應一個人,則顯示其姓名和所在部門,如若對應多個人(如來電號碼是某個辦公室的公共電話)則只顯示電話號碼對應的部門名稱。如圖6所示。如果用戶沒有接通來電,系統還會記錄來電者的信息,以便查看漏接的電話是哪個部門的哪位同事在哪個時間打來的
對于來電號碼的查詢需要注意以下問題。如果是同城的電話號碼,用戶在系統中登記固定電話時,一般是不會登記長途區號的,這是一種普遍的習慣,但是來電號碼中卻是包含長途區號的。另外我國的長途區號有3位、4位和5位,例如北京是010,深圳是0755,由于位數的不統一,因此處理起來比較繁瑣。但是有一點相同的是,長途區號都是以0開頭的。而對于手機來電,只會直接顯示11位的號碼,即使是長途,也不會在前面加0。因此可以斷言,對于國內的電話,如果來電號碼是以0開頭的,則必定是固話,否則就是手機號碼。為此檢查來電的邏輯如下:首先查詢系統中是否存在該完整的來電號碼,如果有則顯示對應信息,否則檢查該號碼是否以0開頭,如果不是則退出,否則先去掉前3位再檢查,如果依然無果則去掉前4位再檢查,如此重復,直至找到此號碼或剩下的號碼長度小于3位為止。剩下的號碼長度小于3位的原因是,我國的電話號碼是沒有小于3位的。在Android系統下的核心代碼如下所示。
//查詢電話號碼信息
String info=usersTelephoneViewController.getUserInfo(phoneNumber);
//找不到該電話號碼信息
if (info.isEmpty(》{
//判斷是否為固話
if (phoneNumber.startsWith(“0”)){
//去掉長途區號再找
String number= phoneNumber.substring(3);
while《info=usersTelephoneViewController.getUserInfo(number》.isEmpty()
&& (number.length()>3》{
number= number.substring(l);
}
}
}
if (linfo.isEmpty(》
popWindow(info+“\r\n”+phoneNumber);
} else{
removeWindow();
}
(6)參數設置。包括設置是否啟用來電提示,設置軟件和通訊錄更新方式等等。這樣用戶可以選擇在哪種聯網狀態下才檢查軟件和通訊錄更新,以避免消耗用戶的上網流量。endprint
(7)自動同步通訊錄。在設定的聯網狀態下,系統會啟用后臺線程,對比本地通訊錄與云端的數據是否有差異,如有差異,則自動下載差異的數據并更新本地信息。由于差異的數據通常不多,因此同步所消耗的流量也是非常有限的。另外此過程是自動的,對于用戶完全透明,不需要人工干預。
前面已提到,數據更新的信息是在數據庫的觸發器中記錄的,因此客戶端只需通過對比本地的數據版本號和服務器端的數據版本號即可獲知是否有數據需要更新。這里取DataChangelnfo表中字段OID的值作為數據版本號,只要客戶端的數據版本號小于服務器端的數據版本號,則客戶端就會讀取DataChangelnfo表中所有大于客戶端數據版本號的記錄,然后根據所記錄的操作類型再從對應的數據表中獲取更新信息或刪除本地的某條記錄,這樣就實現了差異數據的更新操作。
(8)系統更新。與自動同步通訊錄相同,在設定的聯網狀態下,后臺線程會檢查系統是否有新版本,若有則提示用戶進行更新。客戶端軟件都有版本號,只要對比本地的軟件版本號和服務器發布的版本號即可獲知是否有更新。
2.4.2 Web網站應用
Web網站應用以網頁的形式給用戶提供服務,其擴展性非常好。例如可以嵌入各企業的門戶平臺,可以接人微信平臺等等。但由于Web方式無法獲取某些設備信息,所以此模式下無法實現手機卡檢測、來電提示等特殊功能。另外Web方式只能實時獲取數據,因此無法離線使用。除此之外,其他的功能與智能終端App應用方式相同。另外由于該Web網站要同時兼容PC模式和移動模式,因此在開發時需要在頁面中添加聲明
2.5 管理端
管理端也是以網頁形式提供服務。主要是供管理員對通訊錄信息進行增、刪、改等操作,也就是通過調用數據訪問層的接口函數實現對數據信息的處理。同樣為了讓系統同時兼容PC模式和移動模式,也需要在頁面中添加上面的聲明語句。
3 結論
目前,筆者已經成功研發了這套以云計算技術為基礎,以HJO(HTTP+JSON+OAuth)為架構的企業共享型移動通訊錄,并已獲得國家軟件著作權授權。系統在筆者單位使用后受到了用戶的好評。
本系統實現了通訊錄信息的高度共享和自主管理的能力。用戶能在不同的地點使用各種終端(如手機、平板電腦、PC機等)獲取云端的數據信息。借助移動終端隨身攜帶的特點,結合云計算技術,系統突破了時間和地域的限制,讓每個用戶能夠隨時隨地地維護自己的信息,充分顯現移動應用的便捷性,另外還提高了數據的時效性、準確性、可靠性和可用性,減輕了企業對員工通訊錄信息的維護工作量,降低了維護成本,提高了維護的效率。利用來電提示功能,用戶不需要維護手機本身的通訊錄,也能對同事的來電一目了然;使用離線數據同步技術方便了用戶離線使用,節省了通訊流量,這些都給使用者帶來了更好的用戶體驗。由于系統使用了HJO架構,因此具有良好的擴展能力,后續該系統可以擴展為多企業的數據共享,甚至是以行業或地區為基礎的數據共享。例如餐飲業,系統可以匯集各商家的聯系方式,同時商家也可自行維護自己的信息,用戶通過本系統即可以迅速查找所需餐廳的聯系方式,這樣即方便商家推廣也方便了用戶的使用。