Làm việc với Worklight, Phần 2: Phát triển các mô đun có cấu trúc và sử dụng tính năng Encrypted Offline Cache trong IBM Worklight

Phân tầng ứng dụng di động của bạn về cấu trúc, chức năng và bảo mật

Loạt bài này giới thiệu nền tảng IBM® Worklight® (Worklight của IBM) thông qua việc cho thấy cách bạn có thể xây dựng các ứng dụng di động sử dụng một loạt các sản phẩm phần mềm của IBM. Phần 2 tiếp tục mô tả quá trình phát triển một ứng dụng Worklight, đồng thời đưa ra một số hướng dẫn thực hành tốt nhất để xây dựng các ứng dụng lai và đề cao tính năng EOC (Encrypted Offline Cache – Bộ nhớ đệm ngắt tuyến được mã hóa) của Worklight.

Carlos Andreu , Nhà phát triển phần mềm, IBM

Carlos Andreu là một nhà phát triển phần mềm trong Tập đoàn phần mềm IBM. Công việc hiện tại của ông là tạo các framework để xây dựng các ứng dụng Hybrid, Android và iOS. Phạm vi quan tâm của ông trải rộng từ việc theo đuổi các xu hướng và các blog công nghệ mới nhất, đến đọc sách, xem truyền hình và thưởng thức tất cả các thể loại âm nhạc. Bạn có thể tìm hiểu thêm về ông tại địa chỉ http://dev.yapr.org/carlosandreu.



Jeremy Nortey, Nhà phát triển phần mềm, IBM

Jeremy Nortey là một nhà phát triển phần mềm cho Quỹ di động của IBM trong Tập đoàn phần mềm. Ông phát triển phần mềm và bảo đảm chất lượng cho các giải pháp di động. Ông chuyên về iOS và học xây dựng các ứng dụng nguyên bản cho iPhone trong thời gian rãnh rỗi. Ông thích bóng đá và chạy bộ.



Raj Balasubramanian, Kiến trúc sư sản phẩm, IBM

Raj Balasubramanian là một tư vấn viên về kiến trúc CNTT cho Tập đoàn phần mềm IBM. Ông làm về ứng dụng phân phối các cam kết khách hàng và các dự án liên quan đến cơ sở hạ tầng. Các mối quan tâm của ông trải rộng từ bất cứ thứ gì về kỹ thuật cho đến lịch sử và vật lý. Trong những lúc rảnh rỗi của mình, ông thích hẹn hò với vợ và nói chuyện về người máy với các con trai của mình. Bạn có thể đọc về các cuộc phiêu lưu cá nhân và kỹ thuật của ông trên blog Gurukulam.



25 02 2013

Giới thiệu

Worklight của IBM, một phần của Quỹ di động của IBM (IBM Mobile Foundation) cung cấp một nền tảng vững mạnh để nhanh chóng xây dựng các ứng dụng di động, bằng cách sử dụng các công nghệ dựa trên web có thể chạy trên nhiều nền tảng thiết bị. Bài này nhặt ra những điểm mà Phần 1 đã để lại trong quá trình phát triển một ứng dụng di động độc lập, đủ chức năng, tên là "Todo", cho phép một người dùng di động xây dựng và duy trì một danh sách các công việc cần làm. Trong quá trình này, bạn sẽ tìm hiểu về Encrypted Offline Cache, một biện pháp bảo mật của thời gian chạy máy khách Worklight để bảo vệ thông tin nhạy cảm khỏi các cuộc tấn công của phần mềm độc hại và các thiết bị nghe lén.

Bạn hãy tải về Worklight

Tải về phiên bản dành cho nhà phát triển IBM Worklight Developer Edition 5.0 miễn phí và sử dụng vô thời hạn!

Bây giờ, bạn cần có IBM Worklight Studio được cài đặt trong môi trường phát triển tích hợp (IDE) Eclipse của mình và bạn cần biết rõ về cách triển khai một ứng dụng kiểu "Hello World" đơn giản trên iOS và Android. Chúng ta sẽ bắt đầu với ứng dụng Todo mà bạn đã bắt đầu phát triển trong Phần 1. Tải ứng dụng ban đầu mà bạn tạo ra trong Phần 1 và thêm nó vào môi trường phát triển Worklight Studio của bạn. (Một cách khác là bạn có thể tải về các tệp dự án ứng dụng Todo có kèm theo bài này).


Phát triển ứng dụng

Sử dụng ứng dụng ví dụ mẫu

Ứng dụng ví dụ mẫu mô tả ở đây được trình bày như một bài tập chỉ dùng cho mục đích làm ví dụ. Vì phần lớn logic ứng dụng sẽ có trong JavaScript™ (cụ thể là sử dụng JQuery), nên các hướng dẫn thực hành tốt nhất trong việc cấu trúc logic ứng dụng để có tính dễ đọc, độ tin cậy và tính nhất quán tốt hơn sẽ được nêu bật, cũng như các hướng dẫn thực hành liên quan đến việc sử dụng namespace và nhiều hơn nữa.

Hình 1 minh họa luồng chung của người dùng đang chạy ứng dụng di động Todo. Tóm tắt các bước người dùng thường làm như sau:

  1. Mở ứng dụng.
  2. Nhập mật khẩu để lưu trữ an toàn dữ liệu ngắt tuyến (offline) và gõ nhẹ lên Start để chuyển sang ô cửa sổ thứ hai.
  3. Nhập bất kỳ văn bản nào đại diện cho một mục "to do" (việc cần làm) vào trong trường đầu tiên, rồi thêm nó vào danh sách bằng cách gõ nhẹ lên nút Add Item (Thêm mục).
  4. Đánh dấu một mục là "done" (đã thực hiện) bằng cách gõ nhẹ lên mục đó trong danh sách, làm cho nó được chọn. Gõ nhẹ lên Remove Done (Hủy bỏ mục đã thực hiện) để xóa tất cả các mục được đánh dấu là đã thực hiện.
  5. Lọc các mục được hiển thị trên ô cửa sổ bằng cách gõ tất cả hoặc một phần tên của một mục bên trong trường văn bản thứ hai, sau đó gõ nhẹ lên Filter Items... (Lọc các mục...).
Hình 1. Các ô cửa sổ ứng dụng ví dụ mẫu
Hình 1. Các ô cửa sổ ứng dụng ví dụ mẫu

Bước đầu tiên của bạn trong việc thêm chức năng này vào ứng dụng của mình là chia mã của bạn thành các mô đun có các trách nhiệm cụ thể trong ứng dụng đó. Todo sẽ có các mô đun sau (Hình 2):

  • Mô đun Hằng số (Constant module) nhận và thiết lập các hằng số khác nhau mà bạn sẽ sử dụng trong ứng dụng của mình.
  • Mô đun Danh sách (List module) chịu trách nhiệm lưu trữ danh sách cho phiên làm việc hiện tại và xử lý các sự kiện, chẳng hạn như thêm một mục mới vào danh sách, đánh dấu các mục là đã thực hiện và loại bỏ các mục được đánh dấu là đã thực hiện.
  • Mô đun Che phủ (Vault module) được giao nhiệm vụ mã hóa và giải mã danh sách. Đây là nơi bạn sẽ sử dụng tính năng Encrypted Offline Cache của Worklight.
Hình 2. Các mô đun và các tương tác của chúng
Hình 2. Các mô đun và các tương tác của chúng

Để cấu trúc mã của mình, bạn sẽ sử dụng Module Pattern (Mẫu mô đun) chung và phổ biến, từ thế giới JavaScript (xem phần Tài nguyên). Liệt kê 1 cho thấy bộ khung của một mô đun. Bạn gán một hàm chạy tự động (hoặc hàm tức thời - immediate function) cho một đối tượng (Module1) nằm trong namespace của bạn (MYAPP). Một ý tưởng tốt là chuyển cho nó những thứ như đối tượng chung (cửa sổ, đối với hầu hết JavaScript phía máy khách) và các thư viện của nhà cung cấp (như jQuery, vì vậy bạn có thể sử dụng $ bên trong mô đun của mình, ngay cả khi có cái gì khác sử dụng $ bên ngoài mô đun này, như là Prototype.js hoặc thư viện khác). Một hướng dẫn thực hành tốt nữa là liệt kê các phụ thuộc và gán các biến cục bộ cho các phụ thuộc của bạn vì truy cập các biến địa phương sẽ nhanh hơn là tìm kiếm các cặp giá trị khóa.

Ví dụ:

var eoc = WL.EncryptedCache; eoc.open()

sẽ tốt hơn so với dùng JavaScript tìm kiếm đối tượng WL và sau đó tìm kiếm khóa EncryptedCache trỏ đến một đối tượng khác có chứa hàm open mà bạn muốn gọi mỗi khi bạn cần gọi hàm đó bên trong một mô đun nào đó của mình.

Liệt kê 1. Bộ khung của Module Pattern
MYAPP.Module1 = (function (global, $) { 
//List dependencies: jQuery 1.7.2

//List private variables

//List private functions
var _init = function () {
console.log("I'm ready!");
}

//List one time initialization procedures 

//public API
return {
init : _init
};

}(window, jQuery)); //MYAPP.Module1

Đây là một điểm tốt để đưa ra một số quy ước về kiểu dáng thông minh. Các ký tự viết hoa được sử dụng trong các mẫu mã này dùng cho các hằng số và các ký tự gạch dưới được thêm vào phía trước các hàm riêng để phân biệt với các biến private. Bạn có thể mở rộng quy ước này để sử dụng "mẫu var đơn lẻ", trong đó một biến (var) đơn lẻ được khai báo ở phần đầu của mỗi hàm yêu cầu các biến. Điều này được thực hiện vì JavaScript sẽ "nhấc" các biến lên phần đầu khi mã được thực thi (Liệt kê 2) và vì đôi khi việc quên sử dụng var tạo ra các kết quả không mong muốn, chẳng hạn như ghi đè lên một biến chung (global) cùng tên.

Liệt kê 2. Ví dụ về nhấc biến lên
//Example of Hoisting 
myname = "global";

function func() {
alert(myname); //returns: "undefined" 
var myname = "local";
alert(myname); //returns: "local"

Có một cấu kiện cơ bản được gọi là bao đóng (closure), cung cấp các mô đun (xem phần Tài nguyên). Trong JavaScript, bao đóng đề cập đến một biến cục bộ dành cho một hàm mà vẫn còn tiếp tục sống sau khi hàm đã trả kết quả về. Điều này liên quan chặt chẽ đến việc quy định phạm vi trong JavaScript, được định nghĩa theo hàm. Ví dụ, Liệt kê 1 cho bạn thấy một ví dụ về bao đóng đang hoạt động. Ở đây, hàm _init là một hàm riêng không thể truy cập bên ngoài hàm chạy tự động đã gán cho MYAPP.Module1, nhưng bạn trả về một đối tượng có một tham chiếu đến hàm riêng đó; theo cách này, bạn có thể dễ dàng truy cập nó giống như MYAPP.Module1. init (). Điều này có thể được thực hiện là nhờ bao đóng.

JavaScript là một ngôn ngữ lập trình hướng sự kiện, giống như Observer Pattern (Mẫu Trình quan sát) được mô tả trong hầu hết các cuốn sách về các mẫu lập trình. Trong các kịch bản lệnh JavaScript, các sự kiện được khởi động mỗi khi người dùng cuộn, nhấn chuột vào một thẻ HTML hoặc di chuột trên một liên kết, để nêu lên một vài ví dụ. Có thể nghe các sự kiện và bạn có thể bắt đầu các sự kiện riêng của mình.

Tách biệt các mối quan tâm là một hướng dẫn thực hành quan trọng khác cần thực hiện, nó có nghĩa là giữ cho việc đánh dấu, kiểu dáng và logic ứng dụng tách rời nhau. Mã HTML của bạn chỉ cần mô tả cấu trúc ứng dụng của bạn; không nên có các hàm JavaScript nội dòng trong HTML. Bạn có thể đạt được điều này bằng cách sử dụng phong cách mã hóa theo sự kiện, trong đó một phần tử cụ thể sẽ cần có cuộc gọi hàm nội dòng, thì thay vào đó sẽ được theo dõi một sự kiện cụ thể và kích hoạt hành động cần thiết. Điều này cho phép bạn có logic ứng dụng chỉ ở một nơi, trong JavaScript, chứ không ở nhiều nơi trong toàn bộ mã HTML. Tương tự như vậy, bạn nên tránh viết mã HTML như là một phần của JavaScript và sử dụng các khuôn mẫu để thay thế (xem phần Tài nguyên).


Mô đun Hằng số

Hãy bắt đầu bằng cách định nghĩa namespace của bạn (Liệt kê 3). Đối với ứng dụng Todo ví dụ mẫu, hãy gọi namespace của bạn là "TD". Về cơ bản namespace này là một đối tượng sẽ lưu giữ các đối tượng khác, tất cả đều liên quan đến ứng dụng của bạn. Có thể là khi ứng dụng của bạn phát triển thêm, TD đã được định nghĩa trong namespace chung rồi. Sử dụng mẫu var đơn lẻ để tạo ra một đối tượng TD nếu nó vẫn chưa có sẵn. Hàm namespace này sẽ bảo đảm tính nhất quán trong lời gọi phương thức: việc gọi TD.namespace(TD.module1) sẽ thêm một đối tượng có tên là module1 vào TD. Bạn sẽ thấy bạn có thể khai báo namespace TD và sử dụng nó ra sao để xếp tầng các đối tượng trong namespace TD khi cần.

Liệt kê 3. Hàm namespace
/**********************************************************************************
* TD NAMESPACE
**********************************************************************************/
var TD = TD || {};

TD.namespace = function (ns_string) { 
var parts = ns_string.split('.'),
parent = TD, 
i;

// strip redundant leading global 
if (parts[0] === "TD") {
parts = parts.slice(1); 
}

for (i = 0; i < parts.length; i += 1) {
// create a property if it doesn't exist
if (typeof parent[parts[i]] === "undefined") {
parent[parts[i]] = {}; 
}
parent = parent[parts[i]]; 
}

return parent; 
};

Trong Hình 3, bạn có thể thấy rằng TD.Constant (mô đun Hằng số của bạn) không có bất kỳ các thành viên riêng lẻ nào. Nó sẽ chỉ trả về các giá trị thông qua những gì chúng ta sẽ gọi API công cộng (Public API - là một cặp giá trị khóa đơn giản được tạo ra bằng cách sử dụng một đối tượng bằng chữ). Tương tự như vậy khóa các mục Todo (Todo items key) được sử dụng cho Encrypted Offline Cache. Các giá trị mã hóa (encrypt) và giải mã (decrypt) là các giá trị boolean đơn giản mà cuối cùng sẽ nói cho mô đun Che phủ (Vault) của bạn biết liệu bạn có muốn mã hóa hoặc giải mã không.

Hình 3. Các phần tử của các mô đun
Hình 3. Các mô đun và các tương tác của chúng

Mô đun list (danh sách)

Như thể hiện trong Hình 1 và Liệt kê 4, ô cửa sổ thứ hai của ứng dụng này về bản chất là trang chủ của ứng dụng. Nó gồm:

  • Một logo ở đầu trang.
  • Một trường văn bản (id="new-todo") sẽ được sử dụng để thêm các mục mới.
  • Một button để thêm các mục mới (id="add").
  • Một button để xóa tất cả các mục được đánh dấu là đã thực hiện (id="delete").
  • Một danh sách không đánh số thứ tự để nối thêm danh sách mục (id="todo-list").
  • Một thẻ div (id="no_items") để hiển thị văn bản khi danh sách rỗng.

Cũng lưu ý rằng bạn nhận dữ liệu lọc miễn phí bằng cách thêm một thuộc tính data-filter=’true’ vào thẻ <ul> của bạn (xem phần Tài nguyên). (http://jquerymobile.com/demos/1.1.0/docs/lists/index.html).

Liệt kê 4. HTML của ô cửa sổ chính
<!-------------------------- MAIN PAGE  -------------------------->
<div data-role="page" id="main" >

<!-- <div data-role="header"><h1>Todo App</h1></div> -->
<img class="centerimg" src="images/logonobg.png"/>

<div data-role="content" >

<input type="text" name="new-todo" id="new-todo" 
placeholder="Write your tasks here..." />

<div class="controls" data-role="controlgroup" data-type="horizontal">
<a href="#" id="add" data-role="button" data-icon="plus">Add New</a> 
<a href="#" id="delete" data-role="button" data-icon="delete">Delete Done</a>
</div>

<ul id="todo-list" data-role="listview" data-filter="true" data-inset="true" >
</ul><!-- /todo-list -->

<div class="center" id="no_items"></div>

</div>
<!-- /content -->
</div>
<!-- /page -->

Với danh sách công việc của bạn, bạn sẽ lưu trữ các mục trong một mảng danh sách. Ví dụ::

[{content: “myTodo Item 1", done: false},
{content: “myTodo Item 2", done: true}].

Nó chỉ là một mảng đơn giản với các cặp giá trị khóa (các đối tượng JavaScript) có một chuỗi ký tự cho tên mục và một giá trị Boolean để theo dõi xem một mục công việc đã được thực hiện hay chưa.

Như thể hiện trong Hình 3, TD.List (mô đun Danh sách của bạn) chứa một phương thức riêng đã định nghĩa (_encrypt), mà phương thức riêng này sẽ mã hóa danh sách (một mảng riêng gọi là 'list – danh sách') bằng cách gọi phương thức mã hóa của mô đun Vault của bạn từ API công cộng của nó. Bạn cũng có hàm _item_template, là một hàm được tạo ra từ một khuôn mẫu để hiển thị các mục đã định nghĩa trong tài liệu HTML của bạn; bạn cần chuyển cho nó một đối tượng có 'item' dùng cho khóa và một mảng danh sách.

Bài tập

Bạn có thể thực hiện kiểm tra kiểu phức tạp hơn (ví dụ, hãy kiểm tra xem item.done có trả về một giá trị Boolean hay không, kiểm tra xem có là null hay không và v.v).

Hàm riêng _add sẽ kiểm tra xem item.content có không rỗng hoặc không xác định hay không và liệu có một cái gì đó được trả về không khi bạn gọi item.done. Hãy nhớ rằng các biến chưa được gán một giá trị theo mặc định sẽ trả về "không xác định".

Liệt kê 5. Hàm _add
_add =  function (item) {
if (item.content !== 'undefined' && item.done !== 'undefined' && item.content.length > 0)
{
list.push(item);
}
},// add item

Hàm _refresh_list chạy động một hàm ánh xạ trên mảng danh sách và thêm một phần tử mới vào tất cả các đối tượng được lưu trữ trong mảng đó. Phần còn lại của hàm xóa danh sách, nối thêm kết quả của khuôn mẫu được tạo ra dựa trên danh sách đó vào danh sách không đánh số thứ tự (ul) trong HTML và làm mới khung nhìn. Cuộc gọi phương thức sau cùng này là đặc trưng của jQuery Mobile để làm mới kiểu dáng của danh sách đó.

Liệt kê 6. Hàm _refresh_list
_refresh_list = function () {

$.map(list, function (item, i) {
item.index = i;
});

list_ul.empty();
list_ul.append(_item_template({item : list}));
list_ul.listview('refresh');

if (list.length < 1) {
no_items.text('No items.');
} else {
no_items.text('');
}

}; // refresh list

Một bài tập khác

Bạn có thể thay đổi cách tiếp cận này bằng cách sử dụng một cấu trúc dữ liệu khác và một thuật toán khác để tạo ra và theo dõi các ID (mã định danh). Mục đích là không cần sử dụng hàm map để lặp lại qua toàn bộ danh sách rồi tạo ra các ID và không cần xóa rồi nối lại toàn bộ danh sách mỗi khi bạn thêm vào hoặc loại bỏ một mục.

Tiếp theo, bạn sẽ đính kèm các hành động tới các sự kiện. Nếu bạn hiểu rõ về jQuery, bạn có lẽ thường sử dụng để xem hoặc sử dụng các cuộc gọi như bind(), live() và delegate(). Trong ví dụ này, chỉ sử dụng duy nhất hàm, on() vì sau phiên bản jQuery 1.7.0, các phương thức như bind (kết buộc), live (sống) và delegate (ủy quyền) chỉ là các trình bao bọc cho hàm on(). Ngoài ra, $ (this) "được lưu sẵn" vào một biến cục bộ có tên là $this vì, lý tưởng là, bạn muốn sử dụng hàm jQuery đó càng ít càng tốt và hạn chế số lần bạn đi sâu vào DOM (Document Object Model - Mô hình đối tượng tài liệu) vì đó là một hoạt động rất tốn kém. Lưu ý rằng chúng ta bật tắt giá trị boolean để biểu thị liệu mục công việc đó đã được thực hiện hay chưa và thêm vào hoặc loại bỏ một lớp có tên là "done" được định nghĩa trong bản định kiểu (tệp .css). Cuối cùng, bạn dùng hàm encrypt() để mã hóa danh sách để lưu giữ lâu bền, ngay cả khi bạn đóng ứng dụng ngay lập tức sau khi nhấn vào một mục để đánh dấu nó là đã thực hiện.

Liệt kê 7. Các phần đính kèm sự kiện bên trong tệp TD.List
add_btn.on('click', function () {

_add({content : new_item.val(), 
done: false });

new_item.val('');
_refresh_list();

_encrypt();

}); // add btn

list_ul.on('click', 'li', function () {

var $this = $(this),
$item = $this.find('a'),
index = $item.attr('id'), 
current_item = list[index];

current_item.done = !(current_item.done);

if (current_item.done) {
$item.addClass('done');
} else {
$item.removeClass('done');
}

_encrypt();

}); // list item

delete_btn.on('click', function () { 
var i = list.length;

while (i--) {
if (list[i].done) {
list.remove(i);
}
}

_refresh_list();

_encrypt();

});// delete btn

Tương tự, ta cũng xử lý như vậy cho button delete, bạn có thể xem mã thực hiện việc này trong Worklight Studio.

API công cộng dùng cho mô đun List (Danh sách) của bạn rất đơn giản; bạn có thể lấy danh sách hiện tại mà bạn đang làm việc với nó, thiết lập một danh sách mới và làm việc với danh sách mới đó và làm mới danh sách hiện tại vừa thiết lập. Bạn gọi những phương thức này bằng cách gọi namespace TD, tiếp theo bằng tên của mô đun và, cuối cùng, một trong các khóa của đối tượng được mô đun của bạn trả về.

Ví dụ:

TD.List.get(), TD.List.set([]), TD.List.refresh()

tất cả đều hợp lệ, trong khi:

TD.List._refresh_list(), TD.List._add()

thì không hợp lệ, bởi vì những hàm đó chỉ có thể được gọi bên trong mô đun (hãy nhớ rằng, các hàm tạo phạm vi) hoặc được gọi bởi các thành viên có đặc quyền (như đối tượng được trả về bên trong mô đun của bạn).

Liệt kê 8. API Công cộng của TD.List
//public API
return {
get : function () {
return list;
},
set : function (new_list) {
list = new_list;
},
refresh : function () {
_refresh_list();
}
};

Mô đun Vault

Mô đun TD.Vault là một trình bao bọc cho các chức năng EOC (Encrypted Offline) của Worklight. Dựa vào việc lưu trữ cục bộ trong HTML5, EOC là một cách để lưu trữ dữ liệu lâu bền mà không cần sử dụng các cookie. EOC cung cấp các phương thức để mở và đóng và sau đó để đọc và viết các giá trị khi mở. Các chi tiết bảo mật đằng sau EOC nằm ngoài phạm vi của bài này, nhưng nói tóm lại, EOC sử dụng một mật khẩu người dùng để mã hóa dữ liệu. Do đó, mã HTML có liên quan đến mô đun đặc biệt này là một trang (ô cửa sổ đầu tiên trong Hình 1) có chứa:

  • Một hình ảnh đầu trang có biểu trưng hoặc tên ứng dụng.
  • Một trường dùng cho mật khẩu (id=’passcode’).
  • Một nút nhấn (id=’send_passcode’) để gửi đi mật khẩu đó.
Liệt kê 9. Mã HTML dùng cho trang mật khẩu
<!-------------------------- PASSCODE PAGE  -------------------------->
<div data-role="page">

<img class="centerimg" src="images/logonobg.png"/>

<div data-role="content">

<div class="center" id="invalid_passcode"></div>

<ul data-role="listview" data-inset="true">
<li data-role="fieldcontain">
<label for="passcode">Enter Passcode:</label> 
<input type="text" name="passcode" id="passcode" value="" placeholder="Your passcode" />
</li>
</ul>

<a id="send_passcode" href="#" data-role="button" data-theme="a">Start</a>
</div>
<!-- /content -->

</div>
<!-- /page -->

Hãy bắt đầu mã JavaScript của bạn bằng cách chuyển một số biến toàn cục (global) cho hàm chạy tự động của bạn, chẳng hạn như jQuery (được định nghĩa lại là $) và WL (namespace của Worklight, được định nghĩa lại là WL). Sau đó bạn "lưu sẵn trong bộ nhớ đệm" các phụ thuộc của mình để dùng khi cần bằng cách gán các biến cục bộ cho chúng. Điều này bảo đảm rằng bạn có thể dễ dàng gọi wl.EncryptedCache.open (chứ không phải chuyển namespace WL như là một tham số cho mô đun đó) và sau đó lưu sẵn wl.EncryptedCache trong một biến cục bộ được gọi là eoc. Tiếp theo, các biến private như KEY lưu trữ cụm từ mật khẩu mà người dùng nhập vào và một số cuộc gọi DOM được lưu trữ cho button mật khẩu, trường mật khẩu và một div hiển thị một thông báo lỗi nếu mật khẩu không hợp lệ (Liệt kê 10).

Liệt kê 10. Mô đun TD.Vault, các phụ thuộc và các biến private
TD.namespace('TD.Vault');
TD.Vault = (function ($, wl) { 
//dependencies
var eoc = wl.EncryptedCache,
log = wl.Logger,
list_obj = TD.List,
CONST = TD.Constant,

//private variables
KEY = "",
send_passcode_btn = $('#send_passcode'),
passcode_fld = $('#passcode'),
invalid_passcode_div = $('#invalid_passcode'),

Bài tập cuối cùng

Bạn có thể kiểm tra tài liệu hướng dẫn Worklight và thực hiện xử lý từng lỗi cụ thể dựa trên mã trạng thái mà hàm gọi lại onErrorHandler trả về.

Tiếp theo, bạn có một số biến private, như _error, mà chỉ đơn giản ghi nhật ký khi bạn nhận được một cuộc gọi lại có lỗi. Các phương thức _setData and _getData quy định bạn nhận và thiết lập dữ liệu mà bạn sắp mã hóa và giải mã như thế nào (Liệt kê 11).

Liệt kê 11. Các hàm _error, _setData and _getData
//private functions
_error = function () {
log.debug("error");
},

_setData = function (new_list) {
if (new_list) {
list_obj.set(new_list);
list_obj.refresh();
} 
},

_getData = function () {
return list_obj.get();
},

Việc định nghĩa sự kiện tương tự như định nghĩa trong TD.List, ở đây bạn đính kèm send_passcode_btn on click (send_passcode_btn khi nhấn chuột), việc này chỉ đơn giản là gán mật khẩu mà người dùng nhập vào khi khởi động ứng dụng cho biến private KEY, nếu chiều dài đầu vào ít nhất là 1 ký tự (Liệt kê 12).

Liệt kê 12. Đính kèm sự kiện cho button Send Passcode (Gửi mật khẩu)
send_passcode_btn.on('click', function () {

var passcode = passcode_fld.val();

if (passcode.length > 0) {
KEY = passcode;

_decrypt();

$.mobile.changePage("#main", { transition: CONST.DEFAULT_TRANSITION });

} else {
passcode_fld.val('');
invalid_passcode_div.text('Invalid Passcode.');
}

});

Tiếp theo, bạn giải mã các nội dung của EOC bằng cách gọi biến riêng _decrypt(). Việc này gọi hàm _open với một hằng số (CONST.DECRYPT) để cho biết rằng bạn sắp giải mã sau khi bạn mở bộ nhớ đệm đã mã hóa. Hàm _open khởi động sự kiện eoc-open và gửi hành động (decrypt) tới hàm _read(). Sau đó, bạn sẽ thử đọc bộ nhớ đệm đã mã hóa bằng khóa mà người dùng được cấp. Lúc này, hàm _setData được gọi với dữ liệu mà bạn đã lấy ra được phân tích cú pháp thành một mảng JavaScript bằng hàm parseJSON (mảng đó có chứa một cặp giá trị khóa mô tả một mục đơn lẻ trên tất cả chỉ mục của mảng). Nếu bạn đã lấy lại một cái gì đó từ bộ nhớ đệm, bạn gọi hàm set với mô đun Danh sách để thiết lập danh sách mà bạn đã lấy ra làm danh sách mới. Cuối cùng, phần tử HTML của danh sách được làm mới bằng cách gọi refresh từ API công cộng của TD.List.

Liệt kê 13. Các hàm _close, _write, _read, _encrypt, _decrypt và một trình nghe sự kiện ‘eoc-open’
_close = function () {
var onCompleteHandler = function () { 
$.publish('eoc-closed'); 
};

//function(onCompleteHandler, onErrorHandler)
eoc.close(onCompleteHandler, _error);
},

_write = function () {
var data = JSON.stringify(_getData());

//function(key, data, onCompleteHandler, onErrorHandler)
eoc.write(CONST.TODO_ITEMS_KEY, data, _close, _error); 
},

_read = function () {
var onCompleteHandler = function (data) {
_setData($.parseJSON(data)); 
_close(); 
};

//function(key, onCompleteHandler, onErrorHandler)
eoc.read(CONST.TODO_ITEMS_KEY, onCompleteHandler, _error);
},

_encrypt = function () {
_open(CONST.ENCRYPT);
},

_decrypt = function () {
_open(CONST.DECRYPT);
};

$.subscribe("eoc-open", function (e, action) {
if (action) { // == CONST.ENCRYPT
_write();
} else { // == CONST.DECRYPT
_read();
}
});

Việc mã hóa chủ yếu theo các bước tương tự, trừ hành động sau khi bạn mở bộ nhớ đệm sẽ gọi hàm _write thay cho hàm _read. Sau đó bạn chạy hàm _getData để lấy danh sách hiện tại, chuyển nó thành một chuỗi bằng JSON.stringify và lưu trữ nó trong bộ nhớ đệm. Đóng bộ nhớ đệm lại sau mỗi lần mã hóa và giải mã.

Hình 4 và 5 cho thấy ứng dụng đã hoàn thành chạy trên trình giả lập iPhone.

Hình 4. Ứng dụng đã hoàn thành chạy trên trình giả lập iPhone (trang Mật khẩu - Passcode)
Hình 4. Ứng dụng đã hoàn thành chạy trên trình giả lập iPhone (trang Mật khẩu)
Hình 5. Ứng dụng đã hoàn thành chạy trên trình giả lập iPhone (Trang chủ)
Hình 5. Ứng dụng đã hoàn thành chạy trên trình giả lập iPhone (Trang chủ)

Kết luận

Phần 2 của loạt bài giới thiệu này về IBM Worklight tiếp tục sử dụng môi trường phát triển Worklight được thiết lập trong Phần 1 và thêm vào chức năng để xây dựng ứng dụng ví dụ mẫu Todo. Theo cách này, bạn đã tìm hiểu việc cấu trúc mã của mình có thể giúp ích cho việc phát triển, trình bày và bảo trì ứng dụng của bạn như thế nào. Bạn cũng đã học về lưu giữ lâu bền dữ liệu (danh sách công việc) trên thiết bị của bạn bằng cách sử dụng chức năng EOC (Encrypted Offline Cache) của Worklight. Phần kết của loạt bài này sẽ bổ sung kết nối phía máy chủ với các trình tiếp hợp để hoàn thành ứng dụng ví dụ mẫu này.


Tải về

Mô tảTênKích thước
Sample application project filestodo-app-part2.zip18.5MB

Tài nguyên

Học tập

Lấy sản phẩm và công nghệ

Bình luận

developerWorks: Đăng nhập

Các trường được đánh dấu hoa thị là bắt buộc (*).


Bạn cần một ID của IBM?
Bạn quên định danh?


Bạn quên mật khẩu?
Đổi mật khẩu

Bằng việc nhấn Gửi, bạn đã đồng ý với các điều khoản sử dụng developerWorks Điều khoản sử dụng.

 


Ở lần bạn đăng nhập đầu tiên vào trang developerWorks, một hồ sơ cá nhân của bạn được tạo ra. Thông tin trong bản hồ sơ này (tên bạn, nước/vùng lãnh thổ, và tên cơ quan) sẽ được trưng ra cho mọi người và sẽ đi cùng các nội dung mà bạn đăng, trừ khi bạn chọn việc ẩn tên cơ quan của bạn. Bạn có thể cập nhật tài khoản trên trang IBM bất cứ khi nào.

Thông tin gửi đi được đảm bảo an toàn.

Chọn tên hiển thị của bạn



Lần đầu tiên bạn đăng nhập vào trang developerWorks, một bản trích ngang được tạo ra cho bạn, bạn cần phải chọn một tên để hiển thị. Tên hiển thị của bạn sẽ đi kèm theo các nội dung mà bạn đăng tải trên developerWorks.

Tên hiển thị cần có từ 3 đến 30 ký tự. Tên xuất hiện của bạn phải là duy nhất trên trang Cộng đồng developerWorks và vì lí do an ninh nó không phải là địa chỉ email của bạn.

Các trường được đánh dấu hoa thị là bắt buộc (*).

(Tên hiển thị cần có từ 3 đến 30 ký tự)

Bằng việc nhấn Gửi, bạn đã đồng ý với các điều khoản sử dụng developerWorks Điều khoản sử dụng.

 


Thông tin gửi đi được đảm bảo an toàn.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=70
Zone=Nguồn mở
ArticleID=859409
ArticleTitle=Làm việc với Worklight, Phần 2: Phát triển các mô đun có cấu trúc và sử dụng tính năng Encrypted Offline Cache trong IBM Worklight
publish-date=02252013