ch5 struts2 framework

84
CÔNG NGHJAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK Nguyn Nghim - Nht ngh320 CHƯƠNG 5: STRUTS 2X 5.1 Gii thiu 5.1.1 Mô hình MVC MVC (Model-View-Controller) là mô hình lp trình phbiến nht hin nay. Mô hình này gm 3 phn: Model: có nhim vqun lý dliu ca ng dng View: to giao diện để hin thcho người dùng Controller: tiếp nhn yêu cu tngười dùng, điều khin stương tác giữa Model và View. Ba phn hoặc động độc lp trong ng dng. Controller tiếp nhn yêu cu tngười dùng sau đó chun bModel để chia svi View. View chviệc khai thác Model được chun bsn tController để to giao din phù hợp để đáp ứng yêu cu của người dùng. Hình: Mô hình MVC Struts 2x là một framework được xây dựng trên cơ sở ca mô hình MVC cũng là nội dung ca giáo trình này.

Upload: tam-phong

Post on 31-Dec-2015

637 views

Category:

Documents


5 download

TRANSCRIPT

Page 1: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 320

CHƯƠNG 5: STRUTS 2X

5.1 Giới thiệu

5.1.1 Mô hình MVC

MVC (Model-View-Controller) là mô hình lập trình phổ biến nhất hiện nay. Mô hình này gồm 3

phần:

Model: có nhiệm vụ quản lý dữ liệu của ứng dụng

View: tạo giao diện để hiển thị cho người dùng

Controller: tiếp nhận yêu cầu từ người dùng, điều khiển sự tương tác giữa Model và

View.

Ba phần hoặc động độc lập trong ứng dụng. Controller tiếp nhận yêu cầu từ người dùng sau đó

chuẩn bị Model để chia sẻ với View. View chỉ việc khai thác Model được chuẩn bị sẵn từ

Controller để tạo giao diện phù hợp để đáp ứng yêu cầu của người dùng.

Hình: Mô hình MVC

Struts 2x là một framework được xây dựng trên cơ sở của mô hình MVC – cũng là nội dung của

giáo trình này.

Page 2: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 321

5.1.2 Cài đặt môi trường

Để lập trình được với Struts 2x, bạn cần bổ sung các thư viện cần thiết sau đây vào thư mục

WEB-INF/lib.

Bước 1: Download thư viện (struts-2.0.14-all.zip) tại địa chỉ:

http://struts.apache.org/download.cgi

Bước 2: Giải nén struts-2.0.14-all.zip

Bước 3: Chép tất cả các tập tin thư viện trong thư mục lib vào WEB-INF/lib của web

project

Chú ý: bạn phải cài JDK, Eclipse và Tomcat trước khi thực hiện thiết lập môi trường cho

Struts2x.

5.1.3 Kiến trúc công nghệ Struts2

Đứng ở mức cao, bạn có thể nhìn thấy Struts2 gồm 5 thành phần cột lõi như hình sau.

1. Actions

2. Interceptors

3. Value Stack / OGNL

4. Results / Result types

5. View technologies

Page 3: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 322

Dù có hơi khác một chút với mô hình lập trình MVC truyền thống nhưng vẫn tuân thủ mô hình

lập trình MVC, cụ thể được phân chia như sau:

Controller gồm Dispatcher Filter và các Intercepters

Model là Action

View gồm một số loại trong đó JSP là chính

Còn StackValue/OGNL là đầu mối các thông tin cần chia sẻ được truy xuất và quản lý bởi Model

và View.

Sau đây là qui trình xử lý một yêu cầu

1. Người dùng gửi yêu cầu đến server để thực hiện một công việc nào đó

2. DispatcherFilter tiếp nhận yêu cầu và xác định Action được yêu cầu

3. Một số Intercepter tiền xử lý (kiểm lỗi, upload...) được cấu hình sẽ hoạt động

4. Action được yêu cầu được thực hiện

5. Một số Intercepter hậu xử lý được cấu hình sẽ hoạt động

6. Cuối cùng kết quả được chuẩn bị và chuyển tiếp sang view để sinh giao diện và hiển thị

5.1.4 Struts2 Hello World

Khám phá ứng dụng “Hello World” sau đây sẽ giúp bạn dễ dàng hiểu một cách cơ bản về

nguyên lý hoạt động của Struts 2x.

Khi người dùng click vào một liên kết hay một nút submit thì một hành động trong lớp Action sẽ

được yêu cầu. Ngay lập tức Controller sẽ thu thập thông tin đầu vào sau đó chuyển cho Action

Page 4: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 323

được yêu cầu. Action sẽ thực thi yêu cầu và sinh kết quả và chuyển tiếp về View để hiển thị cho

người dùng.

Trong ví dụ sau chúng ta phải thực hiện các công việc cụ thể sau đây để hiện thực ví dụ Hello

World:

Thành phần Mô tả

Action

(HelloWorldAction.java)

Lớp chứa phương thức xử lý yêu cầu người dùng (action method)

View

(HelloWorld.jsp)

Trang JSP dùng để hiển thị kết quả sau khi xử lý

Configuration

(struts.xml)

Tập tin cấu hình thiết lập mối liên hệ giữa action và các đầu ra (View)

Đương nhiên chúng ta còn cần index.jsp chứa form yêu cầu để người dùng nhập liệu cũng như

các khâu chuẩn bị cần thiết khác như tạo project, chuẩn bị thư viên...

Cụ thể trong bài này bạn sẽ tạo ra một project có cấu trúc sau đây

Bước 1: Tạo Dynamic Web Project

Tạo Project

Trong eclipse bạn tạo một Dynamic Web Project với tên HelloWorldStruts2 như hướng dẫn sau:

Page 5: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 324

Page 6: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 325

Bổ sung thư viện

Sau đây là các thư viện cần thiết cho ứng dụng Struts2 cơ bản. Bạn cần chép vào thư mục

WEB-INF/lib của Project.

commons-fileupload-x.y.z.jar

commons-io-x.y.z.jar

Page 7: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 326

commons-lang-x.y.jar

commons-logging-x.y.z.jar

commons-logging-api-x.y.jar

freemarker-x.y.z.jar

javassist-.xy.z.GA

ognl-x.y.z.jar

struts2-core-x.y.z.jar

xwork-core.x.y.z.jar

Bước 2: Tạo Action Class (HelloWorldAction.java)

Lớp Action là thành phần chính yếu của ứng dụng Struts. Nó thực hiện các vấn đề nghiệp vụ để

đáp ứng yêu cầu. Lớp này được đặt trong thư mục Java Resources/src và cả thư mục package

của lớp (Ví dụ nnghiem.struts). Khi người dùng click vào URL thì một hoặc nhiều phương thức

hành động trong lớp Action sẽ chạy. Kết quả của phương thức hành động là một chuỗi chỉ ra

cài View được lựa chọn để hiển thị.

package nnghiem.struts; import com.opensymphony.xwork2.ActionSupport; /* * Lớp Action trong struts2 */ public class HelloWorldAction extends ActionSupport{ /* * Phương thức Action */ public String execute() throws Exception { return "success"; } /* * Thuộc tính của lớp action */ private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }

Trên đây là lớp Action đơn giản gồm một phương thức hành động là “execute()” luôn trả về

“success” và một thuộc tính có tên là “name” tuân theo qui ước của JavaBean (getter/setter).

Page 8: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 327

Struts Framework sẽ tạo một object từ HelloWorldAction và gọi phương thức execute() khi có

yêu cầu từ người dùng.

Bước 3: Tạo View (HelloWorld.jsp)

View là trang JSP sử dụng để hiển thị kết của cho người dùng

<%@ page contentType="text/html; charset=utf8" pageEncoding="utf8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <html> <head> <title>Hello World</title> </head> <body> Hello World, <s:property value="name"/> </body>

</html>

Ở dòng thứ 2 (từ trên xuống) dùng để khai báo thư viện thẻ struts2

Dòng thứ 3 (từ dưới lên) dùng để hiển thị thuộc tính name (phương thức getName())

được định nghĩa trong lớp Action. Bạn có thể thay bằng cách truy xuất của EL là

${name}

Bước 4: Tạo form đầu vào (index.jsp)

Trang index.jsp chứa form nhập liệu cung cấp cho HelloWorldAction có mã jsp như sau

<%@ page contentType="text/html; charset=utf8" pageEncoding="utf8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>Hello World</title> </head> <body> <h1>Hello World From Struts2</h1> <form action="hello"> <label for="name">Please enter your name</label><br/> <input type="text" name="name"/> <input type="submit" value="Say Hello"/> </form> </body>

</html>

Form nhập của index.jsp chứa ô nhập có tên là name và action của form là hello. Nghĩa là khi

bạn nhấp nút submit thì dữ liệu của ô nhập name sẽ được chuyển đến lớp action có tên là

hello.

Bước 5: Cấu hình

Page 9: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 328

Tập tin cấu hình struts.xml

Tập tin cấu hình struts.xml được sử dụng để kết nối các thành phần rời rạc (model-

HelloWorldAction và View-HelloWorld.jsp) lại với nhau.

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <package name="test" extends="struts-default"> <action name="hello" class="nnghiem.struts.HelloWorldAction" method="execute"> <result name="success">/HelloWorld.jsp</result> </action> </package>

</struts>

Trong trường hợp này nó định nghĩa một hành động có tên là hello trỏ đến phương thức

execute bên trong lớp HelloWorldAction. Nghĩa là khi bạn đưa ra yêu cầu hello.action (bằng

cách submit form hay liên kết) thì phương thức execute của lớp HelloWorldAction sẽ chạy để

đáp ứng yêu cầu.

Thẻ <result> khai báo View được sử dụng khi phương thức execute trả về giá trị success.

Tập tin cấu hình web.xml

Để chạy được struts, bạn cần khai báo bộ lọc struts trong tập tin cấu hình ứng dụng web

(web.xml) của bạn:

<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <!-- các trang mặc định --> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <!-- bộ lọc struts 2 --> <filter> <filter-name>struts2</filter-name> <filter-class> org.apache.struts2.dispatcher.FilterDispatcher </filter-class>

Page 10: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 329

</filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>

</web-app>

Bước 6: Chạy thử trong eclipse

Phải chuột lên trang index.jsp>Run as>Run on Server

Nhập chữ “Struts2” và nhấp nút Say Hello bạn sẽ nhận được kết quả hiển thị của trang

HelloWorld.jsp

Bạn cũng có thể xuất thành tập tin ứng dụng web (*.war) sau đó chép vào thư mục webapps

của tomcat và chạy bằng cách nhập vào ô địa chỉ của trình duyệt

http://localhost:8080/HelloWorldStruts2/

Page 11: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 330

Qui trình hoạt động của HelloWorldStruts2 ở trên

1-Chạy index.jsp để hiển thị form nhập

2-Submit form đến action hello

3-FilterDispatcher nhận yêu cầu, tra cứu action hello trong struts.xml

4-Nhận các tham số và chuyển vào các thuộc tính tương ứng của lớp HelloWorldAction sau đó

gọi execute()

5-Tra cứu view trong struts.xml dựa vào kết quả (success) của execute()

6-Chuyển tiếp sang view (HelloWorld.jsp) đã lựa chọn

7-Hiển thị thuộc tính name cho người dùng

Index.jsp

HelloWorldAction

execute() FilterDispatcher

HelloWorld.jsp

1

2 4

6 7

Struts.xml

3

Page 12: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 331

5.2 Lớp action

5.2.1 Định nghĩa lớp

Lớp Action đóng vai trò như một model trong mô hình MVC. Lớp này nên kế thừa từ lớp

ActionSupport để tận dụng sức mạnh của lớp này trong lập trình Struts2.

Bên trong lớp Action định nghĩa các phương thức action và các thuộc tính JavaBean.

package nnghiem.struts; import com.opensymphony.xwork2.ActionSupport; public class <tên lớp hành động> extends ActionSupport{ <định nghĩa các phương thức hành động và danh sách các thuộc tính> }

5.2.2 Phương thức action

Phương thức action được định nghĩa đúng cú pháp để được ánh xạ với các action khai báo

trong tập tin cấu hình struts.xml.

public String <tên phương thức action>() throws Exception{ ...thực hiện công việc... return <giá trị kết quả>; }

Phương thức này có tên bất kỳ nhưng không có tham số và kiểu tra về là String. Mỗi giá trị kết

quả trả về từ phương thức hành động sẽ được ánh xạ đến một View (JSP) cụ thể trong tập tin

struts.xml.

5.2.3 Thuộc tính của lớp action

Thuộc tính của lớp action được sử dụng để định nghĩa các thông tin trạng thái của model.

Nghĩa là thông tin này ánh xạ đến dữ liệu đầu vào từ form nhập cũng được chia sẽ với View để

hiển thị.

Các thuộc tính của lớp action phải tuân theo qui ước của JavaBean, tức phải định nghĩa các

phương thức getter (dùng để đọc) và setter (dùng để ghi).

int age; public int getAge(){

return age; } public void setAge(int age){

this.age = age; }

Page 13: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 332

5.2.4 Ví dụ

Ví dụ sau đây định nghĩa lớp action MemberAction chứa 2 phương thức action là signIn() và

input(). Lớp này còn định nghĩa các thuộc tính là userId và password.

Phương thức input() không thực hiện hành động gì chỉ trả về giá trị “input”. Điều này có nghĩa

chỉ hiển thị View được ánh xạ trong struts.xml

Phương thức signIn() trả về “success” nếu đăng nhập thành công và “error” nếu ngược lại.

Nghĩa là khi thực hiện action signIn người dùng có thể nhận được 2 View khác nhau tùy vào kết

quả kiểm tra sự tồn tại của thành việc.

package nnghiem.struts; import com.opensymphony.xwork2.ActionSupport; public class MemberAction extends ActionSupport{ public String input() throws Exception { return "input"; } public String signIn() throws Exception { if(userId.equals("user") && password.equals("123") ){ return "success"; } return "error"; } String userId, password; public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }

Tập tin cấu hình sau đây cấu hình:

Action: viewLogin sẽ chạy phương thức input() sau đó hiển thị trang LoginInput.jsp

Action: login sẽ chạy phương thức signIn(). Nếu phương thức signIn(0 trả về giá trị

o “error”: hiển thị trang LoginError.jsp

o “success”: hiển thị trang MyAccount.jsp

Page 14: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 333

<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <package name="default" extends="default"> <action name="viewLogin" method="input" class="nnghiem.struts.MemberAction"> <result name="input">/LoginInput.jsp</result> </action> <action name="login" method="signIn" class="nnghiem.struts.MemberAction"> <result name="error">/LoginError.jsp</result> <result name="success">/MyAccount.jsp</result> </action> </package>

</struts>

5.3 Cấu hình struts.xml

5.3.1 Ánh xạ action

Ánh xạ action sẽ giúp DispatcherFilter chuyển tiếp một yêu cầu mang tên action vào một

phương thức action đặt bên trong lớp action. Công việc ánh xạ này được thực hiện bằng cách

khai báo các thẻ <action> trong tập tinh cấu hình struts.xml.

<action name="viewLogin" method="input" class="nnghiem.struts.MemberAction">

<action name="login" method="signIn" class="nnghiem.struts.MemberAction">

Hai dòng khai báo trên chỉ ra rằng:

Nếu yêu cầu đến với tên action là viewLogin.action thì chạy phương thức action

input() trong lớp action MemberAction.

Nếu yêu cầu đến với tên action là login.action thì chạy phương thức action signIn()

trong lớp action MemberAction.

5.3.2 Ánh xạ action động

Nếu có nhiều phương thức hành động được định nghĩa trong cùng một lớp action và nếu khai

báo theo cách trên, bạn sẽ phải khai báo rất nhiều thẻ <action> - mỗi thẻ tương ứng với một

phương thức action.

Struts2 cho phép bạn khai báo các ánh xạ <action> động để tránh rườm rà trong việc khai báo

này.

<action name="*Member" method="{1}" class="nnghiem.struts.MemberAction">

Dòng khai báo trên có ý nghĩa như sau

Page 15: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 334

Nếu một yêu cầu đến xyzMember.action thì phương thức xyz() bên trong lớp

MemberAction sẽ chạy.

Nếu một yêu cầu đến Member.action thì phương thức execute() bên trong lớp

MemberAction sẽ chạy.

Với cách khai báo này giúp bạn tiết kiệm khá nhiều dòng khai báo nhờ vào việc gom các hành

động có liên quan để định nghĩa bên trong một lớp action sau đó chỉ khai báo một lần là được.

Sau đây là một ví dụ cách định nghĩa nhiều hành động trong một lớp action

package nnghiem.struts; import com.opensymphony.xwork2.ActionSupport; public class MemberAction extends ActionSupport{ /* * Đăng nhập */ public String signIn() throws Exception { return "account"; } /* * Đăng xuất */ public String signOut() throws Exception { return "home"; } /* * Đăng ký */ public String signUp() throws Exception { return "login"; } /* * Quên mật khẩu */ public String forgotPassword() throws Exception { return "login"; } /* * Đổi mật khẩu */ public String changePasword() throws Exception { return "login"; } /* * Cập nhật thông tin tài khoản */ public String updateProfile() throws Exception { return "login"; } public String input() throws Exception { return "register";

Page 16: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 335

} }

Với lớp MemberAction như trên, bạn có thể các phương thức action như sau:

Yêu cầu Phương thức

signInMember.action MemberAction.signIn()

signOutMember.action MemberAction. signOut()

signUpMember.action MemberAction.signUp()

changePasswordMember.action MemberAction.changePassword

forgotPasswordMember.action MemberAction.forgotPassword()

updateProfileMember.action MemberAction.updateProfile()

Member.action MemberAction.execute()

5.3.3 Ánh xạ kết quả

Khai báo <result> là để ánh xạ kết quả trả về của phương thức action với một View cụ thể. 2

cách khai báo <result> sau đây thường xuyên được sử dụng

Cách 1: (dispatcher)

<result name="success">/HelloWorld.jsp</result>

Theo cách này Struts framework sử dụng RequestDispatcher.forward() để chuyển tiếp đến

View. Như vậy View có thể chia sẻ request với lớp action.

Cách 2: (redirect)

<result name="success" type="redirect">/NewWorld.jsp</result>

Theo cách này Struts framework sử dụng HttpServletResponse.redirect() để chuyển tiếp đến

View. Như vậy View không thể chia sẻ request với lớp action mã chỉ có thể dùng tham số hoặc

session.

<result name="success" type="redirect"> <param name="location">/NewWorld.jsp</param >

</result>

5.4 ModelDriven

Các thuộc tính của lớp action được định nghĩa theo qui ước của JavaBean và được dùng để kết

hợp với các thành phần giao diện trên các View.

Page 17: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 336

Trên action sẽ rất rối khi có nhiều thuộc tính và nhiều phương thức action. Vì vậy struts2 cung

cấp một cơ chế cho phép tách rời các thuộc tính action định nghĩa trong một lớp riêng.

Để dễ hiểu, chúng ta xét lại ví dụ về lớp MemberAction có mã như sau

package nnghiem.struts; import com.opensymphony.xwork2.ActionSupport; public class MemberAction extends ActionSupport{ public String input() throws Exception { return "input"; } public String signIn() throws Exception { if(userId.equals("user") && password.equals("123") ){ return "success"; } return "error"; } String userId, password; public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }

Lớp action này có thể tách thành 2 lớp (MemberAction và MemberModel) sau đó gắn kết chúng

lại với nhau mà không làm ảnh hưởng đến kết quả chạy.

Lớp MemberModel chỉ chứa mô hình dữ liệu (thông tin trạng thái của trang web) có mã như

sau:

package nnghiem.struts; public class MemberModel { String userId, password; public String getUserId() { return userId; } public void setUserId(String userId) {

Page 18: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 337

this.userId = userId; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }

Phần còn lại (MemberAction) được chỉnh sử để gắn kết được với MemberModel sẽ có mã như

sau:

package nnghiem.struts; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.ModelDriven; public class MemberAction extends ActionSupport implements ModelDriven<MemberModel>{ public String input() throws Exception { return "input"; } public String signIn() throws Exception { String userId = user.getUserId(); String password = user.getPassword(); if(userId.equals("user") && password.equals("123") ){ return "success"; } return "error"; } MemberModel user = new MemberModel(); @Override public MemberModel getModel() { return user; } }

Bạn hãy lưu ý 2 thay đổi quan trọng sau đây được sử dụng để gắn kết với MemberModel:

implements ModelDriven<MemberModel>

public MemberModel getModel()

Chú ý: bạn có thể vừa định nghĩa các thuộc tính trên action và vừa kết hợp với Model. Cả 2

cách định nghĩa này để cung cấp trong tin để kết nối với các thành phần giao diện của trang

web.

Page 19: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 338

5.5 Annotation

Ở phần trên bạn phải sử dụng struts.xml để khai báo ánh xạ các action và view của ứng dụng

lại với nhau.

Trong phần này cung cấp cho bạn một cách khai báo khác là Annotation để thực hiện công việc

tương tự như trên.

package nnghiem.struts; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Result; import org.apache.struts2.convention.annotation.Results; import com.opensymphony.xwork2.ActionSupport; @Results(value={ @Result(name="input", location="/register.jsp"), @Result(name="error", location="/error.jsp", type="redirect"), @Result(name="login", location="/login.jsp") }) public class MemberAction extends ActionSupport { /* * Đăng nhập */ @Action(value="signIn", results={ @Result(name="account", location="/account.jsp") } ) public String signIn() throws Exception { return "account"; } /* * Đăng xuất */ @Action(value="signOut", results={ @Result(name="home", location="/index.jsp") }

) public String signOut() throws Exception { return "home"; } /* * Đăng ký */ @Action(value="signUp") public String signUp() throws Exception { return "login"; } /* * Quên mật khẩu */

Page 20: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 339

@Action(value="forgotPassword") public String forgotPassword() throws Exception { return "login"; } /* * Đổi mật khẩu */ @Action(value="changePasword") public String changePasword() throws Exception { return "login"; } /* * Cập nhật thông tin tài khoản */ @Action(value="updateProfile") public String updateProfile() throws Exception { return "login"; } /* * Hiển thị form đăng ký */ @Action(value="input") public String input() throws Exception { return "register"; } }

Với cách khai báo annotation

Mỗi phương thức action được khai báo với một @Action và thuộc tính value của @Action

ánh xạ đến yêu cầu action. Ví dụ: signIn(), signUp(), input()...

@Action(value="signUp")

Thuộc tính results chỉ ra các kết quả trả về của phương thức action. Ví dụ: signIn() và

signOut()

@Action(value="signIn", results={ @Result(name="account", location="/account.jsp") } )

Những @Action không khai báo thuộc tính results thì sử dụng khai báo dùng chung của

toàn lớp

@Results(value={ @Result(name="input", location="/register.jsp"), @Result(name="error", location="/error.jsp", type="redirect"), @Result(name="login", location="/login.jsp") })

Page 21: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 340

5.6 Các thẻ thông dụng

5.6.1 Thẻ điều khiển

5.6.1.1 Thẻ lựa chọn <s:if>

Thẻ <s:if> được sử dụng để thực hiện các loại lệnh lựa chọn tương tự như if, if...else if...else

và switch...case trong java.

Lệnh này thường dùng để lựa chọn khối giao diện phù hợp với điều kiện đặt ra. Sau đây là cú

pháp thực hiện của lệnh

<s:if test="điều kiện 1"> Giao diện 1 </s:if> <s:elseif test="điều khiện 2"> Giao diện 2 </s:elseif> <s:elseif test="điều khiện 3"> Giao diện 3 </s:elseif> <s:else> Giao diện N + 1 </s:else>

Điều kiện nào có giá trị đúng trước thị khối giao diện tương ứng sẽ được thực hiện và xuất ra

màn hình.

Một số ví dụ

Ví dụ 1: xuất các chức năng quản lý tài khoản nếu trong session đã tồn tại attribute có tên là

user. Ngược lại xuất chức năng đăng nhập, quên mật khẩu và đăng ký.

<!--&lt; là dấu nhỏ hơn, &gt; là dấu lớn hơn--> <s:if test="#session.user != null"> <li><a href=”editProfile”>Tài khoản</a></li> <li><a href=”changePassword”>Đổi mật khẩu</a></li> </s:if> <s:else> <li><a href=”login”>Đăng nhập</a></li> <li><a href=”forgotPassword”>Đổi mật khẩu</a></li> <li><a href=”register”>Đăng ký thành viên</a></li> </s:else>

Ví dụ 2: sau đây sẽ xuất hiện lời chào tiếng Anh thích hợp với thời điểm khách web truy xuất.

<!—tạo một bean chứa thời gian hiện tại--> <s:bean var="now" name="java.util.Date"/> <!--&lt; là dấu nhỏ hơn, &gt; là dấu lớn hơn--> <s:if test="now.hours &lt; 12"> <div>Good morning</div> </s:if> <s:elseif test="now.hours &gt; 17">

Page 22: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 341

<div>Good evening</div> </s:elseif> <s:else> <div>Hello</div> </s:else>

Ví dụ 3: minh họa hoàn chỉnh giữa Action và View. Cụ thẻ là người dùng chọn một nick và ứng

dụng sẽ đưa chú tích về người được chọn:

Để thực hiện ứng dụng trên bạn phải thực hiện 3 bước:

Bước 1: Tạo lớp action (MyAction.java)

package nnghiem.struts;

Page 23: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 342

import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Result; @Result(name="success", location="MyView.jsp") public class MyAction{ private String name; @Action(value="/hello") public String execute() throws Exception { return "success"; } public String getName() { return name; } public void setName(String name) { this.name = name; } }

Bước 2: Tạo trang chứa form nhập (MyInput.jsp)

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <html> <head> <title>Hello World</title> </head> <body> <h1>Hello World From Struts2</h1> <form action="hello"> <label for="name">Please pick a name</label><br/> <select name="name"> <option name="Mike">Mike</option> <option name="Jason">Jason</option> <option name="Mark">Mark</option> </select> <input type="submit" value="Say Hello"/> </form> </body> </html>

Bước 3: Tạo trang view (MyView.jsp) sử dụng các lệnh if, else và elseif:

<%@ page contentType="text/html; charset=UTF-8" %> <%@ taglib prefix="s" uri="/struts-tags" %> <html> <head> <title>Example of If and Else</title> </head> <body>

Page 24: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 343

<b>Example of If and Else</b><br/> <s:if test="name=='Mike'"> You have selected 'Mike'. </s:if> <s:elseif test="name=='Jason'"> You have selected 'Jason' </s:elseif> <s:else> You have not selected 'Mike' or 'Jason'. </s:else> </body> </html>

5.6.1.2 Thẻ lặp <s:iterate>

Thẻ <s:iterate> sử dụng để thực hiện các vòng lặp tương tự như các lệnh lặp trong java (while,

for hay do...while).

Thông thường <s:iterate> được sử dụng để duyệt các tập dữ liệu như Collection, Map và mảng

đặt trên ValueStack.

Một số ví dụ:

Ví dụ 1: Giả sử trong ValueStack có một Collection<User> và User có 2 thuộc tính userId

(getUserId()) và password (getPassword()) thì vòng lặp sau cho phép xuất ra tất cả userId và

password của tập users nói trên

<s:iterate value=”users”> <ul> <li>User Id: ${userId}</li> <li>Password: ${password}</li> </ul> </s:else>

Ví dụ 2: lớp action cấp tập List<Employee> dưới dạng thuộc tính của lớp action là employees

mà trang jsp sẽ sử dụng <s:iterate> để hiển thị. Sau đây là các bước thực hiện:

Bước 1: Tạo lớp Action cung cấp List<Employee>

package nnghiem.struts; import java.util.ArrayList; import java.util.List; import org.apache.struts2.convention.annotation.Action; @Result(name="success", location="Employee.jsp") public class Employee { private List<Employee> employees; public List<Employee> getEmployees() { return employees; }

Page 25: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 344

public void setEmployees(List<Employee> employees) { this.employees = employees; } @Action(value="/employee") public String execute() { employees = new ArrayList<Employee>(); employees.add(new Employee("George","Recruitment")); employees.add(new Employee("Danielle","Accounts")); employees.add(new Employee("Melissa","Recruitment")); employees.add(new Employee("Rose","Accounts")); return "success"; } private String name; private String department; public Employee(){} public Employee(String name,String department) { this.name = name; this.department = department; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDepartment() { return department; } public void setDepartment(String department) { this.department = department; } }

Lớp action trên chứa thuộc tính employees là một tập hợp các Employee được tạo ra từ phương

thức ation execute:

Bước 2: Tạo trang Employee.jsp hiển thị tập hợp

<%@ page contentType="text/html; charset=UTF-8" %> <%@ taglib prefix="s" uri="/struts-tags" %> <html> <head> <title>Employees</title> </head> <body> <b>Example of Iterator Tag</b><br/> <s:iterator value="employees"> <s:property value="name"/> , <s:property value="department"/><br/>

Page 26: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 345

</s:iterator> </body> </html>

Kết quả sẽ hiển thị danh sách các employee (mỗi employee gồm name và department)

Bước 3: Chạy employee.action bạn sẽ nhận được kết quả như sau

5.6.2 Thẻ form

5.6.2.1 Các thẻ đơn giản

Trong phần này bạn sẽ được biết các thẻ struts 2 đơn giản để tạo text, password, textarea, file

và hidden.

Để đơn giản chúng ta tìm hiểu form nhập sử dụng các thẻ struts2 đơn gian sau đây:

<%@ page contentType="text/html; charset=utf8" pageEncoding="utf8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <s:head/> <title>Hello World</title> </head> <body> <s:form action="hello" method="post" enctype="multipart/form-data"> <s:textfield name="from" label="Mã đăng nhập"/> <s:password name="password" label="Mật khẩu"/> <s:textarea name="notes" label="Ghi chú"/> <s:file name="attachment" label="Hình ảnh"/> <s:hidden name="country" value="VN"/> <s:submit value="Submit" /> </s:form> </body>

</html>

Khi chạy trang web chúng ta nhận được form nhập như sau

Page 27: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 346

Phải chuột để xem mã HTML được sinh ra từ form nhập struts2 bạn sẽ nhận được đoạn mã

tương ứng của form struts2 như sau:

<form id="hello" name="hello" action="/HelloWorldStruts2/hello.action" method="post" enctype="multipart/form-data"> <table class="wwFormTable"> <tr> <td class="tdLabel"> <label for="hello_from" class="label">Mã đăng nhập:</label> </td> <td> <input type="text" name="from" value="" id="hello_from"/> </td> </tr> <tr> <td class="tdLabel"> <label for="hello_password" class="label">Mật khẩu:</label> </td> <td> <input type="password" name="password" id="hello_password"/> </td> </tr> <tr> <td class="tdLabel">

<label for="hello_notes" class="label">Ghi chú:</label> </td> <td>

<textarea name="notes" cols="" rows="" id="hello_notes"></textarea> </td> </tr> <tr> <td class="tdLabel"> <label for="hello_attachment" class="label">Hình ảnh:</label>

Page 28: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 347

</td> <td> <input type="file" name="attachment" value="" id="hello_attachment"/> </td> </tr> <input type="hidden" name="country" value="VN" id="hello_country"/> <tr> <td colspan="2"> <div align="right"> <input type="submit" id="hello_2" value="Submit"/> </div> </td> </tr> </table> </form>

Như vậy

Mỗi form struts2 sẽ sinh ra một form HTML và có một bảng để trang trí các phần tử

Mỗi phần tử giao diện sẽ sinh ra một hàng 2 ô trên bảng

Mỗi trường ẩn chỉ sinh thẻ ẩn

Mỗi nút submit sẽ sinh một hàng và gộp 2 ô lại thành một

Cụ thể như sau:

Thẻ <s:form>

<s:form action="hello" method="post" enctype="multipart/form-data"> ... </s:form>

Sẽ sinh mã tương ứng

<form id="hello" name="hello" action="/HelloWorldStruts2/hello.action" method="post" enctype="multipart/form-data"> <table class="wwFormTable"> ... </table> </form>

Thẻ <s:textfield>

<s:textfield name="from" label="Mã đăng nhập"/>

Sẽ sinh mã tương ứng là

<tr> <td class="tdLabel"> <label for="hello_from" class="label">Mã đăng nhập:</label> </td> <td> <input type="text" name="from" value="" id="hello_from"/> </td> </tr>

Nút submit

Page 29: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 348

<s:submit value="Submit" />

Sẽ sinh mã tương ứng là

<tr> <td colspan="2"> <div align="right"> <input type="submit" id="hello_2" value="Submit"/> </div> </td> </tr>

Trường ẩn

<s:hidden name="country" value="VN"/>

Sẽ sinh mã tương ứng là

<input type="hidden" name="country" value="VN" id="hello_country"/>

5.6.2.2 Các thẻ nhóm

Để tiện cho việc sử dụng các phần tử giao diện, struts2 cung cấp 2 thể dùng để nhóm các radio

button và checkbox lại thành từng nhóm.

Ví dụ sau đây sẽ cho bạn biết cách sử dụng các thẻ nhóm

<%@ page contentType="text/html; charset=utf8" pageEncoding="utf8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <html> <head> <title>Hello World</title> <s:head /> </head> <body> <s:form action="hello.action"> <s:radio name="gender" label="Giới tính" list="#{'1':'male','0':'female'}" /> <s:checkboxlist name="hobbies" label="Sở thích" list="{'sports','tv','shopping'}" /> </s:form> </body>

</html>

Kết quả hiển thị

Page 30: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 349

Mã HTML được sinh ra

<html> <head> <title>Hello World</title> <link rel="stylesheet" href="/HelloWorldStruts2/struts/xhtml/styles.css" type="text/css"/> <script src="/HelloWorldStruts2/struts/utils.js" type="text/javascript"></script> </head> <body> <form id="hello" action="hello.action" method="post"> <table class="wwFormTable"> <tr> <td class="tdLabel"><label for="hello_gender" class="label">Giới tính:</label></td> <td> <input type="radio" name="gender" id="hello_gender1" value="1"/>

<label for="hello_gender1">male</label>

<input type="radio" name="gender" id="hello_gender0" value="0"/> <label for="hello_gender0">female</label>

</td> </tr> <tr> <td class="tdLabel"><label for="hello_hobbies" class="label">Sở thích:</label></td> <td> <input type="checkbox" name="hobbies" value="sports" id="hobbies-1"/> <label for="hobbies-1" class="checkboxLabel">sports</label> <input type="checkbox" name="hobbies" value="tv" id="hobbies-2"/> <label for="hobbies-2" class="checkboxLabel">tv</label> <input type="checkbox" name="hobbies" value="shopping" id="hobbies-3"/> <label for="hobbies-3" class="checkboxLabel">shopping</label> </td> </tr> </table> </form> </body>

Page 31: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 350

</html>

Thuộc tính list của <s:radio> và <s:checkboxlist> được sử dụng để cấp dữ liệu cho các thành

phần trong nhóm. Giá trị của list có thể là mảng {a,b,c} hoặc bảng băm #{key1:value1,

key2:value2....}.

Các phần tử trong mang {a,c,b} vừa là nhãn được nhìn thấy vừa là giá trị của mỗi phần

tử nhóm

Các phần tử trong bảng băm thì key là giá trị còn value là nhãn của các phần tử trong

nhóm

5.6.2.3 Các thẻ <select>

Thẻ select được struts cải biên kết hợp với javascript để tạo ra các thành phần giao diện mới. Ví

dụ sau sẽ cho bạn thấy khả năng sử dụng thẻ <select> trong struts.

<%@ page contentType="text/html; charset=utf8" pageEncoding="utf8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <html> <head> <title>Hello World</title> <s:head /> </head> <body> <s:form action="login.action"> <s:select name="username" label="Username" list="{'Mike','John','Smith'}" /> <s:select label="Company Office" name="mySelection" value="{'America'}" list="#{'America':'America'}"> <s:optgroup label="Asia" list="#{'India':'India','China':'China'}" /> <s:optgroup label="Europe" list="#{'UK':'UK','Sweden':'Sweden','Italy':'Italy'}" /> </s:select> <s:combobox label="My Sign" name="mySign" list="#{'aries':'aries','capricorn':'capricorn'}" headerKey="-1" headerValue="--- Please Select ---" emptyOption="true" value="capricorn" /> </s:form> </body>

</html>

Page 32: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 351

<html> <head> <title>Hello World</title> <link rel="stylesheet" href="/HelloWorldStruts2/struts/xhtml/styles.css" type="text/css"/> <script src="/HelloWorldStruts2/struts/utils.js" type="text/javascript"></script> </head> <body> <form id="login" action="login.action" method="post"> <table class="wwFormTable"> <tr> <td class="tdLabel"><label for="login_username" class="label">Username:</label></td> <td> <select name="username" id="login_username"> <option value="Mike">Mike</option> <option value="John">John</option> <option value="Smith">Smith</option> </select> </td> </tr> <tr> <td class="tdLabel"> <label for="login_mySelection" class="label">Company Office:</label> </td>

Page 33: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 352

<td> <select name="mySelection" id="login_mySelection"> <option value="America" selected="selected">America</option> <optgroup label="Asia"> <option value="India">India</option> <option value="China">China</option> </optgroup> <optgroup label="Europe"> <option value="UK">UK</option> <option value="Sweden">Sweden</option> <option value="Italy">Italy</option> </optgroup> </select> </td> </tr> <tr> <td class="tdLabel"> <label for="login_mySign" class="label">My Sign:</label> </td> <td> <script type="text/javascript"> function autoPopulate_login_mySign(targetElement) { if (targetElement.options[targetElement.selectedIndex].value == -1) { return; } if (targetElement.options[targetElement.selectedIndex].value == '') { return; } targetElement.form.elements['mySign'].value = targetElement.options[targetElement.selectedIndex].value; } </script> <input type="text" name="mySign" value="capricorn" id="login_mySign"/><br /> <select onChange="autoPopulate_login_mySign(this);"> <option value="-1">--- Please Select ---</option> <option value=""></option> <option value="aries">aries</option> <option value="capricorn" selected="selected">capricorn</option> </select> </td> </tr> </table> </form> </body> </html>

Theme

Chúng ta xét form đơn giản trên đây và bổ sung thuộc tính theme vào form. Điều chỉnh thuộc

tính theme thì mã HTML được sinh ra cũng bị thay đổi theo.

<%@ page contentType="text/html; charset=utf8" pageEncoding="utf8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"

Page 34: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 353

"http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <s:head/> <title>Hello World</title> </head> <body> <s:form theme=”???” action="hello" method="post" enctype="multipart/form-data"> <s:textfield name="from" label="Mã đăng nhập"/> <s:password name="password" label="Mật khẩu"/> <s:textarea name="notes" label="Ghi chú"/> <s:file name="attachment" label="Hình ảnh"/> <s:hidden name="country" value="VN"/> <s:submit value="Submit" /> </s:form> </body>

</html>

Giá trị hợp lệ của thuộc tính theme gồm simple, css_xhml và xhtml (mặc định). Nghĩa là khi bạn

sử dụng theme=”xhtml” thì mã HTML được sinh ra như trên. Trong phần này chúng ta chỉ xét 2

theme còn lại là simple và css_xhtml.

<s:form theme=”simple”...>

Mã HTML được sinh ra

<!DOCTYPE html> <html> <head> <link rel="stylesheet" href="/HelloWorldStruts2/struts/xhtml/styles.css" type="text/css"/> <script src="/HelloWorldStruts2/struts/utils.js" type="text/javascript"></script> <title>Hello World</title> </head> <body> <form id="hello" name="hello" action="/HelloWorldStruts2/hello.action" method="post" enctype="multipart/form-data"> <input type="text" name="from" value="" id="hello_from"/>

Page 35: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 354

<input type="password" name="password" id="hello_password"/> <textarea name="notes" cols="" rows="" id="hello_notes"></textarea> <input type="file" name="attachment" value="" id="hello_attachment"/> <input type="hidden" name="country" value="VN" id="hello_country"/> <input type="submit" id="hello_0" value="Submit"/> </form> </body> </html>

Như vậy các phần tử trong form được sinh ra không được bố cục. Theo cách này mã HTML sinh

ra rất sáng sủa nhưng bạn phải bố cục các phần tử form cho form.

<s:form theme=”css_xhtml”...>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <link rel="stylesheet" href="/HelloWorldStruts2/struts/xhtml/styles.css" type="text/css"/> <script src="/HelloWorldStruts2/struts/utils.js" type="text/javascript"></script> <title>Hello World</title> </head> <body> <form id="hello" name="hello" action="/HelloWorldStruts2/hello.action" method="post" enctype="multipart/form-data"> <div id="wwgrp_hello_from" class="wwgrp">

Page 36: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 355

<div id="wwlbl_hello_from" class="wwlbl"> <label for="hello_from" class="label">Mã đăng nhập:</label> </div> <br /> <div id="wwctrl_hello_from" class="wwctrl"> <input type="text" name="from" value="" id="hello_from"/> </div> </div> <div id="wwgrp_hello_password" class="wwgrp"> <div id="wwlbl_hello_password" class="wwlbl"> <label for="hello_password" class="label">Mật khẩu:</label> </div> <br /> <div id="wwctrl_hello_password" class="wwctrl"> <input type="password" name="password" id="hello_password"/> </div> </div> <div id="wwgrp_hello_notes" class="wwgrp"> <div id="wwlbl_hello_notes" class="wwlbl"> <label for="hello_notes" class="label">Ghi chú:</label> </div> <br /> <div id="wwctrl_hello_notes" class="wwctrl"> <textarea name="notes" cols="" rows="" id="hello_notes"></textarea> </div> </div> <div id="wwgrp_hello_attachment" class="wwgrp"> <div id="wwlbl_hello_attachment" class="wwlbl"> <label for="hello_attachment" class="label">Hình ảnh:</label> </div> <br /> <div id="wwctrl_hello_attachment" class="wwctrl"> <input type="file" name="attachment" value="" id="hello_attachment"/> </div> </div> <input type="hidden" name="country" value="VN" id="hello_country"/> <div align="right" id="wwctrl_hello_0"> <input type="submit" id="hello_0" value="Submit"/> </div> </form> </body> </html>

Mỗi phần tử trên form được sinh mã HTML sử dụng <div> và css để bố cục. Sau đây là mã

HTML được sinh ra từ thẻ <s:textfield name="from" label="Mã đăng nhập"/>

<div id="wwgrp_hello_from" class="wwgrp"> <div id="wwlbl_hello_from" class="wwlbl">

Page 37: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 356

<label for="hello_from" class="label">Mã đăng nhập:</label> </div> <br /> <div id="wwctrl_hello_from" class="wwctrl"> <input type="text" name="from" value="" id="hello_from"/> </div> </div>

Chú ý:

Nếu bạn muốn thiết kế giao diện theo ý thích riêng của mình thì hãy sử dụng simple.

Nếu bạn chỉ muốn tập trung vào nghiệp vụ mà không cần trang trí cầu kỳ thì hãy sử dụng

xhtml

Bạn có thể đặt thuộc tính theme=”simple” cho từng thẻ struts2 để chỉ sinh mã HTML đơn

giản nhất.

Ví dụ:

<s:submit value="Submit" theme="simple" />

Chỉ sinh nút submit đơn gian sau

<input type="submit" id="hello_0" value="Submit"/>

5.6.2.4 Upload file

Để upload tập tin bạn cần lưu ý các đặc điểm kỹ thuật của form upload và lớp action xử lý các

tập tin upload sau đây:

Trong form upload phải chứa thuộc tính enctype="multipart/form-data"

<s:form action="uploadFiles" enctype="multipart/form-data"> <s:file name="photo" label="Photo"/> <s:file name="document" label="Document"/> <s:submit value="Upload"/> </s:form>

Trong lớp action, mỗi tập tin upload bạn phải khai báo 3 field để chứa file, tên file và kiểu file

được upload của file đó.

Cụ thể với form trên bạn phải cần đến sau field

private File photo; private String photoContentType; private String photoFileName; private File document; private String documentContentType; private String documentFileName; <Các phương thức getter/setter cho tất cả các field trên>

Để lưu giữ các file được upload bên trong một thư mục của website, bạn cần phải biết được

đường dẫn vật lý của thư mục đó. 2 dòng mã lệnh sau đây giúp bạn lấy đường dẫn vật lý của

thư mục “upload”.

Page 38: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 357

ServletContext application = ServletActionContext.getServletContext(); String directory = application.getRealPath("upload");

Cuối cùng để chuyển các file được upload vào thư mục “upload” bạn chỉ việc gọi phương thức

rename() của file vừa được upload. Dòng mã sau cho phép chuyển file photo vào thư mục

“upload”.

photo.renameTo(new File(directory, photoFileName));

Ví dụ hoàn chính sau đây cho phép bạn có thể hiểu upload file một cách toàn diện. Trang web

cho phép upload 2 file (1 ảnh và một bất kỳ). Sau khi lưu các file upload, ảnh sẽ được hiển thị

còn file còn lại hiện tên và kiểu file được upload.

Page 39: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 358

Các thành phần bạn cần phải tạo ra trong phần này gồm

Trang input (UploadForm.jsp)

Trang view (UploadSuccess.jsp)

Lớp Action (UploadAction.java)

Bước 1: Trang input (UploadForm.jsp)

<%@ page contentType="text/html; charset=utf8" pageEncoding="utf8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <!DOCTYPE html> <html> <head> <title>File Upload</title> </head> <body> <s:form action="uploadFiles" enctype="multipart/form-data"> <s:file name="photo" label="Photo"/> <s:file name="document" label="Document"/> <s:submit value="Upload"/> </s:form> </body>

</html>

Bước 2: Trang view (UploadSuccess.jsp)

<%@ page contentType="text/html; charset=utf8" pageEncoding="utf8"%> <%@ taglib prefix="s" uri="/struts-tags" %> <html> <head> <title>File Upload Error</title> </head> <body> <h1>PHOTO</h1> <img src="upload/${photoFileName}"/> <h1>DOCUMENT</h1> <ul> <li>Name: ${documentFileName}</li> <li>Type: ${documentContentType}</li> </ul> </body>

</html>

Bước 3: Lớp Action (UploadAction.java)

package nnghiem.struts; import java.io.File; import javax.servlet.ServletContext; import org.apache.struts2.ServletActionContext;

Page 40: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 359

import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Result; import org.apache.struts2.convention.annotation.Results; import com.opensymphony.xwork2.ActionSupport; @Results(value={ @Result(name="form", location="/UploadForm.jsp"), @Result(name="success", location="/UploadSuccess.jsp") }) public class UploadAction extends ActionSupport{ @Action(value="/viewUploadForm") public String input() throws Exception { return "form"; } @Action(value="/uploadFiles") public String execute() throws Exception { // lấy đường dẫn vật lý của thư mục upload ServletContext application = ServletActionContext.getServletContext(); String directory = application.getRealPath("upload"); // lưu tập tin ảnh photo.renameTo(new File(directory, photoFileName)); // lưu tập tin tài liệu photo.renameTo(new File(directory, documentFileName)); return "success"; } /*--for uploading photo--*/ private File photo; private String photoContentType; private String photoFileName; public File getPhoto() { return photo; } public void setPhoto(File photo) { this.photo = photo; } public String getPhotoContentType() { return photoContentType; } public void setPhotoContentType(String photoContentType) { this.photoContentType = photoContentType; } public String getPhotoFileName() { return photoFileName;

Page 41: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 360

} public void setPhotoFileName(String photoFileName) { this.photoFileName = photoFileName; } /*--for uploading document--*/ private File document; private String documentContentType; private String documentFileName; public File getDocument() { return document; } public void setDocument(File document) { this.document = document; } public String getDocumentContentType() { return documentContentType; } public void setDocumentContentType(String documentContentType) { this.documentContentType = documentContentType; } public String getDocumentFileName() { return documentFileName; } public void setDocumentFileName(String documentFileName) { this.documentFileName = documentFileName; }

}

5.6.3 Thẻ dữ liệu

Struts 2 có một tập các thẻ chuyên trách xử lý dữ liệu được hiển thị trên các trang. Sau đây là

danh sách các thẻ dữ liệu thường dùng nhất.

5.6.3.1 Thẻ <s:action>

Thẻ này cho phép các lập trình viên gọi một hành động trực tiếp bằng cách chỉ định tên hành

động. Nội dung của thẻ được sinh ra từ hành hành động các khai báo result trong struts.xml sẽ

được bỏ qua nếu thẻ <s:action> của bạn không khai báo thuộc tính executeResult

<div>Thực thi một phương thức action</div> <s:action name="myAction" executeResult="true" />

Lớp Action

package nnghiem.struts; import org.apache.struts2.convention.annotation.Action;

Page 42: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 361

import org.apache.struts2.convention.annotation.Result; @Result(name="success", location="MyView.jsp") public class MyAction{ private String name; @Action(value="/myAction") public String execute() throws Exception { return "success"; } public String getName() { return name; } public void setName(String name) { this.name = name; } }

Trang hiển thị

MyView.jsp sử dụng <s:generator> và <s:iterate> để sinh và hiển thị tập hợp các chuỗi:

<%@ page contentType="text/html; charset=utf8" %> <%@ taglib prefix="s" uri="/struts-tags" %> <html> <head> <title>Hello World</title> </head> <body> <h2>Xin chào</h2> </body> </html>

Trang nhúng <s:action>

<%@ page contentType="text/html; charset=UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <html> <head> <title>Employees</title> </head> <body> <s:action name="myAction" executeResult="true"> Output from myAction: <br /> </s:action> </body> </html>

Chạy Employee.jsp hoặc myAction.action bạn sẽ nhận được kết quả

Page 43: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 362

5.6.3.2 Thẻ <s:include>

Thẻ này tương đương như <jsp:include> của JSP, dùng để bao hàm một tập tin JSP khác. Bạn

có thể thay thế bằng <s:action> đã học trước đây.

<!-- First Syntax --> <s:include value="myJsp.jsp" /> <!-- Second Syntax --> <s:include value="myJsp.jsp"> <s:param name="param1" value="value2" /> <s:param name="param2" value="value2" /> </s:include> <!-- Third Syntax --> <s:include value="myJsp.jsp"> <s:param name="param1">value1</s:param> <s:param name="param2">value2</s:param> </s:include>

Lớp Action:

package nnghiem.struts; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Result; @Result(name="success", location="MyView.jsp") public class MyAction{ @Action(value="/myAction") public String execute() throws Exception { return "success"; } }

Các trang view

MyInclude.jsp có nội dung như sau:

<%@ page contentType="text/html; charset=UTF-8" %> <%@ taglib prefix="s" uri="/struts-tags" %> <html> <head> <title>Hello World</title> </head> <body> <h2>Example of Generator Tag</h2> <h3>The colours of rainbow:</h3> <s:generator val="%{'Violet,Indigo,Blue,

Page 44: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 363

Green,Yellow,Orange,Red'}" count="7" separator=","> <s:iterator> <s:property /><br/> </s:iterator> </s:generator> </body> </html>

MyView.jsp có nội dung như sau:

<%@ page contentType="text/html; charset=UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <html> <head> <title>Employees</title> </head> <body> <p>An example of the include tag: </p> <s:include value="MyInclude.jsp"/> </body> </html>

Chạy myAction.action bạn sẽ nhận được kết quả sau:

Page 45: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 364

5.6.3.3 Thẻ <s:bean>

Thẻ này dùng để tạo ra đối tượng JavaBean thường chuẩn bị dữ liệu cung cấp cho các thẻ điều

khiển hoặc giao diện khác.

<s:bean name="org.apache.struts2.util.Counter" var="counter"> <s:param name="first" value="20"/> <s:param name="last" value="25" /> </s:bean>

Thẻ <s:bean> là sự kết hợp giữa các thẻ <s:set> và <s:push>. Nó cho phép tạo mới một đối

tượng, thiết lập các thuộc tính sau đó đặt lên ngăn xếp giá trị (valuestack) để sử dụng trong

trang jsp.

Lớp Action:

package nnghiem.struts; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Result; @Result(name="success", location="MyView.jsp") public class MyAction{ @Action(value="/myAction") public String execute() throws Exception { return "success"; } }

Các trang View MyView.jsp:

<%@ page contentType="text/html; charset=UTF-8" %> <%@ taglib prefix="s" uri="/struts-tags" %> <html> <head> <title>Hello World</title> </head> <body> <s:bean name="org.apache.struts2.util.Counter" var="counter"> <s:param name="first" value="20"/> <s:param name="last" value="25" /> </s:bean> <ul> <s:iterator value="#counter"> <li><s:property /></li> </s:iterator> </ul> </body> </html>

Page 46: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 365

Chạy myAction.action bạn sẽ nhận được kết quả sau đây:

Trong ví dụ trên chúng ta sử dụng org.apache.struts2.util.Counter và thiết lập thuộc tính first là

20 và last là 25, điều này có nghĩa là counter chứa danh sách các số 20, 21, 22, 23, 24, 25.

Bean được tạo ra và đặt vào valuestack và vì vậy được sử dụng trong trang jsp

5.6.3.4 Thẻ <s:date>

Thẻ này dùng để định dạng thời gian (ngày và giờ)

<s:date name="person.birthday" format="dd/MM/yyyy" /> <s:date name="person.birthday" format="%{getText('some.i18n.key')}" /> <s:date name="person.birthday" nice="true" /> <s:date name="person.birthday" />

Lớp Action:

package nnghiem.struts; import java.util.Date; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Result; @Result(name="success", location="MyView.jsp") public class MyAction{ private Date currentDate; @Action(value="/myAction") public String execute() throws Exception { return "success"; } public void setCurrentDate(Date date){ this.currentDate = date; } public Date getCurrentDate(){ return currentDate; } }

Các trang View MyView.jsp

Page 47: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 366

<%@ page contentType="text/html; charset=UTF-8" %> <%@ taglib prefix="s" uri="/struts-tags" %> <html> <head> <title>Hello World</title> </head> <body> <h2>Current Date</h2> <h3>Day/Month/Year Format</h3> <s:date name="currentDate" format="dd/MM/yyyy" /> <h3>Month/Day/Year Format</h3> <s:date name="currentDate" format="MM/dd/yyyy" /> </body> </html>

Kết quả sau khi chạy hello.action

5.6.3.5 Thẻ <s:property>

Thẻ này dùng để nhận giá trị của một thuộc tính đặt trên đỉnh của valuestack.

<s:push value="myBean"> <!-- Example 1: --> <s:property value="myBeanProperty" /> <!-- Example 2: -->TextUtils <s:property value="myBeanProperty" default="a default value" /> </s:push>

Ví dụ sau đây minh họa việc sử dụng các thẻ <s:set>, <s:push> và <s:property>

Lớp Bean

Page 48: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 367

package nnghiem.struts; public class Environment { private String name; public Environment(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } }

Lớp Action

package nnghiem.struts; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Result; import com.opensymphony.xwork2.ActionSupport; @Result(name="success", location="Systems.jsp") public class SystemDetails extends ActionSupport { private Environment environment = new Environment("Development"); private String operatingSystem = "Windows XP SP3"; @Action(value="/detail") public String execute() { return SUCCESS; } public Environment getEnvironment() { return environment; } public void setEnvironment(Environment environment) { this.environment = environment; } public String getOperatingSystem() { return operatingSystem; } public void setOperatingSystem(String operatingSystem) { this.operatingSystem = operatingSystem; } }

Các trang View System.jsp

<%@ page contentType="text/html; charset=utf8" pageEncoding="utf8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <html>

Page 49: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 368

<head> <title>System Details</title> </head> <body> <p>The environment name property can be accessed in three ways:</p> (Method 1) Environment Name: <s:property value="environment.name"/><br/> (Method 2) Environment Name: <s:push value="environment"> <s:property value="name"/><br/> </s:push> (Method 3) Environment Name: <s:set name="myenv" value="environment.name"/> <s:property value="myenv"/> </body> </html>

Diễn giải

Phương pháp 1: sử dụng <s:property> để nhận thuộc tính name trong environment. Vì

environment là thuộc tính của action nên nó tự động đặt vào đỉnh của valuestack.

Phương pháp này làm việc tốt khi bạn có ít các thuộc tính bên trong một lớp. Hãy tưởng

tượng khi bạn có nhiều thuộc tính trong lớp Environment thì khi truy xuất mỗi thuộc

tính, bạn phải có tiếp đầu ngữ environment sẽ gây rườm ra và đó là lý do để dùng

<s:push>.

Phương pháp 2 (sử dụng <s:push>): loại bỏ tiếp đầu ngữ environment khi truy xuất các

thuộc tính trong lớp Environment vì <s:push> đã đặt đối tượng environment hiện tại lên

đĩnh của valuestack.

Phương pháp cuối cùng (dùng <s:set>): tạo một biến mới tên myenv trỏ đến

environment.name.

Kết quả chạy system.action như sau:

Page 50: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 369

5.6.3.6 Thẻ <s:text>

Thẻ này dùng để sinh chuỗi đa ngôn ngữ lấy từ nguồn tài nguyên tương ứng với địa phương

được chọn.

<!-- First Example --> <s:i18n name="struts.action.test.i18n.Shop"> <s:text name="main.title"/> </s:i18n> <!-- Second Example --> <s:text name="main.title" /> <!-- Third Examlpe --> <s:text name="i18n.label.greetings"> <s:param >Mr Smith</s:param> </s:text>

Thẻ <s:text> được dùng cần tuân theo 3 bước sau đây:

Chuỗi đa ngôn ngữ phải được khai báo trong file tài nguyên (.properties) đính kèm có

tên giống tên lớp Action được kết hợp và đặt cùng chỗ với lớp này.

Nếu chuỗi đa ngôn ngữ không được tìm thấy thì phần thân của thẻ <s:text> là thông

điệp mặc định.

Trong trường hợp không có thân của thẻ <s:text> thì tên của thông điệp sẽ được hiện

ra.

Lớp Action:

package nnghiem.struts; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Result; @Result(name="success", location="MyView.jsp") public class MyAction{ @Action(value="/myAction") public String execute() throws Exception { return "success"; } }

Các trang View MyView.jsp

<%@ taglib prefix="s" uri="/struts-tags"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>Text Tag Example</title> </head> <body>

Page 51: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 370

<s:i18n name="MyAction"> <s:text name="name.success"/><br> <s:text name="name.xyz">Message doesn't exists</s:text><br> <s:text name="name.msg.param"> <s:param >ZARA</s:param> </s:text> </s:i18n> </body> </html>

Các tập tin cấu hình

Tạo một tập tin tài nguyên đính kèm cùng tên với lớp Action những phần mở rộng là properties

(MyAction.properties) đặt cùng vị trí với lớp Action hoặc trong classpath có nội dung

như sau:

name.success = This is success message

name.msg.param = The param example - param : {0}

struts.xml

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <constant name="struts.custom.i18n.resources" value="GlobalResources"/> <package name="empty" extends="struts-default"> </package> </struts>

Kết quả chạy myAction.action như sau:

Page 52: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 371

5.6.3.7 Thẻ <s:url>

Dùng để tạo một URL để sử dụng các các thẻ liên kết hay hành động khác

<!-- Example 1 --> <s:url value="editGadget.action"> <s:param name="id" value="%{selected}" /> </s:url> <!-- Example 2 --> <s:url action="editGadget"> <s:param name="id" value="%{selected}" /> </s:url> <!-- Example 3--> <s:url includeParams="get"> <s:param name="id" value="%{'22'}" /> </s:url>

Lớp Action

package nnghiem.struts; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Result; @Result(name="success", location="MyView.jsp") public class MyAction{ private String name; @Action(value="/myAction") public String execute() throws Exception { return "success"; } public String getName() { return name; } public void setName(String name) { this.name = name; } }

Các trang View MyView.jsp

<%@ page contentType="text/html; charset=UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <html> <head> <title>Hello World</title> </head> <body> <s:url action="myAction" var="myurl"> <s:param name="user">Zara</s:param>

Page 53: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 372

</s:url> <a href='<s:property value="#myurl"/>'> <s:property value="#myurl"/></a> </body> </html>

<s:url> trong ví dụ này tạo và cung cấp một chuỗi URL cho thẻ <a href=””></a>

Kết quả chạy hello.action như sau:

5.7 Kiểm lỗi

Việc kiểm lỗi xảy ra sau khi các thuộc tính của lớp action được thiết lập.

Nếu tất cả các thuộc tính đều hợp lệ thì thương thức action được gọi

Ngược lại sẽ tự quay lại input. Vì vậy tất cả các action có kiểm lỗi đều phải khai báo

input

valid

ate

()

act

ion()

input.jsp

<s:fielderrors>

setX

yz(

)

success.jsp

[valid] [invalid

]

[request]

[resp

onse

]

[resp

onse

]

Page 54: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 373

Struts2 cung cấp 3 phương pháp kiểm lỗi:

Kiểm lỗi bằng tay: việc kiểm lỗi do lập trình viết

Kiểm lỗi bằng XML: việc kiểm lỗi được thực hiện thông qua khai báo bằng XML

Kiểm lỗi bằng Annotation: việc kiểm lỗi thông qua khai báo các annotation

5.7.1 Kiểm lỗi bằng tay

Để kiểm lỗi bằng tay, trong lớp action bạn chỉ cần override phương thức validate của lớp

ActionSupport sau đó tự viết mã kiểm tra theo ý của bạn.

Trong phương thức validate() của lớp action, bạn sử dụng phương thức addFieldError()

để tích lũy các lỗi.

Trong trong input lỗi sẽ được hiển thị theo 2 cách:

o Lỗi tự động thêm vào bên phải các phần tử không hợp lệ.

o Ngoài ra bạn có thể hiển thị lỗi tập trung bằng <s:fielderror/>

Ví dụ sau cho bạn thấy việc kiểm lỗi bằng tay:

Page 55: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 374

Để thực hiện việc kiểm lỗi như trên, bạn cần phải viết ra các thành phần sau đây:

Validate.jsp là trang input

Success.jsp là trang view

ValidateAction.java là lớp action chứa phương thức kiểm lỗi (validate())

ValidateAction.properties là tập tin chứa các thông báo lỗi được sử dụng trong validate()

Bước 1: Validate.jsp

Trong trang này bạn cần lưu ý 2 điểm:

Thẻ <s:fielderror> là nôi tập trung và hiển thị lỗi

CSS gồm 2 luật

o tr[errorFor]{display:none;}: ẩn các lỗi hiển thị sau mỗi field

o .errorMessage li{color:red;}: định nghĩa css cho các thông báo lỗi

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="/struts-tags" prefix="s" %> <!DOCTYPE HTML> <html> <head> <title>Struts & Hibernate</title> <style type="text/css"> tr[errorFor]{display:none;} .errorMessage li{color:red;} </style> </head> <body> <h1>Form cần kiểm soát dữ liệu</h1> <s:form action="validate"> <s:textfield name="id" label="Login Name" /> <s:textfield name="password" label="Password" /> <s:textfield name="name" label="Full Name" /> <s:textfield name="email" label="Email" /> <s:textfield name="age" label="Age" /> <s:textfield name="moto" label="Moto" /> <s:textarea rows="5" cols="44" name="notes" label="Notes" /> <s:submit value="Validate" /> </s:form> <s:fielderror/> </body> </html>

Bước 2: ValidateAction.java

Trong lớp action bạn hãy chú ý vào phương thức validate(), nó sẽ được gọi để thực hiện kiểm

tra tính hợp lệ của dữ liệu. Vì vậy nhiệm vụ của bạn là phải đặt mã kiểm tra trong đó là được.

Bạn cũng cần phải khai báo trang input để khi gặp lỗi sẽ được tự động quay về.

Phương thức tích lũy thông báo lỗi addFieldError(fieldName, getText(key, args)); được

hiểu như sau:

Page 56: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 375

fieldName là tên field không hợp lệ

getText() là thông báo lỗi được lấy trong tập tin tài nguyên (ValidateAction.properties)

với khóa (key: errors.required, errors.range) và danh sach các tham số (args) để cung

cấp cho các tham số dánh sẵn trong chuỗi thông báo (xem thêm Bước 3).

package nnghiem.struts.action; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Result; import org.apache.struts2.convention.annotation.Results; import com.opensymphony.xwork2.ActionSupport; @Results(value={ @Result(name="input", location="/Validate.jsp"), @Result(name="success", location="/Success.jsp") }) public class ValidateAction extends ActionSupport { @Action(value="/validate") @Override public String execute() throws Exception { return "success"; } @Override public void validate() { if(id == null || id.length() == 0){ addError("id", "errors.required", "Id"); } if(name == null || name.length() == 0){ addError("name", "errors.required", "Name"); } if(email == null || email.length() == 0){ addError("email", "errors.required", "Email"); } else if(!email.matches("^(\\w+@\\w+\\.\\w+)$")){ addError("email", "errors.invalid", "Email"); } if(password != null && password.length() < 6){ addError("password", "errors.minlength", "Password", "6"); } if(notes != null && notes.length() > 255){ addError("notes", "errors.maxlength", "Notes", "255"); } if(age < 18 || age > 55){ addError("age", "errors.range", "Age", "18", "55"); } if(!moto.matches("^(5\\d-[A-Z]\\d-\\d{4})$")){ addError("moto", "errors.invalid", "Moto"); } } void addError(String fieldName, String key, String...args){

Page 57: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 376

addFieldError(fieldName, getText(key, args)); } String id, email, name, password, moto, notes; int age; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getMoto() { return moto; } public void setMoto(String moto) { this.moto = moto; } public String getNotes() { return notes; } public void setNotes(String notes) { this.notes = notes; } public int getAge() { return age; } public void setAge(int age) { this.age = age; }

Page 58: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 377

}

Bước 3: ValidateAction.properties

errors.range=<b><i>{0}</i></b> phai tu {1} den {2} errors.maxlength=<b><i>{0}</i></b> phai nho hon {1} errors.minlength=<b><i>{0}</i></b> phai lon hon {1} errors.required=<b><i>{0}</i></b> la bat buoc errors.invalid=<b><i>{0}</i></b> khong dung dinh dang

Đây là tập tin cung cấp danh sách thông báo lỗi đươc sử dụng trong phương thức

getText(String key, String[] args). Bạn chỉ cần đưa ra dúng key và danh sách (mảng chuỗi)

tham số để thế vào các vị trí dành sẵn ({i}) theo đúng thứ tự.

Ví dụ: đoạn mã sau cho giá trị của message là “<b><i>Tuoi</i></b> phai tu 18 den 55”

String key = “errors.range”; String[] args = {“Tuoi”, “18”, “55”}; String message = getText(key, args);

Bước 4: Success.jsp

Đây là tập tin View, chỉ làm nhiệm vụ hiển thị tất cả các giá trị hợp lệ đã nhập vào

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="/struts-tags" prefix="s" %> <!DOCTYPE HTML> <html> <head> <title>Struts 2 & Hibernate</title> </head> <body> <h1>Thông tin hợp lệ</h1> <ul> <li>Id: ${id}</li> <li>Name: ${name}</li> <li>Email: ${email}</li> <li>Password: ${password}</li> <li>Age: ${age}</li> <li>Moto: ${moto}</li> <li>Notes: ${notes}</li> </ul> </body> </html>

5.7.2 Kiểm lỗi bằng XML

Kiểm lỗi bằng XML thì công việc kiểm lỗi sẽ giao cho việc khai báo XML. Để hiểu rõ hơn, chúng

ta

Page 59: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 378

Trong bài này bạn cần phải tạo các thành phần sau đây

Trang input (Validate.jsp)

Lớp action (ValidateAction.java)

Tập tin kiểm lỗi (ValidateAction-validate.xml)

Tập tin tài nguyên thông báo lỗi (ValidateAction.properties)

Trang view (Success.jsp)

Bước 1: trang input (Validate.jsp)

Trang web này không thay đổi so với phần kiểm lỗi bằng tay

Page 60: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 379

Bước 2: lớp action (ValidateAction.java)

Không có phương thức kiểm lỗi validate(), chỉ cần khai báo trang input để khi gặp lỗi sẽ quay

về.

package nnghiem.struts.action.xml; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Result; import org.apache.struts2.convention.annotation.Results; import com.opensymphony.xwork2.ActionSupport; @Results(value={ @Result(name="input", location="/Validate.jsp"), @Result(name="success", location="/Success.jsp") }) public class ValidateAction extends ActionSupport { @Action(value="/validate") @Override public String execute() throws Exception { return "success"; } String id, email, name, password, moto, notes; int age; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; }

Page 61: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 380

public String getMoto() { return moto; } public void setMoto(String moto) { this.moto = moto; } public String getNotes() { return notes; } public void setNotes(String notes) { this.notes = notes; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }

Bước 3: tập tin khai báo kiểm lỗi (ValidateAction-validate.xml)

Đây là tập tin khai báo các luật kiểm lỗi cho các field trên form (hay thuộc tính của action).

Trong bài này chúng ta sử dụng các luật kiểm lỗi sau:

requiredstring: không để trống

email: không đúng dạng email

regex: không khới với biểu thức chính qui

int: không phải số nguyên hợp lệ

Thông báo lỗi sẽ được lấy trong tập tin ValidateAction.properties (xem bước tiếp theo)

<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd"> <validators> <field name="id"> <field-validator type="requiredstring"> <message key="id.required"/> </field-validator> </field> <field name="name"> <field-validator type="requiredstring"> <message key="name.required"/> </field-validator> </field> <field name="email"> <field-validator type="requiredstring"> <message key="email.required"/> </field-validator> <field-validator type="email"> <message key="email.format"/>

Page 62: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 381

</field-validator> </field> <field name="password"> <field-validator type="stringlength"> <param name="minLength">6</param> <message key="password.minlength"/> </field-validator> </field> <field name="moto"> <field-validator type="regex"> <param name="expression"> <![CDATA[^(5\d-[A-Z]\d-\d{4})$]]> </param> <message key="moto.format"/> </field-validator> </field> <field name="notes"> <field-validator type="stringlength"> <param name="maxLength">255</param> <message key="notes.maxlength"/> </field-validator> </field> <field name="age"> <field-validator type="int"> <param name="min">18</param> <param name="max">55</param> <message key="age.range"/> </field-validator> </field> </validators>

Bước 4: tập tin tài nguyên thông báo lỗi (ValidateAction.properties)

Các bạn lưu ý sự khác biết giữa nội dung của tập tin này với trong phần kiểm lỗi bằng tay là các

tham số dành sẵn được đánh theo tên (${min}) chứ không phải vị trí (${0}) như trước đây. Tên

của tham số chính là tên của <param name="min">18</param> được sử dụng trong XML.

age.range=Age must be between ${min} and ${max} notes.maxlength=Notes must be less than ${maxLength} moto.format=Moto is invalid Saigon region password.minlength=Notes must be greater than ${minLength} id.required=Id is required field 123 name.required=Name is required field email.required=Email is required field email.format=Email is invalid format

Bước 5: trang view (Success.jsp)

Không thay đổi so với phần kiểm lỗi bằng tay

Tham khảo các luật kiểm lỗi

date validator

<field name="birthday">

Page 63: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 382

<field-validator type="date"> <param name="min">01/01/1990</param> <param name="max">01/01/2000</param> <message>Birthday must be within ${min} and ${max}</message> </field-validator> </field>

double validator

<field name="percentage"> <field-validator type="double"> <param name="minExclusive">0.123</param> <param name="maxExclusive">99.98</param> <message> Percentage needs to be between ${minExclusive} ${maxExclusive} (exclusive) </message> </field-validator> </field>

email validator

<field name="myEmail"> <field-validator type="email"> <message>Must provide a valid email</message> </field-validator> </field>

expression validator

A Non-Field Level validator that validates based on regular expression supplied.

<field-validator type="expression"> <param name="expression">....</param> <message>Failed to meet Ognl Expression</message> </field-validator>

int validator

<field name="age"> <field-validator type="int"> <param name="min">5</param> <param name="max">50</param> <message>Age needs to be between ${min} and ${max}</message> </field-validator> </field>

regex validator

<field name="myStrangePostcode"> <field-validator type="regex"> <param name="fieldName">myStrangePostcode</param> <param name="expression"><![CDATA[([aAbBcCdD][123][eEfFgG][456])]]></param>

Page 64: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 383

</field-validator> </field>

required validator

<field name="username"> <field-validator type="required"> <message>username must not be null</message> </field-validator> </field>

requiredstring validator

<field name="username"> <field-validator type="requiredstring"> <param name="trim">true</param> <message>username must not be null</message> </field-validator> </field>

stringlength validator

<field name="username"> <field-validator type="stringlength"> <param name="minLength">10</param> <param name="maxLength">10</param> <param name="trim">true</param> <message>Your username needs to be 10 characters long</message> </field-validator> </field>

url validator

<field-validator type="url"> <param name="fieldName">myHomePageURL</param> <message>Invalid homepage url</message> </field-validator>

5.7.3 Kiểm lỗi bằng Annotation

Khác với 2 phương pháp trước - bạn không cần phương thức validate() và cũng không có tập

tin XML mà thay vào đó bạn chỉ sử dụng các annotation để khai báo trực tiếp lên các field bạn

muốn kiểm lỗi.

Trong bài này bạn cần phải tạo các thành phần sau đây

Trang input (Validate.jsp)

Lớp action (ValidateAction.java)

Tập tin tài nguyên thông báo lỗi (ValidateAction.properties)

Trang view (Success.jsp)

Bước 1: Trang input (Validate.jsp)

Page 65: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 384

Giống như trước đây

Bước 2: Lớp action (ValidateAction.java)

package nnghiem.struts.action.anotation; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Result; import org.apache.struts2.convention.annotation.Results; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.validator.annotations.EmailValidator; import com.opensymphony.xwork2.validator.annotations.IntRangeFieldValidator; import com.opensymphony.xwork2.validator.annotations.RegexFieldValidator; import com.opensymphony.xwork2.validator.annotations.RequiredStringValidator; import com.opensymphony.xwork2.validator.annotations.StringLengthFieldValidator; @Results(value={ @Result(name="input", location="/Validate.jsp"), @Result(name="success", location="/Success.jsp") }) public class ValidateAction extends ActionSupport { @Action(value="/validate") @Override public String execute() throws Exception { return "success"; } String id, email, name, password, moto, notes; int age; @RequiredStringValidator(key="id.required") public String getId() { return id; } public void setId(String id) { this.id = id; } @RequiredStringValidator(key="email.required") @EmailValidator(key="email.format") public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @RequiredStringValidator(key="name.required") public String getName() { return name; } public void setName(String name) { this.name = name;

Page 66: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 385

} @StringLengthFieldValidator(key="password.minlength", minLength="6") public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @RegexFieldValidator(key="moto.format", expression="^(5\\d-[A-Z]\\d-\\d{4})$") public String getMoto() { return moto; } public void setMoto(String moto) { this.moto = moto; } @StringLengthFieldValidator(key="notes.maxlength", maxLength="255") public String getNotes() { return notes; } public void setNotes(String notes) { this.notes = notes; } @IntRangeFieldValidator(key="age.range", min="18", max="55") public int getAge() { return age; } public void setAge(int age) { this.age = age; } }

Bước 3: Tập tin tài nguyên thông báo lỗi (ValidateAction.properties)

Giống phần kiểm lỗi bằng XML

Bước 4: Trang view (Success.jsp)

Giống như trước đây

Bỏ qua validate cho 1 phương thức action

Thông thường, khi bạn gọi đến bất kỳ action nào thì kiểm lỗi bằng annotation sẽ tự động thực

hiện. Đôi khi một vài phương thức action nào đó chúng ta không muốn việc kiểm lỗi xảy ra. Vì

vậy chúng ta cần có cách để hủy bỏ việc kiểm lỗi với phương thức này. Để thực hiện điều này,

bạn sử dụng annotation @SkipValidation.

public class ValidateAction extends ActionSupport { @SkipValidation @Action(value="/validate") public String execute() throws Exception {

Page 67: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 386

return "success"; } }

Tham khao các annotation kiểm lỗi

ConversionErrorFieldValidator

Dùng để kiểm lỗi chuyển đổi dữ liệu không hợp lệ

public class Employee extends ActionSupport{ @ConversionErrorFieldValidator(message = "Default message",

key = "i18n.key", shortCircuit = true) public String getName() { return name; } }

DateRangeFieldValidator

Kiểm lỗi phạm vi thời gian

public class Employee extends ActionSupport{ @DateRangeFieldValidator(message = "Default message",

key = "i18n.key", shortCircuit = true, min = "2005/01/01", max = "2005/12/31")

public String getDOB() { return dob; } }

DoubleRangeFieldValidator

Kiểm lỗi phạm vi số thực

public class Employee extends ActionSupport{ @DoubleRangeFieldValidator(message = "Default message", key = "i18n.key", shortCircuit = true, minInclusive = "0.123", maxInclusive = "99.987") public String getIncome() { return income; } }

EmailValidator

Kiểm lỗi định dạng email

public class Employee extends ActionSupport{ @EmailValidator(message = "Default message", key = "i18n.key", shortCircuit = true) public String getEmail() { return email; } }

Page 68: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 387

ExpressionValidator

Kiểm lỗi (chung-không áp dụng cho 1 field cụ thể) theo biểu thức chính qui (regular

exppression)

@ExpressionValidator(message = "Default message", key = "i18n.key", shortCircuit = true, expression = "an OGNL expression" )

IntRangeFieldValidator

Kiểm lỗi phạm vi số nguyên

public class Employee extends ActionSupport{ @IntRangeFieldValidator(message = "Default message", key = "i18n.key", shortCircuit = true, min = "0", max = "42") public String getAge() { return age; } }

RegexFieldValidator

Kiểm lỗi tùy vào biểu thức chính qui

@RegexFieldValidator( key = "regex.field", expression = "yourregexp")

RequiredFieldValidator

Kiểm lỗi null

public class Employee extends ActionSupport{ @RequiredFieldValidator(message = "Default message",

key = "i18n.key", shortCircuit = true) public String getAge() { return age; } }

RequiredStringValidator

Kiểm lỗi không để trống chuỗi

public class Employee extends ActionSupport{ @RequiredStringValidator(message = "Default message", key = "i18n.key", shortCircuit = true, trim = true) public String getName() { return name; } }

StringLengthFieldValidator

Page 69: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 388

Kiểm lỗi độ dài chuỗi

public class Employee extends ActionSupport{ @StringLengthFieldValidator(message = "Default message",

key = "i18n.key", shortCircuit = true, trim = true, minLength = "5", maxLength = "12")

public String getName() { return name; } }

UrlValidator

Kiểm lỗi định dạng url

public class Employee extends ActionSupport{ @UrlValidator(message = "Default message", key = "i18n.key", shortCircuit = true) public String getURL() { return url; } }

5.8 Xây dựng layout với Tiles

Xây dựng bố cục (layout) chung cho các trang web thành viên trong website là một kỹ thuật

đáng quan tâm. Với Tiles framework, bạn dễ dàn triển khai layout chung cho website của bạn.

Trong phần này bạn sẽ được học cách xây dựng một layout như hình sau để áp dụng chung

cho nhiều trang web khác nhau.

Trang Home.jsp

Page 70: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 389

Trang AboutUs.jsp

Để xây dựng layout và áp dụng cho các trang web như trên bạn cần tạo các thành phần sau:

Layout.jsp và Layout.css: bố cục chung

Home.jsp, AboutUs.jsp...: các trang thành viên

LayoutAction.java: lớp action

Web.xml: tập tin cấu hình ứng dụng

Thực hiện

Bước 1: Layout.jsp

Trong trang Layout.jsp bạn cần chú ý đến các thành phần được đánh dấu sau đây

Chỉ định thư viện thẻ cần dùng

<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>

Thẻ <tiles:insertAttribute> được dùng để đánh dấu các vùng thay thế nội dung cho các

trang thành viên

<tiles:insertAttribute name="head" ignore="true" />

<tiles:insertAttribute name="main"/>

o @name: tên vùng để thay thế

Page 71: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 390

o @ignore: cho phép bỏ qua (không cung cấp nội dung) hay không

<%@ page contentType="text/html; charset=utf8" pageEncoding="utf8"%> <%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c" %> <%@ taglib uri="http://java.sun.com/jstl/fmt_rt" prefix="fmt" %> <%@ taglib uri="/struts-tags" prefix="s" %> <%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %> <!DOCTYPE HTML> <html> <head> <title>Layout demo</title> <link href="css/Layout.css" rel="stylesheet"> <tiles:insertAttribute name="head" ignore="true" /> </head> <body> <div id="wrapper"> <div id="header"> <div id="menu"> <ul style="float:left"> <li><a href="home">Home</a></li> <li><a href="about">About Us</a></li> <li><a href="contact">Contact Us</a></li> <li><a href="feedback">Feedback</a></li> <li><a href="faqs">FAQs</a></li> <li><a href="account">My Account</a></li> </ul> <ul style="float:right"> <li><a href="?request_locale=en">English</a></li> <li><a href="?request_locale=vi">Tiếng Việt</a></li> </ul> </div> </div> <div id="main"> <tiles:insertAttribute name="main"/> </div> <div id="right">RIGHT</div> <div id="footer">FOOTER</div> </div> </body> </html>

Tập tin css Layout.css

body{ background: gray; font-size: 12px; } #wrapper{ width: 950px; margin: 10px auto; } #header{ height: 200px;

Page 72: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 391

background-color: yellow; position: relative; } #main{ width: 650px; min-height: 400px; background-color: white; float: left; } #right{ border-left:1px dotted lightgray; width: 299px; min-height: 400px; background-color: aqua; float: right; } #footer{ height: 50px; background-color: lightgray; clear: both; border-top: 1px dashed gray; } #header #menu{ width:98%; position: absolute; left: 10px; bottom: 5px; } #header #menu ul{ list-style: 0px; padding: 0px; margin: 0px; } #header #menu li{ display: inline-block; padding: 0px 5px; margin: 0px 2px; } #header #menu li a{ font-variant: small-caps; font-size: 13px; text-decoration: none; } #header #menu li a:hover{ color:red; }

Bước 2: Home.jsp

Thẻ <tiles:putAttribute> được dùng để cung cấp nội dung cho các vị trí được đánh dấu bởi

<tiles:insertAttribute> cùng tên.

<%@ page contentType="text/html; charset=utf8" pageEncoding="utf8"%> <%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c" %> <%@ taglib uri="http://java.sun.com/jstl/fmt_rt" prefix="fmt" %> <%@ taglib uri="/struts-tags" prefix="s" %> <%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>

Page 73: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 392

<tiles:insertTemplate template="Layout.jsp"> <tiles:putAttribute name="head" value=""/> <tiles:putAttribute name="main"> <h1>Home Page</h1> </tiles:putAttribute>

</tiles:insertTemplate>

Bước 3: LayoutAction.java

Lớp action này chỉ cung cấp các liên kết đến các trang jsp không có lớp action cụ thể. Mục đích

là struts2 hoàn toàn việc truy xuất các trang.

package nnghiem.struts.action; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Result; import org.apache.struts2.convention.annotation.Results; import com.opensymphony.xwork2.ActionSupport; @Results(value={ @Result(name="home", location="/Home.jsp"), @Result(name="about", location="/AboutUs.jsp"), @Result(name="contact", location="/ContactUs.jsp"), @Result(name="feedback", location="/Feedback.jsp"), @Result(name="faqs", location="/FAQs.jsp"), @Result(name="account", location="/MyAccount.jsp"), }) public class LayoutAction extends ActionSupport { @Action(value="/home") public String home(){ return "home"; } @Action(value="/about") public String about(){ return "about"; } @Action(value="/contact") public String contact(){ return "contact"; } @Action(value="/feedback") public String feedback(){ return "feedback"; } @Action(value="/faqs") public String faqs(){

Page 74: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 393

return "faqs"; } @Action(value="/account") public String account(){ return "account"; } }

Bước 4: Web.xml

<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>Struts2Example15</display-name> <listener> <listener-class>org.apache.struts2.tiles.StrutsTilesListener</listener-class> </listener> <filter> <filter-name>struts2</filter-name> <filter-class> org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter </filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list>

</web-app>

Bước 5: Chạy

Bạn bắt đầu chạy với tập tin index.jsp. Trang index.jsp sẽ tự chuyển sang home.action. Sau đây

là nội dung trang index.jsp

<!DOCTYPE HTML> <html> <head> <meta http-equiv="Refresh" content="0;URL=home.action" /> </head> <body></body>

</html>

Page 75: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 394

5.9 Đa ngôn ngữ

5.9.1 Giới thiệu

Website đa ngôn ngữ là website có khả năng tùy biến ít nhất là 2 ngôn ngữ. Khi khách web

chọn ngôn ngữ nào thì toàn bộ các trang web được truy xuất sẽ hiển thị với ngôn ngữ đó.

Sau đây là minh họa của website đa ngôn ngữ (tiếng Anh và tiếng Việt).

Tiếng Việt đang được chọn

Tiếng Anh đang được chọn

Page 76: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 395

Để thực hiện được điều này, bạn phải tách văn bản phụ thuộc ngôn ngữ trình bày ra khỏi trang

web và lưu vào các tập tin tài nguyên. Khi khách web chọn ngôn ngữ nào đó thì văn bản trong

các tập tin tài nguyên tương ứng với ngôn ngữ được chọn sẽ nạp vào để trình bày.

5.9.2 Tập tin tài nguyên

Trong struts2 có 2 loại tập tin tài nguyên là toàn cục (global resouces) và cục bộ (local

resources).

Tài nguyên toàn cục: chứa các văn bản phụ thuộc ngôn ngữ dùng chung cho nhiều trang và

cần được khai báo trong struts.xml hay struts.properties.

Dòng khai báo tài nguyên toàn cục sau đây được đặt trong struts.properties

struts.custom.i18n.resources=GlobalResources

Nội dung của tập tin tài nguyên toàn cục như sau:

GlobalResources.properties GlobalResources_vi.properties

layout.home=Home Page layout.about=About Us layout.contact=Contact Us layout.feedback=Feedback layout.faqs=FAQs layout.account=My Account layout.flag = us.gif

layout.home=Trang Chủ layout.about=Giới Thiệu layout.contact=Liên Hệ layout.feedback=Góp Ý layout.faqs=Hỏi-Đáp layout.account=Tài Khoản layout.flag = vi.gif

LocalResources

LocalResources

GlobalResources

Page 77: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 396

Tài nguyên cục bộ: chứa các văn bản phụ thuộc ngôn ngữ dùng riêng cho một lớp hành động

cụ thể nào đó. Nó buộc phải có tên giống với tên lớp action. Tài nguyên cục bột được đặt tại vị

trí của lớp action và được nhận biết và tài tự động mà không cần phải khải báo.

Trong hình trên bạn thấy các lớp action CustomerAction và LayoutAction điều có tài nguyên cục

bộ riêng đặt ngay tại vị trí của lớp action (CustomerAction.properties +

CustomerAction_vi.properties và LayoutAction.properties + LayoutAction_vi.properties). Bên

cạnh đó website cũng có tài nguyên toàn cục là GlobalResources.properties +

GlobalResources_vi.properties đặt tại thư mục góc của mã nguồn.

5.9.3 Truy xuất tài nguyên

Để truy xuất các văn bản phụ thuộc ngôn ngũ của các tài nguyên bạn cần sử dụng phương

thức getText(String key, String[] args).

Trong JSP bạn sử dụng thẻ <s:text name="layout.home"/> để lấy giá trị của văn bản có key là

layout.home. Các nhãn của các field trên form cũng có thể truy xuât tài nguyên bằng cách sử

dụng thuộc tính key. <s:textfield name="name" key="home.name" />.

Sau đây là một ví dụ:

<h1><s:text name="layout.home"/></h1> <s:form action="locale"> <s:textfield name="name" key="home.name" size="20" /> <s:textfield name="salary" key="home.salary" size="20" /> <s:textfield name="birthday" key="home.birthday" size="20" /> <s:submit name="submit" key="home.submit" />

Page 78: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 397

</s:form>

5.9.4 Lựa chọn ngôn ngữ

Để lựa chọn ngôn ngữ hiển thị, bạn chỉ cần truyền tham số request_locale=<mã ngôn ngữ>

cho bất kỳ action nào.

Sau đây là 2 liên kết giúp bạn chọn ngôn ngữ tiếng Anh hoặc tiếng Việt khi click vào liên kết

tương ứng tham số request_locale sẽ truyền mã ngôn ngữ đến action hiện tại.

<a href="?request_locale=en">English</a> <a href="?request_locale=vi">Tiếng Việt</a>

5.9.5 Ví dụ hoàn chỉnh

Sau đây là mã nguồn hoàn chỉnh của website 2 ngôn ngữ (Anh-Việt). Website được tổ chức các

liên kết điều khiển đăt tại Layout.

Các thành phần trong website:

Các lớp action và tài nguyên cục bộ:

o LayoutAction.java, LayoutAction.properties và LayoutAction_vi.properties

o CustomerAction.java, CustomerAction.properties và CustomerAction_vi.properties

Các tài nguyên toàn cục: GlobalResources.properties

Tập tin khai báo tài nguyên: struts.properties

Layout.jsp là khung mẫu cho các trang thành viên

Home.jsp và MyAccount.jsp là các trang thành viên

Web.xml có cấu hình struts và tiles

Sau đây là nội dụng của các thành phần

LayoutAction.java

package nnghiem.struts; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Result; import org.apache.struts2.convention.annotation.Results; import com.opensymphony.xwork2.ActionSupport; @Results(value={ @Result(name="home", location="/Home.jsp"), @Result(name="about", location="/AboutUs.jsp"), @Result(name="contact", location="/ContactUs.jsp"), @Result(name="feedback", location="/Feedback.jsp"), @Result(name="faqs", location="/FAQs.jsp") }) public class LayoutAction extends ActionSupport{ @Action(value="/home") public String home(){

Page 79: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 398

return "home"; } @Action(value="/about") public String about(){ return "about"; } @Action(value="/contact") public String contact(){ return "contact"; } @Action(value="/feedback") public String feedback(){ return "feedback"; } @Action(value="/faqs") public String faqs(){ return "faqs"; } }

LayoutAction.properties

home.name = Name home.salary = Salary home.birthday = Birthday home.submit = Submit

LayoutAction_vi.properties

home.name = H\u1ECD và tên home.salary = L\u01B0\u01A1ng home.birthday = Ngày sinh home.submit = \u0110\u1ED3ng ý

CustomerAction.java

package nnghiem.struts; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Result; import com.opensymphony.xwork2.ActionSupport; @Result(name="success", location="/MyAccount.jsp") public class CustomerAction extends ActionSupport{ @Action(value="/account") public String execute() throws Exception { return "success"; } }

Page 80: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 399

CustomerAction.properties

account.userId=Login Name account.password=Password

CustomerAction_vi.properties

account.userId=Mã \u0110\u0103ng Nh\u1EADp account.password=M\u1EADt Kh\u1EA9u

GlobalResources.properties

layout.home=Home Page layout.about=About Us layout.contact=Contact Us layout.feedback=Feedback layout.faqs=FAQs layout.account=My Account layout.flag = us.gif

struts.properties

struts.custom.i18n.resources=GlobalResources

Layout.jsp

<%@ page contentType="text/html; charset=utf8" pageEncoding="utf8"%> <%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c" %> <%@ taglib uri="http://java.sun.com/jstl/fmt_rt" prefix="fmt" %> <%@ taglib uri="/struts-tags" prefix="s" %> <%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %> <!DOCTYPE HTML> <html> <head> <title>Layout demo</title> <link href="css/Layout.css" rel="stylesheet"> <tiles:insertAttribute name="head" ignore="true" /> </head> <body> <div id="wrapper"> <div id="header"> <img id="flag" src="images/<s:text name="layout.flag"/>"/> <div id="menu"> <ul style="float:left"> <li><a href="home"><s:text name="layout.home"/></a></li> <li><a href="about"><s:text name="layout.about"/></a></li> <li><a href="contact"><s:text name="layout.contact"/></a></li> <li><a href="feedback"><s:text name="layout.feedback"/></a></li> <li><a href="faqs"><s:text name="layout.faqs"/></a></li> <li><a href="account"><s:text name="layout.account"/></a></li> </ul> <ul style="float:right"> <li><a href="?request_locale=en">English</a></li> <li><a href="?request_locale=vi">Tiếng Việt</a></li>

Page 81: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 400

</ul> </div> </div> <div id="main"> <tiles:insertAttribute name="main"/> </div> <div id="right">RIGHT</div> <div id="footer">FOOTER</div> </div> </body> </html>

Home.jsp

<%@ page contentType="text/html; charset=utf8" pageEncoding="utf8"%> <%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c" %> <%@ taglib uri="http://java.sun.com/jstl/fmt_rt" prefix="fmt" %> <%@ taglib uri="/struts-tags" prefix="s" %> <%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %> <tiles:insertTemplate template="Layout.jsp"> <tiles:putAttribute name="head" value=""/> <tiles:putAttribute name="main"> <h1><s:text name="layout.home"/></h1> <s:form action="locale"> <s:textfield name="name" key="home.name" size="20" /> <s:textfield name="salary" key="home.salary" size="20" /> <s:textfield name="birthday" key="home.birthday" size="20" /> <s:submit name="submit" key="home.submit" /> </s:form> </tiles:putAttribute>

</tiles:insertTemplate>

MyAccount.jsp

<%@ page contentType="text/html; charset=utf8" pageEncoding="utf8"%> <%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c" %> <%@ taglib uri="http://java.sun.com/jstl/fmt_rt" prefix="fmt" %> <%@ taglib uri="/struts-tags" prefix="s" %> <%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %> <tiles:insertTemplate template="Layout.jsp"> <tiles:putAttribute name="head" value=""/> <tiles:putAttribute name="main"> <h1><s:text name="layout.account"/></h1> <ul> <li><s:text name="account.userId"/></li> <li><s:text name="account.password"/></li>

Page 82: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 401

</ul> </tiles:putAttribute> </tiles:insertTemplate>

Web.xml có cấu hình struts và tiles

<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>Struts &amp; Hibernate</display-name> <listener> <listener-class>org.apache.struts2.tiles.StrutsTilesListener</listener-class> </listener> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>

5.10 Chia sẽ dữ liệu

Trong lớp action bạn có thể làm việc với các đối tượng servlet quen thuộc như

HttpServletRequest, HttpServletResponse, HttpSession hay ServletContext một cách dễ dàng

theo 2 cách sau:

Cách 1: sử dụng ServletActionContext

package nnghiem.struts; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.struts2.ServletActionContext; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Result; import com.opensymphony.xwork2.ActionSupport;

Page 83: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 402

@Result(name="success", location="/Success.jsp") public class MyAction extends ActionSupport{ @Action(value="/myAction") public String execute() throws Exception { HttpServletRequest req = ServletActionContext.getRequest(); HttpServletResponse resp = ServletActionContext.getResponse(); HttpSession session = req.getSession(); ServletContext application = ServletActionContext.getServletContext(); return "success"; } }

Cách 2: thi hành theo các interface ServletRequestAware, ServletResponseAware,

HttpSessionAware, ServletContextAware

package nnghiem.struts; import java.util.Map; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Result; import org.apache.struts2.interceptor.ServletRequestAware; import org.apache.struts2.interceptor.ServletResponseAware; import org.apache.struts2.interceptor.SessionAware; import org.apache.struts2.util.ServletContextAware; import com.opensymphony.xwork2.ActionSupport; @Result(name="success", location="/Success.jsp") public class MyAction extends ActionSupport implements ServletRequestAware, ServletResponseAware, SessionAware, ServletContextAware{ @Action(value="/myAction") public String execute() throws Exception { return "success"; } @Override public void setServletContext(ServletContext servletContext) { } @Override public void setSession(Map<String, Object> session) { } @Override public void setServletResponse(HttpServletResponse response) { }

Page 84: Ch5 Struts2 Framework

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK

Nguyễn Nghiệm - Nhất nghệ 403

@Override public void setServletRequest(HttpServletRequest request) { } }