Tóm tắt: Phần 2 của loạt hướng dẫn này bao gồm các chi tiết liên quan đến việc
phát triển ứng dụng Facebook mà bạn đã bắt đầu trong Phần 1. Xây dựng một giao
diện Facebook cho một công ty môi giới chứng khoán đang hoạt động, cho phép
quản lý trực tuyến danh mục đầu tư. Tìm hiểu một cách tiếp cận để phân chia chức
năng của một ứng dụng giữa các thành phần PHP và Java, và sử dụng khung công
tác Spring để áp dụng một kiến trúc MVC tiêu chuẩn đối với mã Java ™. Loạt bài
hướng dẫn này dẫn dẫn dắt bạn đi qua quy trình phát triển một ứng dụng Facebook
đầy đủ chức năng bằng cách sử dụng WebSphere® Application Server (Máy chủ
ứng dụng WebSpher), Rational® Application Developer (Bộ Phát triển ứng dụng
Rational), Zend Core cho IBM, PHP 5 và DB2®.
75 trang |
Chia sẻ: tlsuongmuoi | Lượt xem: 2322 | Lượt tải: 0
Bạn đang xem trước 20 trang tài liệu Đề tài Làm chủ việc phát triển ứng dụng Facebook bằng PHP, IBM Rational Application Developer, IBM WebSphere Application Server và DB2, Phần 2: Sử dụng đồng thời Java và PHP, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
Java thường đến từ các nền tảng khác nhau, và nhìn các thế
giới này theo các cách khác nhau. Hai ngôn ngữ này có thể cùng tồn tại trong cùng
một ứng dụng (và cùng một nhóm phát triển) rất thành công, và với một mức độ
trừu tượng cao và cấu trúc sạch một cách toàn diện.
Các đều kiện tiên quyết
Hướng dẫn này dành cho các nhà phát triển Java và PHP có mức kinh nghiệm
khác nhau, những người muốn bắt đầu viết các ứng dụng Facebook trong Java,
PHP hoặc tích hợp cả hai như là những bộ phận của một ứng dụng lớn hơn. Nó
dành cho các nhà phát triển PHP, những người muốn tìm hiểu công việc xây dựng
một ứng dụng J2EE bằng cách sử dụng khuôn mẫu Spring và cách áp dụng một
cấu trúc hướng đối tượng vào các ứng dụng PHP của họ, và dành cho những người
phát triển Java muốn bắt đầu sử dụng PHP, có thể vì mục đích thêm PHP vào ứng
dụng Java doanh nghiệp hiện hành.
Bạn nên đọc Mastering Facebook application development, Part 1 (Làm chủ ứng
dụng Facebook, Phần 1) trước khi tiếp tục Phần 2.
Yêu cầu về hệ thống
Để hoàn thành các bước trong hướng dẫn này, bạn cần các phần mềm sau. Nếu
bạn chưa cài đặt các sản phẩm này, hoặc không có phiên bản mới nhất, bạn có thể
tải về các phiên bản dùng thử miễn phí:
Tải về một phiên bản dùng thử miễn phí Spring Framework -- Tôi sử dụng
phiên bản 2.5.3, bản phát hành mới nhất.
Tải về một phiên bản dùng thử miễn phí Rational Application Developer.
Bạn sẽ sử dụng Rational Application Developer như là một bản IDE đầy đủ
tính năng dựa trên Eclipse để phát triển ứng dụng Web Java của bạn.
Tải về một phiên bản dùng thử miễn phí IBM WebSphere Application
Server V6.1.
Tải về Zend Core For IBM (gồm có IBM DB2® Express-C)
Zend Studio là một công cụ tuyệt vời để viết mã PHP, mặc dù có thể dùng
trình soạn thảo văn bản nào cũng được.
Bổ sung Java cùng với PHP
Trong Phần 1 bạn đã nhận được bên PHP của ứng dụng đang chạy. Bây giờ bạn sẽ
thực hiện việc khởi tạo ban đầu để tạo ra bên Java của ứng dụng -- một dự án
Rational Application Developer và ứng dụng web bằng cách sử dụng khung công
tác Spring nổi tiếng. Sau đó bạn sẽ viết ra các lớp PHP cho phép bạn áp đặt cùng
một mẫu MVC lên mã PHP như trong Java, và tạo một proxy đảo ngược từ
Apache đến IBM WebSphere bằng cách sử dụng mod_rewrite và mod_proxy, do
đó bạn có thể sử dụng cùng một URL Facebook Callback đối với các máy chủ
PHP và Java. Sau đó bạn sẽ sử dụng tập tin .htaccess để gửi các yêu cầu đến PHP
hoặc Java tùy thuộc vào URI yêu cầu. Một cấu trúc chung giữa các máy chủ Java
và PHP của bạn sẽ làm cho sự tích hợp của chúng dễ dàng hơn và cho phép bạn
(hoặc nhóm của bạn) sử dụng bất cứ công nghệ nào thích hợp hơn cho mỗi mảnh
của ứng dụng Facebook, và việc sử dụng proxy và .htaccess sẽ tách rời mặt trước
với việc sử dụng hai công nghệ của bạn ở mặt sau.
Thiết lập dự án Rational Application Developer
Làm theo các bước sau để thiết lập một dự án trong Rational Application
Developer:
1. Mở Rational Application Developer từ trình đơn Start: Start > All
Programs > IBM Software Development Platform > IBM Rational
Application Developer > IBM Rational Application Developer.
2. Tạo một dự án Java mới (File > New > Project), chọn Dynamic Web
Project làm kiểu dự án và WebSphere Application Server v6.1 làm môi
trường chạy đích.
Phải chắc chắn đã đánh dấu chọn các khía cạnh (facet) của dự án Dynamic
Web Module, Java, JSTL, và khía cạnh WebSphere web.
3. Đặt gốc ngữ cảnh ở facebook-stock-demo, thư mục nội dung vào mặc định
của WebContent, và thư mục nguồn Java vào src. Rational Application
Developer sau đó sẽ tạo ra cấu trúc dự án ứng dụng web tiêu chuẩn cho bạn
và bạn chỉ cần điền nó vào.
Hợp nhất khung công tác Spring
Thêm khung công tác Spring đa năng vào ứng dụng.
1. Tải về phiên bản khung công tác Spring với tất cả các phần phụ thuộc (xem
Prerequisites để có một đường liên kết).
2. Giải nén nó vào vị trí có ích nào đó, thí dụ c:\ (việc giải nén các tập tin có
thể mất một thời gian), và từ thư mục dist sao chép tệp spring.jar và tất cả
các tệp JAR dưới thư mục dist/modules vào thư mục WEB-INF/lib của dự
án. Bạn có thể tìm thấy thư mục WEB-INF/lib của dự án của bạn bằng cách
chuyển đến Project > Properties và xem ô Info. Thí dụ, tôi đã sao chép
chúng vào C:\Documents and
Settings\jmiles\IBM\rationalsdp7.0\workspace\facebook-stock-
demo\WebContent\WEB-INF\lib.
3. Bổ sung thêm commons-logging.jar vào đường dẫn lớp (classpath) của dự
án của bạn, từ thư mục lib/jakarta-commons của khung công tác Spring,
thông qua Project > Properties > Java Build Path > Add External JARs
(xem Hình 1). Không được sao chép JAR này vào thư mục lib của bạn; nó
sẽ gây ra một lỗi khi triển khai WebSphere.
Hình 1. Thêm các JAR bên ngoài vào dự án Rational Application
Developer của IBM
4. Làm mới vùng làm việc (nhấn chuột phải vào tên dự án và chọn Refresh),
và khung nhìn Project Explorer sẽ cập nhật tất cả các JAR được thêm vào.
Lập cấu hình Spring
Giờ thì bạn đã cài đặt Spring, và bạn cần phải lập cấu hình ứng dụng Web để sử
dụng nó. Nhấn chuột phải vào web.xml trong Project Explorer (xem Hình 2) và
chọn Open with > Text Editor.
Hình 2. Mở web.xml bằng một trình soạn thảo văn bản trong Rational
Application Developer
Thay nội dung bằng nội dung của Liệt kê 1.
Liệt kê 1. web.xml
<web-app id="WebApp_ID" version="2.4"
xmlns=""
xmlns:xsi="
instance"
xsi:schemaLocation="
app_2_4.xsd">
facebook-stock-demo</display-
name>
spring
org.springframework.web.servlet.DispatcherServlet
1
spring
/action/*
index.jsp
Việc này sẽ định tuyến tất cả các yêu cầu mà các URI của chúng bắt đầu bằng
facebook-stock-demo/action (ở đây facebook-stock-demo là bối cảnh mà bạn sẽ
chỉ định trong WebSphere của IBM) thông qua DispatcherServlet của Spring,
điểm nhập vào khung công tác MVC Spring.
Tiếp theo bạn cần có một tập tin Spring-servlet.xml để lập cấu hình cho các bean
Spring. Spring theo mặc định sẽ nối thêm đuôi “-servlet.xml” vào phần tử
trong web.xml làm tên của tập tin cấu hình, do đó trong khung
nhìn Project Explorer, hãy tạo một tập tin văn bản mới trong thư mục WEB-INF
có tên là spring-servlet.xml. Bạn có thể phải đóng tập tin và nhấn chuột phải vào
nó để mở ra bằng một trình soạn thảo văn bản nếu Rational Application Developer
mở nó ra theo mặc định trong một trình soạn thảo XML. Dán nội dung của Liệt kê
2 vào spring-servlet.xml.
Liệt kê 2. Spring-servlet.xml ban đầu
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"">
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
org.springframework.web.servlet.view.JstlView
/WEB-INF/jsp/
<bean id="urlMapping" class="org.springframework.web.servlet.
handler.SimpleUrlHandlerMapping">
<bean id="stockListController"
class="com.jm.fbstockdemo.StockListController">
stockList.jsp
Bean đầu tiên quy định cách thức mà các tên khung nhìn được ánh xạ vào URL.
Bất cứ khi nào một trình điều khiển trả lại một tên khung nhìn, trình phân giải
khung nhìn (view resolver) sẽ nối thêm phần đầu /WEB-INF/jsp/ vào nó, tạo ra
chẳng hạn tệp /WEB-INF/jsp/stocks.jsp để đáp ứng lại tên khung nhìn stocks.jsp.
Bean thứ hai ánh xạ các URL vào các trình điều khiển spring, trong trường hợp
này nó ánh xạ một url đơn lẻ, /stockList, vào bean điều khiển bằng id
stockListController, mà được định nghĩa như là bean thứ ba trong tập tin này.
Định nghĩa bean stockListController nội xạ một thuộc tính successView với đối
tượng StockListController để giữ các tên của các khung nhìn nằm bên ngoài mã
Java.
Thêm vào một lớp trình điều khiển Spring và khung nhìn tương ứng
Để thêm vào một lớp trình điều khiển Spring và khung nhìn tương ứng, hãy làm
như sau:
1. Tạo một gói dưới thư mục src bằng cách nhấn chuột phải vào Java
Resources: src trong khung nhìn Project Explorer và chọn New >
Package. Tôi gọi gói của tôi là com.jm.fbstockdemo.
2. Nhấn chuột phải vào gói mới này và tạo một lớp StockPriceController có
thực hiện org.springframework.web.servlet.mvc.Controller. Bạn có thể chỉ
cần gõ Controller sau khi nhấn vào Add và Rational Application Developer
sẽ thu hẹp danh sách các tùy chọn tương ứng khi bạn gõ nhập.
3. Điền vào nó một triển khai thực hiện cơ bản nhất có thể, đơn giản chỉ thực
hiện trả lại một tên khung nhìn để biểu hiện (xem Liệt kê 3).
Liệt kê 3. Một lớp StockListController ban đầu (Java)
public class StockListController
implements Controller {
public ModelAndView
handleRequest(HttpServletRequest
request,
HttpServletResponse
response) throws Exception {
return new ModelAndView
(getSuccessView());
}
}
4. Tiếp theo nhấn chuột phải vào WEB-INF và tạo một thư mục jsp.
5. Trong thư mục jsp tạo tệp stockList.jsp ban đầu, có chứa xml để kiểm thử
như Liệt kê/như trong Liệt kê 4.
Liệt kê 4. Một stockList.jsp ban đầu
<%@ page contentType="text/xml"
%>
<%@ taglib prefix="c"
uri=""
%>
1
JAKE
3000
Triển khai vào WebSphere Application Server
Với ứng dụng Spring Java khung sườn đã viết, giờ đây bạn có thể triển khai nó
vào WebSphere Application Server (Máy chủ ứng dụng WebSphere).
1. Tạo tập tin WAR bằng cách nhấn chuột phải vào dự án trong Rational
Application Developer, và chọn Export > WAR file.
2. Trong cửa sổ Save As, di chuyển đến thư mục của dự án (như bạn đã làm
trên đây) và tạo một thư mục mới có tên dist bên cạnh các thư mục src và
WebContent. Thí dụ, tôi đã ghi lưu tệp WAR là c:\Documents và
Settings\jmiles\IBM\rationalsdp7.0\workspace\facebook-stock-
demo\dist\facebook-stock-demo.war.
3. Nhấn Finish. Rational Application Developer sẽ bao bọc ứng dụng một
cách thành thục thành facebook-stock-demo.war.
4. Để triển khai tập tin WAR, khởi động một cá thể máy chủ ứng dụng
WebSphere qua Start>All Programs>IBM WebSphere > Application
Server v6.1 > Profiles > [your profile name] > Start the server (xem
Hình 3). Đợi nó khởi động (một cửa sổ nhắc lệnh sẽ xuất hiện, hiển thị
thông tin khởi động, sau đó biến mất), và sau đó di chuyển đến bàn điều
khiển (Administrative Console) qua cùng đường dẫn của trình đơn Start.
Thao tác này sẽ mở ra bàn điều khiển của cá thể WebSphere của bạn trong
trình duyệt Web.
Hình 3. Khởi động Máy chủ Ứng dụng WebSphere từ trình đơn khởi
động Windows
5. Đăng nhập vào bàn điều khiển admin, mở phiếu Applications và chọn
Install New Application.
6. Chọn Local file system, di chuyển đến tệp tin WAR của bạn và chọn nó.
7. Chỉ rõ /facebook-stock-demo làm bối cảnh gốc, và nhấn Next. Giữ nguyên
tất cả các giá trị mặc định trên màn hình các tùy chọn cài đặt và nhấn Next.
8. Trên màn hình “Map modules to servers” chọn ứng dụng web của bạn để
thêm nó vào server1.
9. Nhấn vào Finish trên màn hình summary, và WebSphere sẽ cài đặt ứng
dụng web. Hãy chắc chắn nhấn vào Save dưới đáy màn hình đầu ra khi cài
đặt hoàn tất.
10. Nhấn vào Enterprise Applications ở bên trái, và bạn sẽ thấy ứng dụng của
bạn nằm trong danh mục các ứng dụng đã cài đặt. Chọn cái đó và nhấn
Start để khởi động.
11. Để xác nhận cổng mà ứng dụng của bạn đang chạy trên đó, hãy mở phần
Servers ở bên trái, nhấn Application servers, chọn server1, và trong phần
Communications của cấu hình server1 nhấn Ports ((xem Hình 4).
WC_defaulthost chỉ rõ cổng mà qua đó bạn có thể truy cập ứng dụng web
của bạn. Trong cài đặt của tôi cổng này là 9083; thay thế giá trị ấy vào chỗ
của WC_defaulthost trong tất cả các URL được chỉ ra sau đây.
Hình 4. Tìm cổng HTTP của máy chủ của bạn trong Máy chủ ứng
dụng WebSphere
12. Cuối cùng, để xác nhận rằng tất cả hoạt động tốt, hãy mở một cửa sổ trình
duyệt nữa, vào
và bạn sẽ thấy xml của stockList.jsp.
Ứng dụng web MVC Spring bây giờ đã được cài đặt và làm việc dưới IBM
WebSphere cung cấp một cấu trúc MVC tiêu chuẩn để phát triển mã ứng dụng
Facebook của bạn trong đó.
Cơ cấu một ứng dụng PHP tương tự như một ứng dụng Java Spring
Cấu trúc của một ứng dụng Web Java và DispatcherServlet của Spring cung cấp
một mô hình tuyệt vời cho nửa PHP của ứng dụng. Không ném qua cửa sổ những
kết quả trừu tượng hóa hướng đối tượng đẹp đẽ như vậy, bạn sẽ nhanh chóng trực
tiếp làm ra một số các lớp có thể giúp cho việc mô phỏng chức năng thêm thuộc
tính của Spring và chức năng điều phối của MVC. Bạn sẽ viết ra một lớp
Properties đọc các tệp tin thuộc tính, một lớp Injectable cho phép bạn thêm các
thuộc tính từ các tệp tin đó vào các cá thể lớp, và một lớp ActionDispatcher sẽ
điều phối một biến yêu cầu đến đúng lớp điều khiển để xử lý yêu cầu.
Để viết mã PHP, bất kỳ trình soạn thảo văn bản nào cũng làm được, nhưng Zend
Studio là tuyệt vời (xem Tài nguyên).
Đọc các giá trị từ các tệp tin thuộc tính
Để giữ cho những phần không thay đổi của ứng dụng nằm bên ngoài mã, bạn sẽ sử
dụng một tập hợp các tệp tin thuộc tính và một lớp Properties đọc được chúng, lắp
ráp một mảng kết hợp các thuộc tính mà phần còn lại của ứng dụng có thể sử dụng
được, như trong liệt kê 5 (đặt Properties.php trong một thư mục con lib dưới thư
mục fb_stock_demo).
Liệt kê 5. Properties.php
<?php
class Properties {
private $props;
public function __construct
($propertiesFilePaths) {
$this->props = array();
foreach ($propertiesFilePaths as
$path) {
$this->loadProperties($path);
}
}
private function
loadProperties($propertiesFilePath)
{
$lines =
file($propertiesFilePath);
foreach ($lines as $line) {
$trimmed = trim($line);
if (strlen($trimmed) > 0 &&
strchr($trimmed, 0, 1) != "#") {
$split = split("=", trim($line));
$key = $split[0];
$value = $split[1];
$this->props[$key] = $value;
}
}
}
public function get($key) {
if (! isset($this->props[$key])) {
throw new Exception
("Properties: unknown key $key");
}
return $this->props[$key];
}
}
Bạn cung cấp cho hàm tạo (constructor) một mảng các đường dẫn đến tệp tin
thuộc tính, nó đọc lần lượt từng cái một, lắp ráp mảng kết hợp trong
loadProperties(). Bằng cách nhận cả một mảng các đường dẫn tệp tin thuộc tính
chứ không phải chỉ là một đường dẫn, bạn tách rời các thuộc tính phụ thuộc vào
môi trường như các giá trị kết nối cơ sở dữ liệu. Điều này làm cho việc sao chép
mã dễ dàng hơn từ một môi trường này đến môi trường khác (ví dụ từ phát triển
đến sản xuất) không phải viết đè lên các giá trị đó; bạn chỉ cần không sao chép các
tập tin đặc trưng cho môi trường hoặc thiết lập cấp quyền truy cập chúng sao cho
bạn không thể viết đè lên chúng được trong khi sao chép. Thí dụ, ứng dụng này sẽ
sử dụng hai tập tin thuộc tính, app.properties và db.properties, ở đây
app.properties chứa các hằng số như khoá mã và bí mật API Facebook (Facebook
API Key and Secret), còn db.properties chứa thông tin đăng nhập cơ sở dữ liệu.
Sử dụng các phương thức thần kỳ PHP 5 để cung cấp phép thêm vào thuộc tính
kiểu như Spring
Bây giờ ta xem xét một số phép thần kỳ PHP 5. Để cung cấp thêm một chút gì hơn
kiểu như Spring, bạn có thể thêm các thuộc tính vào một đối tượng từ một tệp tin
cấu hình mà sẽ xem xét và đối xử chính xác như các biến cá thể trong đối tượng
đích. Tất cả các lớp cần có các thuộc tính được thêm vào như vậy cần phải là lớp
con của lớp Injectable (xem Liệt kê 6).
Liệt kê 6. Lớp Injectable (PHP)
class Injectable {
protected $properties;
private $prefix;
public function
Injectable($properties=null,
$propPrefix=null) {
$this->prefix =
$propPrefix == null ?
get_class($this) . '/' :
$propPrefix;
$this->setProperties
($properties);
}
public function
setProperties($properties) {
$this->properties =
$properties;
}
public function
__get($property) {
return $this-
>getProperty($property);
}
public function
getProperty($property) {
return $this->properties-
>get($this->prefix .
$property);
}
}
Then chốt của lớp Injectable là phương thức __get() đó là một phương thức thần
kỳ của PHP 5. Các phương thức thần kỳ là phương thức đặc biệt có sẵn trên tất cả
các đối tượng PHP 5, mà PHP sử dụng để cung cấp cho các đối tượng các hành vi
lõi đặc biệt; bất kỳ biến PHP và bất kỳ phương thức nào có tên bắt đầu bằng __
(hai gạch dưới) sẽ được coi là phương thức thần kỳ. Bất cứ khi nào bạn truy cập
một biến cá thể của một đối tượng, nếu biến đó không được tìm thấy trên đối
tượng, PHP sẽ gọi phương thức __get() của đối tượng để tìm ra giá trị của nó, chỉ
cần cung cấp tên của biến được yêu cầu dưới dạng chuỗi ký tự. Phương thức
__get() của lớp Injectable tìm kiếm thuộc tính đó trên đối tượng Properties, đặt
thêm vào trước tên thuộc tính một tiền tố duy nhất của nó, mà mặc định là tên lớp
của đối tượng Injectable theo sau bởi một dấu gạch chéo (Ghi chú: sử dụng dấu
chấm (dot) sẽ gây ra các vấn đề cho trình phân tích PHP). Điều này làm cho việc
thêm các thuộc tính từ bên ngoài vào trong một cái gì đó, ví dụ như một lớp kết
nối cơ sở dữ liệu trở thành một việc tầm thường, và bạn sẽ làm ngay sau đây. Các
thuộc tính được thêm vào có thể được tham chiếu đến đối tượng đích như các biến
cá thể bình thường, cứ như là chúng đã được đặt trong mã rồi.
Do đó bây giờ bạn có thể thêm bất kỳ thuộc tính nào mà bạn cần vào một đối
tượng bằng cách chỉ rõ giá trị thuộc tính trong một tập tin thuộc tính bên ngoài,
tương tự như hành vi Spring-servlet.xml của Spring. Điều này rõ ràng là một
nhóm phụ rất nhỏ các chức năng của Spring, nhưng lại khá hữu ích trong việc giữ
cho mã Java và mã PHP có cấu trúc tương tự và sạch sẽ.
Viết ActionDispatcher
Để duy trì một sự đối xứng với khung MVC của Spring, bạn sẽ sử dụng các lớp
điều khiển như bạn đã làm trong Spring, mỗi lớp dành cho một yêu cầu, và sử
dụng cùng một phép trừu tượng hóa ánh xạ các khoá URI với các tên lớp điều
khiển, sao cho URI có thể chỉ cần chỉ định rõ một khoá cho yêu cầu đó, và
ActionDispatcher sẽ tạo ra và gọi đúng đối tượng điều khiển để đáp ứng lại yêu
cầu, như trong Liệt kê 7 (đặt ActionDispatcher.php vào trong thư mục con lib).
Liệt kê 7. Lớp ActionDispatcher (PHP)
class ActionDispatcher extends
Injectable {
public function
__construct($properties) {
parent::__construct($properties);
}
public function
dispatchKey($controllerKey) {
try {
$controllerName = $this-
>getProperty($controllerKey);
if (! $controllerName) {
throw new Exception
("ActionDispatcher.createController
-- unknown controller key:
$controllerKey");
}
// load the controller class
require_once("$controllerName.php");
// create an instance of the action's
controller
$controller = eval("return new
$controllerName();");
// give it the application-wide
properties file
$controller->setProperties($this-
>properties);
// let the response call back into
this dispatcher to respond
$response = $controller-
>execute();
$response->respond($this);
} catch (Exception $e) {
echo $e;
exit;
}
}
}
ActionDispatcher làm lớp con của lớp Injectable như vậy bạn có thể tiêm vào các
thuộc tính (các khóa yêu cầu, sẽ trình bày sau). dispatchKey() tìm kiếm khoá đã
cho trong đối tượng Properties (tường minh, không qua phương thức thần kỳ
__get() vì vào lúc này bạn đã có tên của thuộc tính dưới dạng là một chuỗi ký tự
rồi), lấy được tên của lớp điều khiển để thi hành. Nó sử dụng eval() để tạo ra một
cá thể của điều khiển đó (bạn cũng có thể sử dụng các lớp phản chiếu Zend 2 để
làm việc này), đặt đối tượng Properties lên điều khiển đó, và gọi ra phương thức
execute() của trình điều khiển đó, nhận được một đối tượng đáp ứng. Sau đó nó
gọi phương thức respond() của đối tượng đáp ứng, chuyển tham số là chính nó
trong trường hợp đối tượng đáp ứng cần đến. Dãy lời gọi phương thức có chút tiến
rồi lại lui này cho phép bạn thêm vào các kiểu đáp ứng khi cần thiết mà không bao
giờ phải thay đổi execute() của trình điều khiển đó, nhận được một đối tượng đáp
ứng. Sau đó nó gọi phương thức respond() của đối tượng đáp ứng, chuyển tham số
là chính nó trong trường hợp đối tượng đáp ứng cần đến. Dãy lời gọi phương thức
có chút tiến rồi lại lui này cho phép bạn thêm vào các kiểu đáp ứng khi cần thiết
mà không bao giờ phải thay đổi ActionDispatcher -- đấy là tinh thần lập trình
hướng đối tượng.
Các đối tượng đáp ứng xác định thực chất phải làm gì để biểu hiện đáp lại: nó tạo
ra một lớp cho mỗi kiểu đáp ứng để biểu hiện trong ActionDispatcher.php, như
trong Liệt kê 8.
Liệt kê 8. Các lớp đáp ứng của ActionDispatcher
class ModelAndView {
public function
__construct($viewURI,
$model=null) {
$this->viewURI =
$viewURI;
$this->model = $model;
}
public function
respond($dispatcher) {
$model = $this->model;
include($this-
>viewURI);
}
}
class ControllerForward {
public function
__construct($controllerKey)
{
$this->controllerKey =
$controllerKey;
}
public function
respond($dispatcher) {
$dispatcher-
>dispatchKey($this-
>controllerKey);
}
}
Lớp ModelAndView cung cấp cùng một hành vi như ModelAndView của Spring.
Phương thức execute của điều khiển của bạn trả lại một đối tượng ModelAndView
chứa đường dẫn tập tin của khung nhìn (view) để biểu hiện và một đối tượng mô
hình nếu có, và khi ActionDispatcher gọi phương thức respond() của nó, respond()
chỉ làm một việc tầm thường là gửi đi tệp tin khung nhìn tới cho trình xử lý PHP,
bằng cách sử dụng phương thức include(). Khung nhìn được gửi có quyền truy cập
vào các biến trong phạm vi của mã gọi ra, do đó bạn tạo ra một biến có tên $model
chứa đối tượng mô hình được cung cấp, đây là cái mà tất cả các khung nhìn mong
đợi có thể tìm thấy (thậm chí nếu nó là rỗng).
Lớp ControllerForward là để dành cho một trình điều khiển làm một điều gì đó
nhưng sau đó lại muốn chuyển điều khiển đến một trình điều khiển
ActionDispatcher khác. Phương thức respond() của nó chỉ gọi lại
ActionDispatcher với khoá của trình điều khiển mới, khởi động một lần nữa toàn
bộ quá trình đối với trình điều khiển đó (nhưng không phải đọc lại tệp tin các
thuộc tính).
Do tất cả các trình điều khiển phải cung cấp một phương thức execute() và để làm
cho dễ dàng thêm các thuộc tính vào chúng, tất cả chúng sẽ đều là lớp con của lớp
AbstractController (xem Liệt kê 9).
Liệt kê 9. AbstractController (PHP)
abstract class
AbstractController
extends Injectable
{
public abstract
function
execute();
}
Bây giờ bạn có một khung công tác MVC và thêm thuộc tính đơn giản, cho phép
bạn cấu trúc mã của bạn tương tự như mã Java Spring của bạn, loại bỏ việc cần
phải dẫn hướng di chuyển trong hai cấu trúc mã hoàn toàn khác nhau khi bạn di
chuyển qua lại giữa hai ngôn ngữ.
Sử dụng index.php để khởi động việc điều phối yêu cầu
Khi ActionDispatcher sẵn sàng xử lý các yêu cầu, nó cần phải được gọi ra. Hãy
tạo một tệp index.php tối thiểu, hành động như là điểm vào của hệ thống điều phối
(xem Liệt kê 10).
Liệt kê 10. index.php
<?php
ini_set('include_path',
'.;.\client;.\lib;.\app');
require_once('ActionDispatcher.php');
require_once('Properties.php');
$dispatcher =
new ActionDispatcher (new Properties
(array('conf\app.properties',
'conf\db.properties')));
$dispatcher-
>dispatchKey($_REQUEST['controller']);
?>
Lời gọi ini_set thiết lập đường dẫn để bao gồm thêm (include) (chú ý việc sử dụng
';' đối với một đường dẫn bao gồm thêm trong Windows; nó phải là một ':' trên các
hệ thống Linux), sao cho các tệp tin PHP khác không cần phải biết chúng được
yêu cầu lẫn nhau ở đâu. Kịch bản lệnh sau đó tạo ra đối tượng Properties chuyển
giao vào nó toàn bộ các đường dẫn tệp tin thuộc tính được sử dụng trong ứng
dụng, và tạo ra một đối tượng ActionDispatcher với nó. Sau đó nó gọi ra phương
thức dispatchKey() của ActionDispatcher, chuyển giao tham số là giá trị của một
biến yêu cầu trình điều khiển (controller), chứa khoá của điều khiển để tạo và gọi
ra.
index.php đóng một vai trò tương tự như web.xml trong ứng dụng Web Java,
chuyển toàn bộ kiểm soát đến một trình điều phối yêu cầu đơn lẻ cấu hình được;
DispatcherServlet của Spring về phía Java, ActionDispatcher trong PHP.
Tạo ra một proxy đảo ngược từ Apache đến máy chủ ứng dụng
Để ngăn cách thế giới bên ngoài khỏi việc sử dụng hai máy chủ, hãy sửa đổi
httpd.conf và sử dụng một tệp tin .htaccess cho proxy từ Apache đến máy chủ ứng
dụng WebSphere đối với các yêu cầu mà bạn đã thực hiện trong java. Trước tiên,
trong httpd.conf (C:\Program Files\Zend\Apache2\conf\httpd.conf), thực hiện hai
thay đổi:
1. Đảm bảo rằng các dòng trong Liệt kê 11 đã được bỏ dấu chú thích (nghĩa
là, phải chắc chắn rằng chúng không bắt đầu bằng một #).
Liệt kê 11.Kích hoạt mod_rewrite và mod_proxy trong httpd.conf
LoadModule
rewrite_module
modules/mod_rewrite.so
LoadModule proxy_module
modules/mod_proxy.so
LoadModule
proxy_http_module
modules/mod_proxy_http.so
2. Thêm nội dung của Liệt kê 12 vào bất cứ nơi nào trong httpd.conf (nhưng
không phải bên trong một thẻ khác).
Liệt kê 12. Thêm thư mục và uỷ nhiệm (proxying) cho ứng dụng vào
httpd.conf
<Directory "C:/Program
Files/Zend/Apache2/htdocs/fb_stock_demo">
Options FollowSymLinks
AllowOverride All
Order deny,allow
Allow from all
ProxyPass /fb_stock_demo/java
demo/action
ProxyPassReverse /fb_stock_demo/java
demo/action
Việc này tạo ra một định nghĩa cho thư mục fb_stock_demo cho phép bạn sử dụng
.htaccess để kiểm soát nó bằng cách sử dụng lệnh AllowOverride All và tạo ra một
proxy đảo ngược bằng cách sử dụng mod_proxy, sao cho bất kỳ yêu cầu nào bắt
đầu bằng /fb_stock_demo/java sẽ được chuyển hướng đến DispatcherServlet của
Spring (ánh xạ đến URI hành động trong web.xml) chạy trong máy chủ ứng dụng
WebSphere.
Để làm cho các thay đổi này có hiệu lực, khởi động lại Apache bằng cách mở một
dấu nhắc lệnh, vào thư mục bin của Apache2 (C:\Program
Files\Zend\Apache2\bin), và ra các lệnh httpd.exe -k stop và httpd.exe -k start.
Không sử dụng lệnh khởi động lại; trên Windows nó sẽ chết một cách thầm lặng
nếu nó không tắt được Apache. Nếu Zend Core đã cài đặt nó như một dịch vụ
Windows, bạn có thể phải ngừng nó lại thông qua trình quản lý dịch vụ Windows
để có thể ngừng và khởi động nó từ dấu nhắc lệnh, hoặc tắt qua trình quản lý Task
Manager.
Sử dụng .htaccess để điều phối các yêu cầu tới PHP hoặc tới Java
Do bạn đã có một cơ chế trung tâm để định tuyến các yêu cầu đến ứng dụng Java,
bạn cần một cách để ánh xạ các yêu cầu cụ thể đến đúng các trình điều khiển PHP
hoặc Java. Khi apache khởi động lại, tạo ra một tập tin .htaccess trong c:\Program
Files\Zend\Apache2\htdocs\fb _stock_demo có chứa nội dung của Liệt kê 13.
Liệt kê 13. .htaccess
RewriteEngine on
RewriteCond
%{QUERY_STRING} (.*)
RewriteRule ^php/(.*)
index.php?controller=$1&%1
[last]
RewriteRule ^phpDbTest$
php/dbTest [next]
RewriteRule ^stockList$
java/stockList [next]
Dòng đầu tiên bật cho phép việc viết lại URL cho thư mục này. Cặp
RewriteCond/RewriteRule tạo ra một giao thức để gọi ra index.php; tất cả các yêu
cầu dưới thư mục fb_stock_demo bắt đầu bằng php/được chuyển đến index.php,
thiết lập một biến yêu cầu trình điều khiển thành tất cả các ký tự tìm thấy sau php/,
và nối thêm bất kỳ biến yêu cầu nào khác sau đó. Thí dụ,
sẽ được viết lại thành
Sau đó bạn có thể tạo ra RewriteRules riêng để định tuyến các yêu cầu cụ thể tới
các trình điều khiển cụ thể chạy trong Zend Core hoặc IBM WebSphere.
RewriteRule thứ hai định tuyến URL “phpDbTest”, ví dụ,
đến
rồi lại được viết lại một lần nữa
bởi quy tắc đầu tiên trở thành
RewriteRule thứ ba
viết lại URI “stockList”, ví dụ thế, thành
sau đó được định nghĩa proxy đảo
ngược trong httpd.conf viết lại thành
demo/action/stockList, rồi trình điều phối Spring định tuyến đến
StockListController. Xem tài liệu về mod_rewrite để biết thêm thông tin về mô
đun Apache rất hữu ích này trong Tài nguyên.
Để kiểm thử proxy đảo ngược và trình đơn điều phối PHP/Java mà bạn đã tạo ra
trong .htaccess, trong trình duyệt của bạn hãy vào
và một lần nữa bạn sẽ thấy danh mục
chứng khoán dưới dạng XML, được chuyển từ trình điều khiển Java. Giờ thì bạn
đã có một cơ chế gọn gàng để gọi ra ứng dụng từ thế giới bên ngoài (tức
Facebook) trong khi tách rời thế giới bên ngoài khỏi việc sử dụng hai công nghệ
máy chủ của bạn.
Hình 5 minh hoạ chuỗi điều phối của một yêu cầu từ trình duyệt của người sử
dụng đến một trình điều khiển PHP hay Java.
Hình 5. Đường đi của một yêu cầu
Kết nối với cơ sở dữ liệu trong Java
Do bạn đã có một mẫu MVC giống nhau được lập ra trong cả bên Java lẫn bên
PHP của các ứng dụng, bạn sẽ kết nối vào cơ sở dữ liệu phía Java. Bạn sẽ sử dụng
nó để xử lý các khía cạnh an toàn hơn của ứng dụng Facebook của bạn – nguồn
cung cấp giá cổ phiếu và các việc kinh doanh cổ phiếu thật.
Thiết lập kết nối cơ sở dữ liệu Java
Để thiết lập kết nối cơ sở dữ liệu Java, hãy tạo ra một nguồn dữ liệu bằng pool kết
nối DB2 trong IBM WebSphere với vai trò một nguồn dữ liệu JNDI, và sau đó
tham chiếu nguồn dữ liệu từ trong ứng dụng Spring. Sau đó, tạo ra một trình điều
khiển Spring và khung nhìn tương ứng, sử dụng nguồn dữ liệu này để biểu hiện cơ
sở dữ liệu về chứng khoán dưới dạng XML. Hình 6 đưa ra cái nhìn khái quát về tất
cả các mảnh dính đến nguồn dữ liệu Java.
Hình 6. Các thành phần của một nguồn dữ liệu DB2 JNDI được sử dụng
trong một ứng dụng Spring chạy trong máy chủ ứng dụng WebSphere của
IBM
Tạo một nguồn dữ liệu với pool kết nối trong Máy chủ ứng dụng WebSphere
Trước khi bạn tạo ra bản thân nguồn dữ liệu, bạn cần phải tạo một biệt danh xác
thực để đăng nhập cơ sở dữ liệu, vì WebSphere Application Server quản lý tập
trung toàn bộ dữ liệu xác thực:
1. Mở rộng phần Security phía bên trái.
2. Nhấn vào Secure administration, applications, and infrastructure.
3. Dưới phần Authentication, mở rộng Java Authentication and Authorization
Service.
4. Nhấn J2C Authentication data.
5. Thêm một xác thực mới với biệt danh StocksDB2Login. Do DB2 sử dụng
hệ điều hành để xác thực người dùng, gõ nhập tên người dùng và mật khẩu
đăng nhập vào hệ điều hành của bạn.
6. Nhấn OK và lưu các thay đổi của bạn vào cấu hình chính.
7. Để tạo (Data Source) nguồn dữ liệu, trong bàn điều khiển Administrative
Console dưới Resources chọn JDBC > Data sources.
8. Chọn máy chủ của bạn (server1) trong trình đơn thả xuống Scope và nhấn
New.
9. Chỉ rõ jdbc/StocksDataSource là tên nguồn dữ liệu và cũng là tên JNDI.
10. Chọn biệt danh xác thực DB2 của bạn (StocksDB2Login) trong trình đơn
thả xuống, và nhấn Next.
11. Tạo một bộ cung cấp JDBC mới với các giá trị sau:
o Kiểu cơ sở dữ liệu: DB2.
o Kiểu bộ cung cấp: DB2 Universal JDBC Driver Provider (Bộ cung
cấp điều khiển JDBC tổng hợp DB2).
o Kiểu thực hiện: Connection pool data source (Nguồn dữ liệu với
pool kết nối).
o Tên: DB2 Universal JDBC Driver Provider.
12. Trên màn hình thông tin đường dẫn của lớp, gõ nhập đường dẫn chứa
db2jcc.jar, C:\Program Files\IBM\SQLLIB\java, và nhấn Next.
13. Trên màn hình thuộc tính riêng cho cơ sở dữ liệu, gõ nhập các giá trị sau:
o Tên cơ sở dữ liệu: stocks (là tên của cơ sở dữ liệu DB2 mà bạn đã
tạo ra trong Phần 1 của hướng dẫn này).
o Kiểu điều khiển: 4
o Tên máy chủ: localhost
o Số cổng: 50000. Bạn có thể xác minh điều này bằng cách mở bàn
điều khiển DB2 (Start > All Programs > IBM DB2 > DB2COPY1
(default) > General Administration Tools > Control Center), tìm
cá thể DB2 dưới All Systems, nhấn “Configure Parameters”, và nhấn
nút Properties cạnh TCP/IP.
14. Nhấn Finish và lưu vào cấu hình chính trên màn hình tiếp theo.
15. Chọn nguồn dữ liệu mới của bạn trong danh sách và nhấn Test connection.
Máy chủ WebSphere Application Server bây giờ sẽ báo cáo rằng việc kết nối đã
thành công.
Thêm nguồn dữ liệu vào ứng dụng web của bạn
Để ứng dụng web của bạn có thể truy cập vào nguồn dữ liệu JNDI mà bạn đã tạo
ra trong thùng chứa (container), hãy thêm một phần tử vào
web.xml (xem Liệt kê 14).
Liệt kê 14. Bộc lộ nguồn dữ liệu JNDI cho ứng dụng web
DB2 Database
Connection
<res-ref-
name>jdbc/StocksDataSource</res-
ref-name>
<res-
type>javax.sql.DataSource</res-
type>
Container</res-
auth>
Để sau đó cung cấp cho Spring khả năng truy cập nguồn dữ liệu, bạn thêm một
bean cho nó vào spring-servlet.xml, và sửa đổi định nghĩa bean điều khiển để thêm
nguồn dữ liệu vào StockListController (xem Liệt kê 15).
Liệt kê 15. Cung cấp nguồn dữ liệu JNDI như là một bean Spring
<bean id="dataSource"
class="org.springframework.jndi.JndiObjectFactoryBean">
java:comp/env/jdbc/StocksDataSource
<bean id="stockListController"
class="com.jm.fbstockdemo.StockListController">
stockList.jsp
Sử dụng bean DataSource trong các trình điều khiển của bạn
Không trộn lẫn SQL vào logic điều khiển của bạn, hãy đặt tất cả các truy vấn SQL
của bạn vào một lớp StocksDao mà bạn cũng có thể làm thành một bean Spring,
rồi thêm nó vào bất kỳ điều khiển nào cần đến nó (xem Liệt kê 16).
Liệt kê 16. Thêm một bean StocksDao của Spring
<bean id="stocksDao"
class="com.jm.fbstockdemo.StocksDao">
StocksDao có thể chỉ cần tập trung vào việc thực hiện các truy vấn SQL, khi biết
dữ liệu của nó sẽ ở đó khi nó được Spring tạo ra và kết nối (xem Liệt kê 17).
Liệt kê 17. StocksDao (lớp Java)
public class StocksDao {
private SimpleJdbcTemplate
jdbcTemplate;
public StocksDao(DataSource
dataSource) {
super();
this.jdbcTemplate = new
SimpleJdbcTemplate(dataSource);
}
public List
fetchAllStocks() {
return
jdbcTemplate.query("select * from
stock",
new
ParameterizedRowMapper
() {
public Stock
mapRow(ResultSet rs, int row)
throws SQLException {
return new
Stock(rs.getInt("id"),
rs.getString("ticker"));
}
});
}
Spring sẽ gọi hàm tạo của DAO của bạn bằng bean dataSource khi tạo ra và kết
nối các bean lúc khởi động, và hàm tạo này tạo ra một cá thể của lớp
SimpleJdbcTemplate của Spring với nó. fetchAllStocks() sử dụng
SimpleJdbcTemplate để sắp xếp hợp lý truy vấn SQL; nó tìm nạp tất cả các hàng
trong bảng “stocks” và ánh xạ chúng vào các đối tượng Stock bằng cách sử dụng
lớp trong vô danh ParameterizedRowMapper. SimpleJdbcTemplate và
ParameterizedRowMapper sử dụng Java chung thông thường (như với Java 1.5)
để mapRow() trả lại một đối tượng Stock thực sự (xem mã kèm theo) chứ không
phải là một đối tượng mà nó ép kiểu thành một Stock. Mã được tạo ra sẽ thực sự
làm việc ép kiểu này, nhưng các lớp được tham số hóa lại buộc phải tuân theo sự
an toàn về kiểu vào lúc biên dịch.
Do tất cả các trình điều khiển của bạn cần phải truy vấn cơ sở dữ liệu, sẽ có một
khung nhìn mà chúng chuyển tiếp đến khi thành công, và cũng sẽ cần truy cập vào
giá cổ phiếu, hãy tạo ra một lớp cơ sở trừu tượng, AbstractStockDemoController,
nằm bên trên một StocksDao, một giá trị successView và một đối tượng
StockPriceSource được Spring thêm vào (xem Liệt kê 18).
Liệt kê 18. Tạo một lớp cơ sở trừu tượng
public abstract class
AbstractStockDemoController
implements Controller {
private StocksDao dao;
private String successView;
public void
setDao(StocksDao dao) {
this.dao = dao;
}
protected StocksDao
getDao() {
return dao;
}
protected String
getSuccessView() {
return successView;
}
public void
setSuccessView(String
successView) {
this.successView =
successView;
}
}
Sau đó sửa đổi StocksListController để nó mở rộng lớp cơ sở này và sử dụng
StocksDao để cung cấp dữ liệu cho khung nhìn (xem Liệt kê 19).
Liệt kê 19. StockListController cung cấp dữ liệu mô hình cho khung nhìn
public class StockListController
extends
AbstractStockDemoController {
public ModelAndView
handleRequest(HttpServletRequest
request,
HttpServletResponse
response) throws Exception {
List stocks =
getDao().fetchAllStocks();
return new ModelAndView
(getSuccessView(), "stocks",
stocks); }
}
StockListController bây giờ tìm nạp các cổ phiếu từ StocksDao và cung cấp các cổ
phiếu như là mô hình, dưới tên bean JSP “stocks”, trả lại giá trị successView được
Spring thêm vào như là khung nhìn đáp ứng để biểu hiện.
Để kiểm tra việc kết nối cơ sở dữ liệu, hãy thay stockList.jsp bằng nội dung của
Liệt kê 19, cung cấp các cổ phiếu như là một nguồn cấp XML.
Liệt kê 19. stockList.jsp cung cấp dữ liệu từ DB2
<%@ page contentType="text/xml"
%>
<%@ taglib prefix="c"
uri=""
%>
<c:forEach items="${stocks}"
var="stock">
<c:out
value="${stock.id}"/>
<c:out
value="${stock.ticker}"/>
Cập nhật ứng dụng web trong máy chủ ứng dụng WebSphere
Cuối cùng, để xem thành quả lao động của bạn, tái xuất WAR và cập nhật ứng
dụng web trong máy chủ ứng dụng WebSphere qua bàn điều khiển Administrative
Console.
1. Mở rộng phần ứng dụng, nhấn Enterprise Applications, chọn ứng dụng
web của bạn trong danh sách và nhấn Update.
2. Nhấn nút Browse dưới Specify the path to the replacement ear file (việc
này cũng áp dụng với một tệp tin WAR), chọn tệp tin WAR của bạn như
trước đây, và phải bảo đảm chắc chắn chỉ rõ lại gốc bối cảnh (/facebook-
stock-demo) trước khi nhấn Next.
3. Nhấn Next một lần nữa trên màn hình tùy chọn tiếp theo, phải chắc chắn
chọn ứng dụng web của bạn trên màn hình Map modules to servers (ánh xạ
các mô-đun tới các máy chủ) trước khi nhấn vào Next ở đó. Vì bạn lần đầu
tiên thêm một nguồn dữ liệu vào ứng dụng web, màn hình tiếp theo lúc này
là một màn hình Map resource references to resources (Ánh xạ các tham
chiếu nguồn tài nguyên đến các tài nguyên).
4. Chọn Use default method đối với phương thức xác thực, chọn biệt danh
xác thực StocksDB2Login.
5. Chọn ứng dụng web của bạn trong bảng, Nhấn Browse dưới Target JNDI
Name, chọn tên jdbc/StocksDataSource JNDI, nhấn Apply, nhấn Next và
nhấn Finish.
6. Đợi máy chủ ứng dụng WebSphere bố trí lại ứng dụng, và nhấn vào Save
dưới đáy màn hình kết quả để lưu các thay đổi của bạn.
Như trước đây, trong trình duyệt Web vào
và giờ bạn sẽ nhìn thấy các cổ phiếu
thực sự từ cơ sở dữ liệu dưới dạng XML.
Kết nối cơ sở dữ liệu trong PHP
Bây giờ bạn sẽ kết nối vào cùng một cơ sở dữ liệu DB2 từ PHP chạy trong Zend
Core for IBM, và tạo ra một trình điều khiển và khung nhìn để kiểm tra kết nối đó.
Để duy trì một sự trừu tượng hóa tương tự như sự trừu tượng hóa DataSource bên
phía Java, bạn sẽ tạo ra một lớp Db2DataSource chịu trách nhiệm về duy trì kết
nối với DB2 và về các giao dịch đối với kết nối đó, và sẽ sử dụng đối tượng
Properties đối với các giá trị kết nối/đăng nhập của nó. Bạn cũng sử dụng một lớp
StocksDao như bạn đã làm trong Java, lớp này sử dụng một Db2DataSource để
truy cập vào các bảng của ứng dụng. Sử dụng một cấu trúc chung trong các nửa
Java và PHP của ứng dụng sẽ cho phép bạn di chuyển giữa chúng dễ dàng hơn,
cho phép bạn thực hiện các đặc tính của ứng dụng Facebook của bạn trong bất kỳ
công nghệ nào thích hợp hơn mà không cần lo lắng đến việc sửa đổi các mã đó.
Giao tiếp với DB2
Trước tiên hãy viết Db2DataSource để đóng gói việc truy cập DB2. Trong thư
mục con lib, tạo tệp Db2Database.php như trong Liệt kê 20.
Liệt kê 20. Lớp Db2DataSource (PHP)
class Db2DataSource extends
Injectable {
private $connection;
public function
__construct($properties,
$persist=true) {
parent::__construct($properties);
$this->connect ($persist);
}
private function connect
($persist=true) {
$connectionString =
"DRIVER={IBM DB2
ODBC DRIVER};" .
"DATABASE=$this-
>database;" .
"HOSTNAME=$this-
>hostname;" .
"PORT=$this->port;" .
"PROTOCOL=TCPIP;" .
"UID=$this->username;" .
"PWD=$this->password;";
if ($persist) {
$this->connection =
db2_pconnect($connectionString,
'', '');
} else {
$this->connection =
db2_connect($connectionString,
'', '');
}
if (! $this->connection) {
throw new Exception
("Db2DataSource -- couldn't
connect to DB2: " .
db2_conn_errormsg());
}
}
public function close() {
if ($this->connection) {
db2_close($this-
>connection);
}
}
}
Hàm tạo này nhận một đối tượng Properties vì nó là một đối tượng Injectable, và
một cờ báo $persist xác định xem liệu có tạo ra một kết nối cơ sở dữ liệu tồn tại
lâu dài phục vụ nhiều yêu cầu hay là một kết nối được tạo mới mỗi lần. connect()
tạo ra xâu ký tự kết nối DB2 tiêu chuẩn có chứa trình điều khiển, giao thức, và
thông tin kết nối cho riêng cơ sở dữ liệu này. Phương thức close() đóng lại kết nối
nếu có một kết nối hợp lệ tồn tại. Lưu ý rằng connect() tham chiếu đến các giá trị
ấy như là các biến cá thể, mặc dù chúng thực sự được xác định trong một tệp tin
thuộc tính (trình bày dưới đây); lớp con Injectable ngăn cách Db2DataSource khỏi
chi tiết này chứ không phải cần chấp nhận một đối tượng Properties trong hàm tạo
của nó.
Bây giờ bạn có thể kết nối với DB2, bạn có thể truy vấn nó và viết dữ liệu lên nó.
Bắt đầu với một phương thức executeQuery() chung, nó gói lời gọi db2_exec() và
đưa ra một lỗi ngoại lệ báo cáo lại bất kỳ thông báo lỗi nào nó nhận được qua
db2_stmt_errormsg() nếu việc truy vấn thất bại (xem Liệt kê 21).
Liệt kê 21. Db2DataSource.executeQuery()
public function executeQuery($query) {
$result = db2_exec($this->connection,
$query);
if ($result == null) {
throw new
Exception("Db2DataSource.executeQuery
failed on query [$query],
DB2 error is " . db2_stmt_errormsg());
}
return $result;
}
Sau đó thêm một phương thức fetchObjects() sử dụng executeQuery(), trả lại một
mảng các đối tượng PHP để đáp ứng một truy vấn SQL (xem Liệt kê 22). Lưu ý
rằng db2_fetch_object() đặt các tên trường lên các đối tượng được trả về toàn bộ
viết hoa (ALL CAPS), ví dụ, $stock->TICKER, chứ không phải là $stock->ticker.
Liệt kê 22. Db2Database.fetchObjects()
public function
fetchObjects($query) {
$result = $this-
>executeQuery($query);
$objects = array();
while ($rowObject =
db2_fetch_object($result))
{
$objects[] =
$rowObject;
}
return $objects;
}
Do bạn đã có một lớp chung để kết nối với DB2 và thi hành các truy vấn DB2,
như bạn đã làm trên mã phía Java, bạn sẽ tạo ra một lớp StocksDao có chứa các
truy vấn riêng cho ứng dụng này.
Lớp StocksDao
StocksDao sẽ chứa toàn bộ các truy vấn SQL thực tế, cũng giống như nó làm trong
mã phía Java. Trước tiên, chúng ta hãy thêm vào một phương thức để thu thập tất
cả các cổ phiếu đang có sẵn (xem Liệt kê 23).
Liệt kê 23. StocksDao.php
<?php
class StocksDao {
private $db;
public function
StocksDao($db) {
$this->db = $db;
}
public function
fetchAllStocks() {
return $this->db-
>fetchObjects('select
* from stock');
}
}
?>
Lưu ý rằng StocksDao dựa trên một đối tượng $db (một Db2DataSource) mà nó
sử dụng cho toàn bộ các truy cập cơ sở dữ liệu, và do đó StocksDao sẽ hầu như
không chứa mã lệnh nào khác trừ các truy vấn SQL riêng cho ứng dụng mà bạn
cần.
Hình 7 cung cấp một bản đồ của các thành phần truy cập dữ liệu PHP để so sánh
với sơ đồ tương tự về phía mã Java trong Hình 6. Nguồn dữ liệu Java liên quan
đến nhiều thành phần chi tiết hơn và yêu cầu công việc cấu hình nhiều hơn, nhưng
bù lại cung cấp sự an toàn, khả năng mở rộng nhiều hơn và một tiêu chuẩn công
nghiệp.
Hình 7. Truy cập dữ liệu trong PHP
Sử dụng một lớp cơ sở điều khiển trừu tượng trong PHP
Hãy nhớ lại rằng ActionDispatcher sẽ tạo ra một trình điều khiển PHP, cung cấp
cho nó một đối tượng Properties và gọi một phương thức execute() của nó, trông
đợi nhận lại một đối tượng ModelAndView để biểu hiện khung nhìn, chính xác
như ở bên mã Java. Vì bạn sẽ cần một kết nối cơ sở dữ liệu trong tất cả các trình
điều khiển của mình, hãy cho tất cả chúng trở thành lớp con của lớp
AbstractStockDemoController mà chính lớp này lại là lớp con của
AbstractController (xem Liệt kê 24). Toàn bộ mã PHP chỉ riêng cho ứng dụng của
bạn phải đặt trong thư mục con app của fb_stock_demo.
Liệt kê 24. Lớp AbstractStockDemoController (PHP)
abstract class
AbstractStockDemoController
extends AbstractController {
protected $db;
protected $dao;
public function __construct()
{
}
public function execute() {
try {
$this->db = new
Db2DataSource($this-
>properties, 'db');
$this->dao = new
StocksDao ($this->db);
$response = $this-
>executeSpecific();
$this->db->close();
return $response;
} catch (Exception $e) {
$this->db->close();
throw $e;
}
}
protected abstract function
executeSpecific();
}
AbstractStockDemoController triển khai thực hiện phương thức execute() được
ActionDispatcher gọi ra, kết nối vào cơ sở dữ liệu bằng cách sử dụng tệp tin thuộc
tính được thêm vào, quy định db làm tiền tố để sử dụng khi tìm kiếm các thuộc
tính kết nối cơ sở dữ liệu, tạo ra một StocksDao từ nó để các lớp con sử dụng, và
gọi ra phương thức executeSpecific() trừu tượng. Lớp con triển khai
executeSpecific() xử lý các chi tiết cụ thể của yêu cầu. Execute() cũng đảm bảo
đóng kết nối cơ sở dữ liệu. Chú ý rằng vì PHP không cung cấp một cấu kiện
finally như trong mã Java, bạn cần phải làm điều này cả trong khối try và khối
catch. Bạn cung cấp phương thức rỗng __construct() sao cho lớp con có thể gọi
parent::__construct() (nó không cần biết rằng nó không phải làm việc đó đối với
lớp cơ sở riêng này).
Kiểm tra nguồn dữ liệu PHP bằng một trình điều khiển và khung nhìn
Với lớp trình điều khiển trừu tượng đã sẵn sàng, bạn có thể tạo ra một lớp con,
DbTestController, để thử nghiệm kết nối cơ sở dữ liệu, như trong Liệt kê 25. Đặt
tệp DbTestController.php trong thư mục con app dưới fb_stock_demo.
Liệt kê 25. Lớp PHP DbTestController
class DbTestController
extends
AbstractStockDemoController
{
public function
executeSpecific() {
return new ModelAndView
("dbTestView.php",
$this->dao-
>fetchAllStocks());
}
}
Lớp này trông rất quen thuộc. Phương thức executeSpecific(), do phương thức
execute() của lớp cơ sở gọi ra, tìm nạp các các cổ phiếu và trả lại khung nhìn
(dbTestView.php) và mô hình (mảng các đối tượng Stock), đúng như trình điều
khiển đã làm bên mã Java, và ActionDispatcher sẽ biểu hiện dbTestView.php bằng
cách sử dụng mô hình các cổ phiếu đã được cung cấp (xem Liệt kê 26). Đặt tệp
dbTestView.php trong thư mục con app cùng với trình điều khiển.
Liệt kê 26. dbTestView.php
The result of
calling
DbTestController
was:
<?
foreach ($model
as $stock):
?>
Stock <?=
$stock->ID ?>:
<?= $stock-
>TICKER ?>
<?
endforeach;
?>
Chú ý rằng bạn phải truy cập vào các trường của các đối tượng trả lại bằng cách sử
dụng ALL CAPS, vì đây là cách mà db2_fetch_object() đã tạo ra các đối tượng
hàng.
Bạn đã tạo nên một mục cho trình điều khiển này trong .htaccess dưới khoá yêu
cầu phpDbTest để gửi đến phía PHP của ứng dụng; bây giờ bạn cần cung cấp một
khóa cho ActionDispatcher. Do khoá này được thêm vào, hãy tạo một
app.properties có chứa một mục cho trình điều khiển mới (xem Liệt kê 27), trong
một thư mục con conf dưới fb_stock_demo.
Liệt kê 27. app.properties
ActionDispatcher/dbTest=DbTestController
Cuối cùng, để cung cấp thông tin kết nối cơ sở dữ liệu, hãy tạo tệp tin
db.properties bên cạnh app.properties, có chứa nội dung của Liệt kê 28.
Liệt kê 28. db.properties
Db2DataSource/database=stocks
Db2DataSource/hostname=localhost
Db2DataSource/port=50000
Db2DataSource/username=[your
operating system username]
Db2DataSource/password=[your
operating system password]
Bạn có thể thêm bất cứ thuộc tính nào khác vào bất kỳ lớp nào mà bạn muốn bằng
cách tạo ra các mục tương tự như vậy trong app.properties (hoặc một tập tin khác,
miễn là index.php bao gồm cả nó khi tạo ra đối tượng Properties).
Để xác nhận rằng khung công tác MVC hạng nhẹ của bạn và kết nối DB2 đang
làm việc bên phía PHP, truy cập trong
trình duyệt, và bạn sẽ thấy khung nhìn của bạn được điền đầy bằng các cổ phiếu từ
cơ sở dữ liệu.
Tóm tắt
Kết hợp các ngôn ngữ Java và PHP vào chỉ một ứng dụng có thể cảm thấy như kết
hợp táo với cam. Do bản chất, ngôn ngữ lập trình Java áp đặt rất nhiều cấu trúc lên
mã lệnh, và giới ngôn ngữ Java có xu hướng hội tụ nhanh chóng đến các mẫu và
khung công tác phổ biến, trong khi giới PHP có cấu trúc ít hơn nhiều và được
chuẩn hóa ít hơn nhiều, đôi khi làm cho các ứng dụng PHP trở thành một tập hợp
các kịch bản lệnh liên quan nhau không rõ nét, mỗi kịch bản có cách tiếp cận sự
vật riêng của nó. Nhưng với một số quan tâm thiết kế hai thế giới này có thể trở
thành ngày càng giống nhau hơn. Trong hướng dẫn này, bạn đã khám phá ra một
cách tiếp cận để tích hợp hai công nghệ này trong khi vẫn duy trì một số mã lệnh
đối xứng giữa hai thế giới. Với những nền móng đã xây dựng, Phần 3 sẽ đảm nhận
các chi tiết cụ thể của việc thực hiện một ứng dụng Facebook đầy đủ chức năng
bằng cách sử dụng FBML, FBJS, Facebook API trong cả hai ngôn ngữ Java và
PHP, và các mẫu MVC và truy cập dữ liệu tương đối đối xứng mà bạn đã thiết lập
sẵn sàng ở đây để tạo ra một ứng dụng quản lý danh mục đầu tư cổ phiếu với các
tính năng mạng xã hội, biến nó thành một trò chơi có tính cạnh tranh.
Các file đính kèm theo tài liệu này:
- Làm chủ việc phát triển ứng dụng Facebook bằng PHP, IBM Rational Application Developer, IBM WebSphe_.pdf