Hình 3.5: luồng thông tin trong Ligker framework 3.1.3.1. Luồng thông tin trong Ligker framework
Quá trình hoạt động, điều khiển luồng thông tin được mô tả trong hình 3.5. Quá trình này gồm 5 chặng:
Chặng 1: Từ trình duyệt, người dùng gửi request (yêu cầu) tới Webserver (ký hiệu B1 trên hình 3.5).
Chặng 2: Bộ phận Front Controller trên Webserver tiếp nhận yêu cầu từ trình duyệt, tiến hành Rewrite URL theo thiết lập trên file .htaccess (hoặc app.yaml nếu sử dụng Google App Engine). Tiếp đó đến lượt file index.php xử lý thông tin, nạp các thông số thiết lập cấu hình từ file config.php. File index.php tiếp tục gửi thông tin vào file main.php trong core hệ thống (ký hiệu I1 trên hình 3.5).
Chặng 3: File main.php sử dụng Router để kiểm tra request từ trình duyệt (ký hiệu M1 trên hình 3.5):
- Trường hợp 1: request có dạng: index.php?controller=c_1&action=a_1. Khi
nội dung code của các thành phần [c_1] (controller), [m_1] (model), [v_1] (view) tương ứng trong thành phần MVC của Application Layer:
+ Tình huống 1.1: nếu các file chứa [c_1], [m_1], [v_1] có chứa các từ khóa include, require , INSERT, UPDATE, SELECT, ...(sẽ có một bộ keyword cho phần này) thì trả về main.php thông báo lỗi (ký hiệu R1 trên hình 3.5);
+ Tình huống 1.2: nếu các file chứa [c_1], [m_1], [v_1] thỏa mãn việc không chứa các từ khóa bị cấm, file main.php sẽ include các file chứa [c_1], [m_1], [v_1] và tiến hành gọi tới controller=c_1&action=a_1 trong MVC của Application Layer (ký hiệu R2 trên hình 3.5). Các thao tác tiếp theo thực hiện trong mô hình MVC của Application layer (xin xem chi tiết trong phần 3.1.3.2. Đặc tả luồng thông tin trong mô hình MVC của Application layer) và trả kết quả về file main.php (ký hiệu MVC1 trên hình 3.5).
- Trường hợp 2: request có dạng: index.php?page=page_1 (ký hiệu R3 trên
hình 3.5). Trong trường hợp này, Router sẽ gửi thông tin đến thành phần Cache để kiểm tra đã có file cache page_1 trong bộ nhớ đệm chưa?
+ Tình huống 2.1: Nếu trong bộ nhớ đệm đã có file cache page_1: cache sẽ trả kết quả về main.php (ký hiệu C1 trên hình 3.5).
+ Tình huống 2.2: Nếu trong bộ nhớ đệm chưa có các file cache tương ứng: Router sẽ gọi đến thành phần PAGE (ký hiệu C2 trên hình 3.5). PAGE nhận request, trả về main.php yêu cầu gọi các module cần thiết (ký hiệu P1 trên hình 3.5). Một PAGE có thể gọi nhiều module khác nhau (xin xem chi tiết trong phần 3.1.4. Mối quan hệ Page - Position - Module trong Ligker framework). Do đó, nếu PAGE yêu cầu n module, Router sẽ thực hiện gọi n lần các module đó thông qua request có dạng index.php?controller=c_i&action=a_i (i chạy từ 1 đến n). Tức là sẽ lặp lại n
lần Trường hợp 1 nêu ở trên.
Kết thúc Chặng 3, kết quả của 2 trường hợp đều hội tụ thông tin về file main.php.
Chặng 4: file main.php sẽ căn cứ theo các thông số cấu hình hệ thống (file config.php) để quyết định có lưu 1 bản cache vào bộ nhớ đệm hay không (ký hiệu
M2 trên hình 3.5). Sau đó, main.php trả kết quả về file index.php (ký hiệu M3 trên hình 3.5)
Chặng 5: file index.php trả kết quả cuối cùng về trình duyệt (ký hiệu I2 trên hình 3.5).
3.1.3.2. Đặc tả luồng thông tin trong mô hình MVC của Application layer
Từ sơ đồ tổng quát Hình 3.5 ở trên, phân tích chi tiết Chặng 3 - trường hợp 1 - tình huống 1.2 (tương ứng với các ký hiệu R2, MVC1 trên hình 3.5), chúng ta đặc tả luồng thông tin hoạt động trong mô hình MVC của Application layer sẽ có sơ đồ như hình 3.6 dưới đây:
Hình 3.6: Luồng thông tin trong mô hình MVC
Ở đây, ta xem xét quá trình Router tiếp nhận yêu cầu từ trình duyệt và chuyển tiếp tới Controller xử lý:
- Controller tiếp nhận yêu cầu từ Router, gọi đồng thời tới các Model và View tương ứng
- Model nhận yêu cầu từ controller, tiến hành thực hiện truy vấn cơ sở dữ liệu, lấy ra dữ liệu theo yêu cầu, trả kết quả về controller.
- View gọi các file HTML cần thiết,
- Controller trộn 2 thành phần: dữ liệu (lấy từ model) và HTML (lấy từ view) thành kết quả trả lại Router.
Trong quá trình xây dựng một dự án, nếu một phương thức được viết trong nhiều hơn 1 lớp, phương thức đó sẽ được Project Leader xem xét đưa vào Base functions. Nếu phương thức nào viết trong Base functions được sử dụng nhiều hơn 2 dự án và hoạt động ổn định, hiệu quả, và có thể áp dụng cho nhiều loại dự án khác nhau, phương thức đó sẽ được cân nhắc đưa vào Core functions.
Ví dụ: ở phiên bản lõi core_1.0 chưa có chức năng tạo mã QR code.
Một dự án quản lý thẻ khách hàng có sử dụng framework ligker core_1.0. Trong đó có 2 lớp ứng dụng là card (thẻ) và customer (khách hàng).
- Giai đoạn 1: yêu cầu tạo mã QR code cho Mã thẻ. Khi đó, lập trình viên tiến hành tạo phương thức: create_card_qr_code() trong lớp card;
- Giai đoạn 2: khách hàng bổ sung: yêu cầu tạo mã QR code cho Mã khách hàng. Ở giai đoạn này, thay vì tiếp tục tạo thêm một phương thức create_member_qr_code(), Project Leader sẽ kiểm tra phương thức create_card_qr_code() đã tạo ở giai đoạn 1, tiến hành chuyển phương thức này về Base functions và đặt lại tên create_qr_code(). Sau đó, cả 2 lớp ứng dụng là card và customer đều dùng chung method này.
Khi kết thúc dự án, nhận thấy phương thức create_qr_code() tỏ ra hiệu quả và có thể tái sử dụng trong nhiều dự án trong tương lai, create_qr_code() đã được đưa vào Core functions trong Core layer của Ligker framework.
3.1.3.3. Một vài nhận xét về quy trình hoạt động của Ligker framework
Với cách tạo ra một khung làm việc như vậy, Core layer sẽ bắt buộc các lập trình viên khi viết code ở Application layer phải tuân thủ việc:
- Không được phép include, require… bất kỳ file nào khác.
- Từ một controller chỉ được phép gọi các model, view mặc định, hoặc controller chỉ được gọi 1 controller khác thông qua hàm call_controller(); hàm này đã được kiểm soát bởi Router trong file main.php (như đã trình bày trong phần
3.1.1.2. Core Layer - lớp lõi). Ngoài ra, các thành phần controller, model, view không được gọi tới các thành phần khác mà không thông qua thành phần Router.
- Trong MVC của Application layer, khi viết controller, các lập trình viên không được phép viết các câu có các từ khóa liên quan đến truy vấn SQL (SELECT, INSERT, UPDATE, …), không được viết các thẻ HTML: <div>, <a>… Tương tự, trong model và view, không được viết If … else.. , switch , case….Đó là các từ khóa bị cấm vì mục đích đảm bảo tuân thủ mô hình MVC của hệ thống.
3.1.4. Mối quan hệ Page - Position - Module trong Ligker framework
3.1.4.1. Page – trang
Một website là tập hợp của nhiều trang web. Mỗi trang web gọi là 1 page. Phần view của một page ở đây được hiểu là một trang HTML hoàn chỉnh với các thẻ HTML : <head>, <body>, <div>...và khi hiển thị trên trình duyệt sẽ được kết quả tương tự như hình 3.7 dưới đây:
3.1.4.2. Position – các vị trí trong một trang
Position là một khái niệm quy ước các vị trí trên web page của người thiết kế giao diện với khách hàng. Do đó, bố cục các position của các page có thể giống hoặc khác nhau.
Một page gồm nhiều position. Thông thường, người thiết kế sẽ chia không gian của 1 web page thành khoảng 5~10 phần, mỗi phần ứng với một position.
3.1.4.3. Module
Tiếp tục chia nhỏ các position theo yêu cầu thiết kế cho đến khi tạo được một khối độc lập gắn với một lớp cụ thể, khi đó ta đã tạo được một module.
Hình 3.8: Các position và module trên một web page
Ví dụ : hình 3.8, tại vị trí Position 5 cần gọi 2 module : Đăng nhập và Tin mới. Việc tạo lập mối quan hệ Page - Position - Module nhằm 2 mục đích :
- Module hóa công việc của các lập trình viên ; - Tái sử dụng các module một cách hiệu quả.
Căn cứ vào bản thiết kế giao diện bao gồm Page – Position - Module, Project Leader sẽ giao mỗi module cho 1 hoặc 1 nhóm coder thực hiện. Các lập trình viên xây dựng module bằng cách gọi tới các controller và method cụ thể, thực hiện truy vấn dữ liệu, kết hợp với thành phần view và trả lại kết quả HTML vào đúng position theo thiết kế.
Trong quá trình thực hiện dự án, Project Leader xác định các module dùng chung cho nhiều page (có thể ở các position giống nhau hoặc khác nhau) để thực hiện tái sử dụng module.
3.1.5. Cấu trúc thư mục của Ligker framework
Căn cứ vào nguyên lý hoạt động của Ligker framework đã trình bày ở phần trên, cấu trúc thư mục của hệ thống được xây dựng với 2 thư mục chính: core và project như minh họa trong hình 3.9:
3.1.5.1. Thư mục Core
Core do tác giả luận văn tự xây dựng. Nội dung Core có thể bổ sung, thay đổi, nâng cấp theo từng phiên bản. Phiên bản Core được trình bày trong luận văn này là phiên bản core_4.0.
Thư mục core bao gồm các thành phần:
- core_functions: bao gồm các hàm chức năng cơ bản nhất của 1 website framework. Các chức năng đó bao gồm: Thêm, sửa, xóa, xem danh sách;
- Các file hệ thống: main.php, router.php. Hai file này sẽ quyết định toàn bộ luồng thông tin của ứng dụng. Toàn bộ hệ thống sẽ phải tuân thủ luồng thông tin mà Ligker framework đặt ra.
- Thư mục cache: lưu các file cache có tác dùng làm bộ nhớ đệm cho ứng dụng - Thư mục default_libray: thư viện mặc định của hệ thống (hình 3.10)
Hình 3.10: Các thành phần trong thư mục default_library
+ Template: Giao diện mặc định để chạy các chức năng cơ bản: thêm, sửa, xóa, liệt kê. Có thể dùng giao diện này cho trang admin mặc định của hệ thống.
+ Thư mục js chứa các file .js bao gồm thư viện các hàm javascript quan trọng, hay được sử dụng.
+ Thư mục gwt: lưu các file js do Google Web Toolkit sinh ra. + Thư mục images: lưu các file ảnh mặc định của framework. Ví dụ: default_avatar.jpg, loading.png…
+ Thư mục jquery: bao gồm các phiên bản jquery
+ Thư mục lang: bao gồm các file ngôn ngữ (dùng trong các project yêu cầu đa ngôn ngữ). Mỗi ngôn ngữ được lưu trong một file XML.
+ Thư mục smarty: các phiên bản của Template Engine Smarty
Core là phần quan trọng nhất của hệ thống. Do đó, thư mục core nên đặt ngoài thư mục gốc của webserver, hạn chế tối đa các hành động tấn công sửa đổi mã nguồn thư mục này. Ngoài ra, cũng nên đặt thư mục core tách biệt hoàn toàn khỏi ứng dụng vì trong thực tế, có thể có nhiều project dùng chung một thư mục core.
Như mô tả trên hình 3.11,thư mục project bao gồm hệ thống các thư mục, file mà các lập trình viên sẽ thực hiện để viết một dự án cụ thể. Thư mục này bao gồm các thành phần:
- Thư mục app: thư mục này bao gồm các thành phần con:
+ Các thư mục MVC (controller, model, view) của dự án. Mỗi đối tượng trong dự án sẽ tương ứng với 3 file trong 3 thư mục MVC này. Ví dụ: đối tượng book sẽ có 3 file: book_controller.php (nằm trong thư mục controller), book_model.php (nằm trong thư mục model), book_view.php (nằm trong thư mục view). Ngoài ra, trong mỗi thư mục MVC sẽ có 1 file cơ sở: base_controller.php, base_model.php, base_view.php; đây là các Base functions kế thừa từ Core. Các lớp cụ thể sẽ kế thừa Base functions, ví dụ: Book_Controller kế thừa Base_Controller, Book_Model kế thừa Base_Model, Book_View kế thừa Base_View.
+ Library: các thư viện của dự án; bao gồm: css, js, lang (các file XML đa ngôn ngữ), các gói template như hình 3.12 dưới đây:
+ Page: các trang của dự án. Ví dụ: dự án website Tin tức sẽ có các trang: Trang chủ, Sự kiện, Thể thao, Văn hóa ...
+ Uploads : lưu các file do người dùng tải lên.
- file .htaccess : một tập tin dùng để cấu hình máy chủ web apache. Nó được máy chủ chấp nhận như là một thành phần và cho phép chúng ta thực hiện điều hướng và bật các tính năng một cách linh hoạt hoặc bảo vệ một phần (folder) nào đó của trang web.
- file app.yaml : là file cấu hình bắt buộc phải có khi sử dụng Google App Engine. App.yaml chứa các thông tin cần thiết để chạy ứng dụng trên môi trường Appengine. .yaml là định dạng dữ liệu được thiết kế nhằm mục đích để người và máy (các ngôn ngữ lập trình) cùng đọc được. yaml được dùng vào mục đích tương tự JSON, XML nhưng ngắn gọn xúc tích hơn.
- file config.php : lưu các thông tin cấu hình của dự án.
- file index.php : chỉ có nhiệm vụ duy nhất là gọi đến file main.php trong core Thư mục app có thể đặt bất kỳ đâu miễn là trong thư mục gốc.
Các thư mục core, default_library, app có thể đặt lại tên. Ví dụ : đặt tên là application, hoặc applications thay vì đặt tên là app. Nếu đặt lại tên của các thư mục này, cần sửa lại các khai báo tương ứng trong file config.php.
3.2. Xử lý phía máy khách (client)
Như chúng ta đã biết, trên trình duyệt web của máy client bao gồm các mã HTML, css, javascript, image... Ligker framework sử dụng 2 công cụ để làm điều này : Google Web Toolkit và Template Engine.
3.2.1. Sử dụng Google Web Toolkit
Cách sử dụng này được áp dùng trong trường hợp các lập trình viên java muốn tạo ra các trang HTML, thực hiện Ajax mà không cần sử dụng đến javascript.
Hình 3.13: Cấu trúc thư mục của một Google Web Toolkit project
Ở trên, chúng ta đã biết thư mục chứa Google Web Toolkit được đặt trong default_libray của Ligker framework. Việc phát triển project gwt_tool có thể thực hiện trên máy local. Khi ghép vào Ligker framework, ta sẽ đặt thư mục gwt_tool như hình 3.14 dưới đây:
Kết quả của một Google Web Toolkit là tạo ra javascript. Do đó, Ligker framework sẽ gọi đến file javascript của gwt_tool từ phần header của HTML trong trang web bằng cách sử dụng đoạn mã sau:
<script "default_library/gwt/gwt_tool/war/gwt_tool/gwt_tool.nocache.js"> </script>
Với đoạn mã trên, chúng ta đã thực hiện kết nối Ligker framework với một Google Web Toolkit có tên là gwt_tool. Gwt_tool có 2 nhiệm vụ: Viết mã HTML và hiện thực Ajax.
3.2.1.1. Viết mã HTML
Bằng cách sử dụng các widget, các lập trình viên sử dụng Google Web Toolkit để tạo ra mã HTML. Google Web Toolkit hỗ trợ tạo ra những widget sau: Các đối tượng chuẩn HTML (Button, Radio Button, Checkbox, TextBox, TextArea, Hyperlink, ListBox, Table v.v...), PushButton, ToggleButton, MenuBar, Tree, TabBar, DialogBox, Panels, RichTextArea, SuggestBox (auto-complete).
Bằng cách sử dụng các widget nêu trên, lập trình viên Java hoàn toàn có thể tạo được bất kỳ trang HTML nào. Điều này vừa đem lại sự thuận tiện cho lập trình viên, đồng thời còn là tiền đề để thực hiện Ajax khi người dùng tạo ra các sự kiện (Event) khi thao tác trên website.
3.2.1.2. Thực hiện Ajax
Google Web Toolkit hỗ trợ xử lý khoảng 33 sự kiện: onblur, onchange, onclick…Chẳng hạn sự kiện onclick được viết như sau:
Kết quả của đoạn mã hình 3.15: bằng việc sử dụng Google Web Toolkit, các lập trình viên đã tạo ra một button (Click here) bằng java thay vì dùng HTML. Với sự kiện onclick, Button Click here cũng đã thực hiện một lệnh javascript như hình 3.16 dưới đây:
Hình 3.16: Đoạn mã Java viết trên Google Web Toolkit sinh ra Javascript
3.2.2. Sử dụng Template Engine
Ngược lại với trường hợp 4.2.1, trong phần này sẽ giả thiết các lập trình viên không thạo về java và sẵn sàng làm việc với các file HTML, viết mã javascript để thực hiện Ajax. Trong trường hợp này, Ligker framework giải quyết như sau:
3.2.2.1.Viết mã HTML
Ligker framework sử dụng Template Engine Smarty để tách riêng mã HTML phía client và code back-end phía server. Thư mục Smarty có cấu trúc như sau:
Trong hình 3.17, mô tả vị trí đặt thư mục Smarty trong hệ thống. Luận văn đang sử dụng Smarty phiên bản 3.1.18.
Để sử dụng Smarty, cần thực hiện cấu hình như nội dung trong file include_smarty.php. Việc cấu hình này là khá đơn giản như trong hình 3.18:
Hình 3.18: Cấu hình Smarty trong Ligker framework
Sau phần khai báo, lập trình viên sẽ xác định nơi đặt các file HTML của toàn