You are on page 1of 84

CÔNG NGHỆ JAVA

CHƯƠNG 5: STRUTS 2X FRAMEWORK

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.

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

320

CÔNG NGHỆ JAVA
5.1.2 Cài đặt môi trường

CHƯƠNG 5: STRUTS 2X FRAMEWORK

Để 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. 2. 3. 4. 5. Actions Interceptors Value Stack / OGNL Results / Result types View technologies

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

321

CÔNG NGHỆ JAVA

CHƯƠNG 5: STRUTS 2X FRAMEWORK

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. 2. 3. 4. 5. 6. Người dùng gửi yêu cầu đến server để thực hiện một công việc nào đó DispatcherFilter tiếp nhận yêu cầu và xác định Action được yêu cầu Một số Intercepter tiền xử lý (kiểm lỗi, upload...) được cấu hình sẽ hoạt động Action được yêu cầu được thực hiện Một số Intercepter hậu xử lý được cấu hình sẽ hoạt động 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

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

322

CÔNG NGHỆ JAVA

CHƯƠNG 5: STRUTS 2X FRAMEWORK

đượ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 Lớp chứa phương thức xử lý yêu cầu người dùng (action method) (HelloWorldAction.java) View (HelloWorld.jsp) Configuration (struts.xml) Trang JSP dùng để hiển thị kết quả sau khi xử lý

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:

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

323

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK Nguyễn Nghiệm .Nhất nghệ 324 .

y.z.Nhất nghệ 325 .CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK  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.jar Nguyễn Nghiệm .z.  commons-fileupload-x. Bạn cần chép vào thư mục WEB-INF/lib của Project.y.jar  commons-io-x.

y.java) Lớp Action là thành phần chính yếu của ứng dụng Struts.y.struts. Nguyễn Nghiệm . 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ị.xwork2. /* * Lớp Action trong struts2 */ public class HelloWorldAction extends ActionSupport{ /* * Phương thức Action */ public String execute() throws Exception { return "success". package nnghiem.jar freemarker-x.y.z.z.opensymphony.z.y. public String getName() { return name.z.y.jar xwork-core.ActionSupport.Nhất nghệ 326 .jar struts2-core-x.y.x.z. 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. Nó thực hiện các vấn đề nghiệp vụ để đáp ứng yêu cầu. } } 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).jar commons-logging-x. } public void setName(String name) { this.struts).CÔNG NGHỆ JAVA         commons-lang-x.GA ognl-x.z. } /* * Thuộc tính của lớp action */ private String name.xy. 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.jar commons-logging-api-x. import com.y.jar javassist-.jar CHƯƠNG 5: STRUTS 2X FRAMEWORK Bước 2: Tạo Action Class (HelloWorldAction.name = name.

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. charset=utf8" pageEncoding="utf8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.jsp) CHƯƠNG 5: STRUTS 2X FRAMEWORK 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.Nhất nghệ 327 .jsp chứa form nhập liệu cung cấp cho HelloWorldAction có mã jsp như sau <%@ page contentType="text/html. Bước 5: Cấu hình Nguyễn Nghiệm . View là trang JSP sử dụng để hiển thị kết của cho người dùng <%@ page contentType="text/html.jsp chứa ô nhập có tên là name và action của form là hello. <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.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.w3.CÔNG NGHỆ JAVA Bước 3: Tạo View (HelloWorld.jsp) Trang index. 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. charset=utf8" pageEncoding="utf8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <html> <head> <title>Hello World</title> </head> <body> Hello World.01 Transitional//EN" "http://www.org/TR/html4/loose.

com/xml/ns/javaee/web-app_2_5.các trang mặc định --> <welcome-file-list> <welcome-file>index.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.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2. Nghĩa là khi bạn đưa ra yêu cầu hello.0"> <!-.0.w3.bộ lọc struts 2 --> <filter> <filter-name>struts2</filter-name> <filter-class> org.xsd" xsi:schemaLocation="http://java.  Tập tin cấu hình web.HelloWorldAction" method="execute"> <result name="success">/HelloWorld.dispatcher. 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 CHƯƠNG 5: STRUTS 2X FRAMEWORK Tập tin cấu hình struts.apache.xml Để chạy được struts. Thẻ <result> khai báo View được sử dụng khi phương thức execute trả về giá trị success.org/2001/XMLSchema-instance" xmlns="http://java.0//EN" "http://struts.dtd"> <struts> <package name="test" extends="struts-default"> <action name="hello" class="nnghiem.xml) của bạn: <?xml version="1.com/xml/ns/javaee" xmlns:web="http://java.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.com/xml/ns/javaee http://java.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.apache. <?xml version="1.struts.sun.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.sun.struts2.CÔNG NGHỆ JAVA  Tập tin cấu hình struts.jsp) lại với nhau.sun.org/dtds/struts-2.sun.Nhất nghệ 328 .jsp</welcome-file> </welcome-file-list> <!-.xml được sử dụng để kết nối các thành phần rời rạc (modelHelloWorldAction và View-HelloWorld.FilterDispatcher </filter-class> Nguyễn Nghiệm .

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.CÔNG NGHỆ JAVA </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app> CHƯƠNG 5: STRUTS 2X FRAMEWORK Bước 6: Chạy thử trong eclipse Phải chuột lên trang index.jsp Bạn cũng có thể xuất thành tập tin ứng dụng web (*.Nhất nghệ 329 .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/ Nguyễn Nghiệm .

xml dựa vào kết quả (success) của execute() 6-Chuyển tiếp sang view (HelloWorld.jsp 1-Chạy index.jsp Struts.CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK Qui trình hoạt động của HelloWorldStruts2 ở trên Index.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.jsp để hiển thị form nhập 2-Submit form đến action hello 3-FilterDispatcher nhận yêu cầu.xml 1 2 3 HelloWorldAction execute() FilterDispatcher 4 7 6 HelloWorld.jsp) đã lựa chọn 7-Hiển thị thuộc tính name cho người dùng Nguyễn Nghiệm .Nhất nghệ 330 . tra cứu action hello trong struts.

xml.struts.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.thực hiện công việc..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.2. Các thuộc tính của lớp action phải tuân theo qui ước của JavaBean.Nhất nghệ 331 .2. 5.ActionSupport.CÔNG NGHỆ JAVA 5. 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ị. 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..age = age. } Nguyễn Nghiệm . 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.1 Định nghĩa lớp CHƯƠNG 5: STRUTS 2X FRAMEWORK  Lớp Action đóng vai trò như một model trong mô hình MVC.. public String <tên phương thức action>() throws Exception{ . } 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. } public void setAge(int age){ this. package nnghiem.2.xwork2.2 Lớp action 5.xml.  Bên trong lớp Action định nghĩa các phương thức action và các thuộc tính JavaBean. import com.opensymphony. 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.. return <giá trị kết quả>. 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.

} } 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.ActionSupport. Lớp này còn định nghĩa các thuộc tính là userId và password.4 Ví dụ CHƯƠNG 5: STRUTS 2X FRAMEWORK Ví dụ sau đây định nghĩa lớp action MemberAction chứa 2 phương thức action là signIn() và input(). Nếu phương thức signIn(0 trả về giá trị o “error”: hiển thị trang LoginError. } return "error". } public String signIn() throws Exception { if(userId.password = password.xwork2.equals("123") ){ return "success". public String getUserId() { return userId. } public String getPassword() { return password. package nnghiem.jsp Nguyễn Nghiệm . 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.equals("user") && password. public class MemberAction extends ActionSupport{ public String input() throws Exception { return "input".opensymphony. password. } public void setUserId(String userId) { this.jsp  Action: login sẽ chạy phương thức signIn(). } String userId. } public void setPassword(String password) { this.jsp o “success”: hiển thị trang MyAccount. Phương thức input() không thực hiện hành động gì chỉ trả về giá trị “input”.struts.userId = userId. Điều này có nghĩa chỉ hiển thị View được ánh xạ trong struts. import com.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.Nhất nghệ 332 .2.CÔNG NGHỆ JAVA 5.

3 Cấu hình struts.3.xml 5.MemberAction"> <result name="input">/LoginInput. <action name="*Member" method="{1}" class="nnghiem.xml.mỗi thẻ tương ứng với một phương thức action.MemberAction"> <action name="login" method="signIn" class="nnghiem.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.struts.jsp</result> <result name="success">/MyAccount.struts.jsp</result> </action> <action name="login" method="signIn" class="nnghiem. 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.struts.0. 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.jsp</result> </action> </package> </struts> 5.dtd"> <struts> <package name="default" extends="default"> <action name="viewLogin" method="input" class="nnghiem.apache.3. bạn sẽ phải khai báo rất nhiều thẻ <action> .struts. <action name="viewLogin" method="input" class="nnghiem.MemberAction"> Dòng khai báo trên có ý nghĩa như sau Nguyễn Nghiệm .action thì chạy phương thức action input() trong lớp action MemberAction.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.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 NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.action thì chạy phương thức action signIn() trong lớp action MemberAction.struts.org/dtds/struts-2.MemberAction"> <result name="error">/LoginError.Nhất nghệ 333 . 5.0//EN" "http://struts.  Nếu yêu cầu đến với tên action là login.

ActionSupport. import com. } /* * Đăng xuất */ public String signOut() throws Exception { return "home".opensymphony. 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.  Nếu một yêu cầu đến Member.Nhất nghệ 334 .struts. 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. } /* * Đăng ký */ public String signUp() throws Exception { return "login". } public String input() throws Exception { return "register". } /* * Cập nhật thông tin tài khoản */ public String updateProfile() throws Exception { return "login". Nguyễn Nghiệm .action thì phương thức execute() bên trong lớp MemberAction sẽ chạy. public class MemberAction extends ActionSupport{ /* * Đăng nhập */ public String signIn() throws Exception { return "account".CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK  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.xwork2. } /* * 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".

jsp</param > </result> 5.  Cách 2: (redirect) <result name="success" type="redirect">/NewWorld.execute() 5.signUp() MemberAction.changePassword MemberAction.forward() để chuyển tiếp đến View.redirect() để chuyển tiếp đến View.Nhất nghệ 335 .jsp</result> Theo cách này Struts framework sử dụng RequestDispatcher.action Member.forgotPassword() MemberAction. Nguyễn Nghiệm .3. 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.CÔNG NGHỆ JAVA } } CHƯƠNG 5: STRUTS 2X FRAMEWORK Với lớp MemberAction như trên.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.updateProfile() MemberAction.action changePasswordMember. signOut() MemberAction.action Phương thức MemberAction. Như vậy View có thể chia sẻ request với lớp action. <result name="success" type="redirect"> <param name="location">/NewWorld. bạn có thể các phương thức action như sau: Yêu cầu signInMember.action signOutMember.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ể.signIn() MemberAction.action forgotPasswordMember.action updateProfileMember. 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.action signUpMember.jsp</result> Theo cách này Struts framework sử dụng HttpServletResponse.

public class MemberAction extends ActionSupport{ public String input() throws Exception { return "input". public class MemberModel { String userId.struts. } } 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.ActionSupport. import com. Để dễ hiểu.equals("user") && password. 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. } public void setPassword(String password) { this. } public void setUserId(String userId) { this.equals("123") ){ return "success". public String getUserId() { return userId. public String getUserId() { return userId. } String userId. } public String signIn() throws Exception { if(userId.opensymphony.Nhất nghệ 336 . } return "error". } public String getPassword() { return password.CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK Trên action sẽ rất rối khi có nhiều thuộc tính và nhiều phương thức action. password.struts. 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. password.userId = userId. chúng ta xét lại ví dụ về lớp MemberAction có mã như sau package nnghiem.xwork2.password = password. } public void setUserId(String userId) { Nguyễn Nghiệm .

userId = userId.opensymphony. import com.opensymphony.password = password. } MemberModel user = new MemberModel(). String password = user. if(userId.getUserId().struts. public class MemberAction extends ActionSupport implements ModelDriven<MemberModel>{ public String input() throws Exception { return "input". } } 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.equals("user") && password.ModelDriven. 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.xwork2.Nhất nghệ 337 . } CHƯƠNG 5: STRUTS 2X FRAMEWORK public void setPassword(String password) { this. Nguyễn Nghiệm . @Override public MemberModel getModel() { return user. } public String signIn() throws Exception { String userId = user. } public String getPassword() { return password.xwork2.getPassword(). } } 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.ActionSupport.equals("123") ){ return "success". } return "error". import com.CÔNG NGHỆ JAVA this.

} /* * Quên mật khẩu */ Nguyễn Nghiệm .struts2. location="/login.jsp").jsp") }) public class MemberAction extends ActionSupport { /* * Đăng nhập */ @Action(value="signIn". @Result(name="login".Nhất nghệ 338 .annotation.jsp") } ) public String signIn() throws Exception { return "account". type="redirect"). import org.struts.5 Annotation CHƯƠNG 5: STRUTS 2X FRAMEWORK Ở phần trên bạn phải sử dụng struts.convention. location="/index. location="/account. results={ @Result(name="home".apache.annotation. @Results(value={ @Result(name="input".Result.ActionSupport.Results.jsp". results={ @Result(name="account". } /* * Đăng xuất */ @Action(value="signOut".Action.xml để khai báo ánh xạ các action và view của ứng dụng lại với nhau.CÔNG NGHỆ JAVA 5.apache.struts2.opensymphony.struts2. import org. @Result(name="error".apache.convention. location="/error.jsp") } ) public String signOut() throws Exception { return "home". } /* * Đăng ký */ @Action(value="signUp") public String signUp() throws Exception { return "login".xwork2. location="/register. import org.convention. 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. import com. package nnghiem.annotation.

@Result(name="error".Nhất nghệ 339 ..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".jsp") }) Nguyễn Nghiệm . Ví dụ: signIn()..jsp"). location="/register. location="/error. } /* * Hiển thị form đăng ký */ @Action(value="input") public String input() throws Exception { return "register". location="/account. input(). type="redirect").jsp". } } 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. @Action(value="signUp")  Thuộc tính results chỉ ra các kết quả trả về của phương thức action. signUp(). } /* * Cập nhật thông tin tài khoản */ @Action(value="updateProfile") public String updateProfile() throws Exception { return "login". Ví dụ: signIn() và signOut() @Action(value="signIn". @Result(name="login". results={ @Result(name="account". location="/login. } /* * Đổi mật khẩu */ @Action(value="changePasword") public String changePasword() throws Exception { return "login".CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK @Action(value="forgotPassword") public String forgotPassword() throws Exception { return "login".

6. là dấu lớn hơn--> <s:if test="now.else if. if.6.1 Thẻ điều khiển 5..  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.hours &lt. 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.case trong java. 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. <!--&lt.Nhất nghệ 340 . <!—tạo một bean chứa thời gian hiện tại--> <s:bean var="now" name="java. là dấu nhỏ hơn. 17"> Nguyễn Nghiệm .CÔNG NGHỆ JAVA 5.. là dấu nhỏ hơn.. 12"> <div>Good morning</div> </s:if> <s:elseif test="now... &gt.util.6 Các thẻ thông dụng 5.1 Thẻ lựa chọn <s:if> CHƯƠNG 5: STRUTS 2X FRAMEWORK 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.1. Ngược lại xuất chức năng đăng nhập. 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.else và switch.Date"/> <!--&lt. &gt.hours &gt.. quên mật khẩu và đăng ký.

Nhất nghệ 341 . Nguyễn Nghiệm . 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.struts.java) package nnghiem.CÔNG NGHỆ JAVA <div>Good evening</div> </s:elseif> <s:else> <div>Hello</div> </s:else> CHƯƠNG 5: STRUTS 2X FRAMEWORK Ví dụ 3: minh họa hoàn chỉnh giữa Action và View.

annotation. charset=UTF-8" %> <%@ taglib prefix="s" uri="/struts-tags" %> <html> <head> <title>Example of If and Else</title> </head> <body> Nguyễn Nghiệm . else và elseif: <%@ page contentType="text/html. @Result(name="success".jsp) <%@ page contentType="text/html. import org.CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK import org. 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.name = name. } public String getName() { return name. } public void setName(String name) { this. location="MyView.Nhất nghệ 342 .apache.struts2.Result.jsp) sử dụng các lệnh if.annotation.convention.jsp") public class MyAction{ private String name. } } Bước 2: Tạo trang chứa form nhập (MyInput.Action. @Action(value="/hello") public String execute() throws Exception { return "success".apache.struts2.convention.

} Nguyễn Nghiệm .apache.convention.jsp") public class Employee { private List<Employee> employees. location="Employee. Thông thường <s:iterate> được sử dụng để duyệt các tập dữ liệu như Collection. public List<Employee> getEmployees() { return employees..while).struts2.util. import java.Nhất nghệ 343 .6.ArrayList.List.annotation. import java. </s:if> <s:elseif test="name=='Jason'"> You have selected 'Jason' </s:elseif> <s:else> You have not selected 'Mike' or 'Jason'. for hay do.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.  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ị.util. </s:else> </body> </html> 5. @Result(name="success".1.Action. import org.CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK <b>Example of If and Else</b><br/> <s:if test="name=='Mike'"> You have selected 'Mike'.. 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. Map và mảng đặt trên ValueStack.struts.

return "success".CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK public void setEmployees(List<Employee> employees) { this. } public String getDepartment() { return department."Accounts")).name = name. employees. } public void setDepartment(String department) { this. 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"/> .String department) { this. } @Action(value="/employee") public String execute() { employees = new ArrayList<Employee>(). public Employee(){} public Employee(String name. employees.department = department.add(new Employee("Melissa".Nhất nghệ 344 . } public String getName() { return name. } } 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. } private String name.name = name."Recruitment")).department = department."Accounts")).employees = employees. } public void setName(String name) { this."Recruitment")).add(new Employee("George". <s:property value="department"/><br/> Nguyễn Nghiệm .add(new Employee("Rose". private String department. employees. this.add(new Employee("Danielle".jsp hiển thị tập hợp <%@ page contentType="text/html. employees.

CÔNG NGHỆ JAVA </s:iterator> </body> </html> CHƯƠNG 5: STRUTS 2X FRAMEWORK 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. Để đơ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. file và hidden.01 Transitional//EN" "http://www.w3.2 Thẻ form 5.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 Nguyễn Nghiệm .6.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.2. charset=utf8" pageEncoding="utf8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.6.Nhất nghệ 345 . textarea.action bạn sẽ nhận được kết quả như sau 5.

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK 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> Nguyễn Nghiệm .Nhất nghệ 346 .

</s:form> Sẽ sinh mã tương ứng <form id="hello" name="hello" action="/HelloWorldStruts2/hello..CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK </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 M ỗi Mỗi M ỗi form struts2 sẽ sinh ra một form HTML và có một bảng để trang trí các phần tử phần tử giao diện sẽ sinh ra một hàng 2 ô trên bảng trường ẩn chỉ sinh thẻ ẩn 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"> .Nhất nghệ 347 .... </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 Nguyễn Nghiệm .action" method="post" enctype="multipart/form-data"> <table class="wwFormTable"> .

2 Các thẻ nhóm Để tiện cho việc sử dụng các phần tử giao diện.Nhất nghệ 348 .CÔNG NGHỆ JAVA <s:submit value="Submit" /> CHƯƠNG 5: STRUTS 2X FRAMEWORK 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. charset=utf8" pageEncoding="utf8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <html> <head> <title>Hello World</title> <s:head /> </head> <body> <s:form action="hello. Ví dụ sau đây sẽ cho bạn biết cách sử dụng các thẻ nhóm <%@ page contentType="text/html.'0':'female'} " /> <s:checkboxlist name="hobbies" label="Sở thích" list="{'sports'.'shopping'}" /> </s:form> </body> </html> Kết quả hiển thị Nguyễn Nghiệm .action"> <s:radio name="gender" label="Giới tính" list="#{'1':'male'.6. struts2 cung cấp 2 thể dùng để nhóm các radio button và checkbox lại thành từng nhóm.2.'tv'.

css" type="text/css"/> <script src="/HelloWorldStruts2/struts/utils.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> Nguyễn Nghiệm .CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK Mã HTML được sinh ra <html> <head> <title>Hello World</title> <link rel="stylesheet" href="/HelloWorldStruts2/struts/xhtml/styles.Nhất nghệ 349 .js" type="text/javascript"></script> </head> <body> <form id="hello" action="hello.

CÔNG NGHỆ JAVA </html> CHƯƠNG 5: STRUTS 2X FRAMEWORK 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. key2:value2. <%@ page contentType="text/html.'Smith'}" /> <s:select label="Company Office" name="mySelection" value="{'America'}" list="#{'America':'America'}"> <s:optgroup label="Asia" list="#{'India':'India'.6. Ví dụ sau sẽ cho bạn thấy khả năng sử dụng thẻ <select> trong struts.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.}.  Các phần tử trong mang {a.c.Please Select ---" emptyOption="true" value="capricorn" /> </s:form> </body> </html> Nguyễn Nghiệm .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.2. Giá trị của list có thể là mảng {a.b.'China':'China'} " /> <s:optgroup label="Europe" list="#{'UK':'UK'.action"> <s:select name="username" label="Username" list="{'Mike'.'Italy':'Italy'} " /> </s:select> <s:combobox label="My Sign" name="mySign" list="#{'aries':'aries'.c} hoặc bảng băm #{key1:value1.'John'.Nhất nghệ 350 ..'Sweden':'Sweden'..'capricorn':'capricorn'} " headerKey="-1" headerValue="--. charset=utf8" pageEncoding="utf8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <html> <head> <title>Hello World</title> <s:head /> </head> <body> <s:form action="login..

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK <html> <head> <title>Hello World</title> <link rel="stylesheet" href="/HelloWorldStruts2/struts/xhtml/styles.js" type="text/javascript"></script> </head> <body> <form id="login" action="login.css" type="text/css"/> <script src="/HelloWorldStruts2/struts/utils.Nhất nghệ 351 .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> Nguyễn Nghiệm .

selectedIndex].options[targetElement.value == '') { return."> <option value="-1">--. } targetElement.form.value.Nhất nghệ 352 . } </script> <input type="text" name="mySign" value="capricorn" id="login_mySign"/><br /> <select onChange="autoPopulate_login_mySign(this). charset=utf8" pageEncoding="utf8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK <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.elements['mySign'].options[targetElement.selectedIndex]. } if (targetElement. Đ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.selectedIndex].value = targetElement.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.value == -1) { return.options[targetElement.01 Transitional//EN" Nguyễn Nghiệm .

css_xhml và xhtml (mặc định).> Mã HTML được sinh ra <!DOCTYPE html> <html> <head> <link rel="stylesheet" href="/HelloWorldStruts2/struts/xhtml/styles. 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”.w3..action" method="post" enctype="multipart/form-data"> <input type="text" name="from" value="" id="hello_from"/> Nguyễn Nghiệm .org/TR/html4/loose.js" type="text/javascript"></script> <title>Hello World</title> </head> <body> <form id="hello" name="hello" action="/HelloWorldStruts2/hello.css" type="text/css"/> <script src="/HelloWorldStruts2/struts/utils..Nhất nghệ 353 .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.CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK "http://www. Nghĩa là khi bạn sử dụng theme=”xhtml” thì mã HTML được sinh ra như trên.

action" method="post" enctype="multipart/form-data"> <div id="wwgrp_hello_from" class="wwgrp"> Nguyễn Nghiệm .dtd"> <html> <head> <link rel="stylesheet" href="/HelloWorldStruts2/struts/xhtml/styles.js" type="text/javascript"></script> <title>Hello World</title> </head> <body> <form id="hello" name="hello" action="/HelloWorldStruts2/hello.  <s:form theme=”css_xhtml”. 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...css" type="text/css"/> <script src="/HelloWorldStruts2/struts/utils.> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK <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.org/TR/html4/loose.Nhất nghệ 354 .01 Transitional//EN" "http://www.w3.

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK <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.Nhất nghệ 355 . 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"> Nguyễn Nghiệm .

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.6.  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. mỗi tập tin upload bạn phải khai báo 3 field để chứa file. 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”. private String documentFileName. private String documentContentType. 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. bạn cần phải biết được đường dẫn vật lý của thư mục đó. private File document.CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK <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. <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.Nhất nghệ 356 .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. private String photoContentType. Nguyễn Nghiệm . private String photoFileName.2.

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. photo. Nguyễn Nghiệm . Trang web cho phép upload 2 file (1 ảnh và một bất kỳ).CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK ServletContext application = ServletActionContext.getServletContext(). 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.Nhất nghệ 357 .getRealPath("upload"). Dòng mã sau cho phép chuyển file photo vào thư mục “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. String directory = application.renameTo(new File(directory.

jsp) CHƯƠNG 5: STRUTS 2X FRAMEWORK Các thành phần bạn cần phải tạo ra trong phần này gồm <%@ page contentType="text/html.io.servlet.struts.java) Bước 1: Trang input (UploadForm.Nhất nghệ 358 . import org.File.jsp)  Trang view (UploadSuccess. Nguyễn Nghiệm .ServletActionContext.jsp)  Lớp Action (UploadAction.CÔNG NGHỆ JAVA  Trang input (UploadForm.struts2. 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.ServletContext.apache.jsp) <%@ page contentType="text/html. import javax. 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. import java.

location="/UploadForm.CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK import org. public File getPhoto() { return photo. import com.jsp").getRealPath("upload"). } public String getPhotoFileName() { return photoFileName. @Results(value={ @Result(name="form". import org. // lưu tập tin ảnh photo. } public void setPhotoContentType(String photoContentType) { this. } public void setPhoto(File photo) { this. } public String getPhotoContentType() { return photoContentType. @Result(name="success". } /*--for uploading photo--*/ private File photo.annotation. String directory = application.photo = photo.renameTo(new File(directory.apache.struts2.annotation. Nguyễn Nghiệm .convention.Action.annotation.ActionSupport.renameTo(new File(directory.convention. import org.struts2.opensymphony.jsp") }) public class UploadAction extends ActionSupport{ @Action(value="/viewUploadForm") public String input() throws Exception { return "form".apache. photoFileName)).getServletContext(). location="/UploadSuccess.xwork2. documentFileName)).photoContentType = photoContentType. // lưu tập tin tài liệu photo.convention. } @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.struts2. private String photoContentType. return "success".Result.apache.Results.Nhất nghệ 359 . private String photoFileName.

photoFileName = photoFileName.6.convention. } public void setDocumentContentType(String documentContentType) { this.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.6. } } 5. Nguyễn Nghiệm . import org.Nhất nghệ 360 . private String documentFileName.3.struts2. } public void setDocument(File document) { this. } public String getDocumentContentType() { return documentContentType.apache.Action.document = document.documentContentType = documentContentType.documentFileName = documentFileName. } public String getDocumentFileName() { return documentFileName. } public void setDocumentFileName(String documentFileName) { this.annotation. Nội dung của thẻ được sinh ra từ hành hành động các khai báo result trong struts.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.CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK } public void setPhotoFileName(String photoFileName) { this. private String documentContentType.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. } /*--for uploading document--*/ private File document. Sau đây là danh sách các thẻ dữ liệu thường dùng nhất. public File getDocument() { return document. 5.struts.

struts2. 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. } }  Trang hiển thị MyView.jsp") public class MyAction{ private String name. @Result(name="success".convention.action bạn sẽ nhận được kết quả Nguyễn Nghiệm .annotation.Result. } public String getName() { return name.apache.jsp hoặc myAction. @Action(value="/myAction") public String execute() throws Exception { return "success". 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. } public void setName(String name) { this.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.CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK import org.name = name. location="MyView.Nhất nghệ 361 .

import org.Third Syntax --> <s:include value="myJsp.jsp"> <s:param name="param1" value="value2" /> <s:param name="param2" value="value2" /> </s:include> <!-.annotation.jsp") public class MyAction{ @Action(value="/myAction") public String execute() throws Exception { return "success".jsp có nội dung như sau: <%@ page contentType="text/html.apache.apache. Nguyễn Nghiệm .struts2.convention. location="MyView. Bạn có thể thay thế bằng <s:action> đã học trước đây.2 Thẻ <s:include> CHƯƠNG 5: STRUTS 2X FRAMEWORK Thẻ này tương đương như <jsp:include> của JSP.convention.First Syntax --> <s:include value="myJsp.Result.3.Blue.struts2.Nhất nghệ 362 . import org. <!-. dùng để bao hàm một tập tin JSP khác.Indigo.Action.jsp" /> <!-.CÔNG NGHỆ JAVA 5. } }  Các trang view MyInclude.jsp"> <s:param name="param1">value1</s:param> <s:param name="param2">value2</s:param> </s:include>  Lớp Action: package nnghiem.annotation.Second Syntax --> <s:include value="myJsp. @Result(name="success".6. 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.struts.

Red'}" count="7" separator=".Yellow.action bạn sẽ nhận được kết quả sau: Nguyễn Nghiệm .CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK Green.Nhất nghệ 363 .Orange."> <s:iterator> <s:property /><br/> </s:iterator> </s:generator> </body> </html>  MyView.jsp có nội dung như sau: <%@ page contentType="text/html.jsp"/> </body> </html>  Chạy myAction. 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.

@Result(name="success". } }  Các trang View MyView.3.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> Nguyễn Nghiệm .CÔNG NGHỆ JAVA 5. charset=UTF-8" %> <%@ taglib prefix="s" uri="/struts-tags" %> <html> <head> <title>Hello World</title> </head> <body> <s:bean name="org. import org. Nó cho phép tạo mới một đối tượng.Nhất nghệ 364 .3 Thẻ <s:bean> CHƯƠNG 5: STRUTS 2X FRAMEWORK 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.struts2.6. 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.convention.struts2.apache. import org.jsp") public class MyAction{ @Action(value="/myAction") public String execute() throws Exception { return "success".apache. location="MyView.annotation.util.util.jsp: <%@ page contentType="text/html.Action.struts2.struts2.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>.apache.apache. <s:bean name="org.  Lớp Action: package nnghiem.convention.annotation.Result.struts.

struts.util.birthday" name="person.Action.birthday" format="dd/MM/yyyy" /> format="%{getText('some.6.annotation.Date.birthday" name="person. } public void setCurrentDate(Date date){ this. điều này có nghĩa là counter chứa danh sách các số 20.key')}" /> nice="true" /> />  Lớp Action: package nnghiem. import org.convention.birthday" name="person. 25.currentDate = date.jsp Nguyễn Nghiệm .struts2. import org.3.struts2.CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK  Chạy myAction.struts2.apache.Nhất nghệ 365 .Result.action bạn sẽ nhận được kết quả sau đây: Trong ví dụ trên chúng ta sử dụng org. 21.apache.i18n.jsp") public class MyAction{ private Date currentDate. Bean được tạo ra và đặt vào valuestack và vì vậy được sử dụng trong trang jsp 5. 22. 24. @Result(name="success". } }  Các trang View MyView. import java.annotation. } public Date getCurrentDate(){ return currentDate.convention.4 Thẻ <s:date> Thẻ này dùng để định dạng thời gian (ngày và giờ) <s:date <s:date <s:date <s:date name="person. location="MyView. 23. @Action(value="/myAction") public String execute() throws Exception { return "success".apache.Counter và thiết lập thuộc tính first là 20 và last là 25.util.

CÔNG NGHỆ JAVA

CHƯƠNG 5: STRUTS 2X FRAMEWORK

<%@ 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

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

366

CÔNG NGHỆ JAVA
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; } }

CHƯƠNG 5: STRUTS 2X FRAMEWORK

 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>

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

367

CÔNG NGHỆ JAVA
<head> <title>System Details</title> </head> <body>

CHƯƠNG 5: STRUTS 2X FRAMEWORK

<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:

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

368

CÔNG NGHỆ JAVA
5.6.3.6 Thẻ <s:text>

CHƯƠNG 5: STRUTS 2X FRAMEWORK

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>

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

369

success = This is success message name.param : {0} struts.custom.dtd"> <struts> <constant name="struts.msg.0//EN" "http://struts.resources" value="GlobalResources"/> <package name="empty" extends="struts-default"> </package> </struts>  Kết quả chạy myAction.apache.success"/><br> <s:text name="name.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.i18n.msg.0.properties) đặt cùng vị trí với lớp Action hoặc trong classpath có nội dung như sau: name.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.action như sau: Nguyễn Nghiệm .Nhất nghệ 370 .xml <?xml version="1.org/dtds/struts-2.xyz">Message doesn't exists</s:text><br> <s:text name="name.param = The param example .CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK <s:i18n name="MyAction"> <s:text name="name.

CÔNG NGHỆ JAVA 5. 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> Nguyễn Nghiệm .name = name.jsp <%@ page contentType="text/html.Action. import org.convention. @Action(value="/myAction") public String execute() throws Exception { return "success".action"> <s:param name="id" value="%{selected}" /> </s:url> <!-.apache. } public String getName() { return name.3.struts2. } }  Các trang View MyView.jsp") public class MyAction{ private String name.7 Thẻ <s:url> CHƯƠNG 5: STRUTS 2X FRAMEWORK 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 <!-. } public void setName(String name) { this. location="MyView.apache.struts2.convention.6. import org.annotation.Result.struts.Example 2 --> <s:url action="editGadget"> <s:param name="id" value="%{selected}" /> </s:url> <!-.Nhất nghệ 371 .Example 1 --> <s:url value="editGadget.Example 3--> <s:url includeParams="get"> <s:param name="id" value="%{'22'}" /> </s:url>  Lớp Action package nnghiem. @Result(name="success".annotation.

jsp <s:fielderrors> [invalid] validate() setXyz() [request] [valid] [response] success.Nhất nghệ action() [response] 372 .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.jsp Nguyễn Nghiệm .  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.action như sau: 5. Vì vậy tất cả các action có kiểm lỗi đều phải khai báo input input.CÔNG NGHỆ JAVA </s:url> <a href='<s:property value="#myurl"/>'> <s:property value="#myurl"/></a> </body> </html> CHƯƠNG 5: STRUTS 2X FRAMEWORK <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.

 Trong phương thức validate() của lớp action.Nhất nghệ 373 .1 Kiểm lỗi bằng tay Để kiểm lỗi bằng tay.7. 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. bạn sử dụng phương thức addFieldError() để tích lũy các lỗi. 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: Nguyễn Nghiệm .CÔNG NGHỆ JAVA Struts2 cung cấp 3 phương pháp kiểm lỗi: CHƯƠNG 5: STRUTS 2X FRAMEWORK  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.  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ệ.

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.} .}: định nghĩa css cho các thông báo lỗi <%@ page contentType="text/html.CÔNG NGHỆ JAVA     CHƯƠNG 5: STRUTS 2X FRAMEWORK Để thực hiện việc kiểm lỗi như trên. 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. bạn cần phải viết ra các thành phần sau đây: Validate. args)).errorMessage li{color:red.Nhất nghệ 374 .jsp là trang input Success.} </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. Vì vậy nhiệm vụ của bạn là phải đặt mã kiểm tra trong đó là được.}: ẩn các lỗi hiển thị sau mỗi field o .jsp là trang view ValidateAction.java là lớp action chứa phương thức kiểm lỗi (validate()) ValidateAction. Phương thức tích lũy thông báo lỗi addFieldError(fieldName. getText(key. nó sẽ được gọi để thực hiện kiểm tra tính hợp lệ của dữ liệu.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. được hiểu như sau: Nguyễn Nghiệm .java Trong lớp action bạn hãy chú ý vào phương thức validate().errorMessage li{color:red. Bạn cũng cần phải khai báo trang input để khi gặp lỗi sẽ được tự động quay về.

@Result(name="success".struts.matches("^(5\\d-[A-Z]\\d-\\d{4})$")){ addError("moto". "255")..convention.required". "errors.args){ Nguyễn Nghiệm . String.apache. "Notes".range". } if(!moto.required.CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK  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.\\w+)$")){ addError("email". } if(age < 18 || age > 55){ addError("age".struts2.Result.maxlength".minlength".required".. } } void addError(String fieldName. package nnghiem.apache. "errors. location="/Validate. "Id").invalid".ActionSupport.annotation. } if(password != null && password. "errors.annotation. "errors.Nhất nghệ 375 . @Results(value={ @Result(name="input". import com.action. "errors. "errors. "Name"). } if(email == null || email.xwork2.invalid". } if(notes != null && notes.Results.length() == 0){ addError("name". errors. "55").properties) với khóa (key: errors.required".matches("^(\\w+@\\w+\\.opensymphony.Action. "18". import org.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).struts2. "Password". import org. "Moto").jsp").length() > 255){ addError("notes". "Email"). "Age". } if(name == null || name. } else if(!email. "errors. "6").convention. } @Override public void validate() { if(id == null || id.jsp") }) public class ValidateAction extends ActionSupport { @Action(value="/validate") @Override public String execute() throws Exception { return "success". "Email").length() == 0){ addError("email".convention. import org.apache.length() == 0){ addError("id". location="/Success. String key. "errors.struts2.annotation.length() < 6){ addError("password".

password. name. args)).email = email. public String getId() { return id.id = id. notes. } public String getPassword() { return password. } public void setPassword(String password) { this. } public String getName() { return name. email. } public void setAge(int age) { this.password = password. } public String getMoto() { return moto.Nhất nghệ 376 . } public void setName(String name) { this. moto. int age. } public void setId(String id) { this.name = name.age = age. } Nguyễn Nghiệm . } public String getEmail() { return email. String id.moto = moto.CÔNG NGHỆ JAVA } CHƯƠNG 5: STRUTS 2X FRAMEWORK addFieldError(fieldName. } public void setEmail(String email) { this. getText(key. } public String getNotes() { return notes. } public int getAge() { return age. } public void setMoto(String moto) { this.notes = notes. } public void setNotes(String notes) { this.

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. “55”}.jsp Đây là tập tin View.properties errors. String[] args = {“Tuoi”.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. args).7. chúng ta Nguyễn Nghiệm . “18”. 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.maxlength=<b><i>{0}</i></b> phai nho hon {1} errors. Bước 4: Success. 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”. 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.required=<b><i>{0}</i></b> la bat buoc errors.CÔNG NGHỆ JAVA } CHƯƠNG 5: STRUTS 2X FRAMEWORK Bước 3: ValidateAction.minlength=<b><i>{0}</i></b> phai lon hon {1} errors. String message = getText(key.Nhất nghệ 377 . String[] args).range=<b><i>{0}</i></b> phai tu {1} den {2} errors. Để hiểu rõ hơn. 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ự.

jsp) Lớp action (ValidateAction.xml) Tập tin tài nguyên thông báo lỗi (ValidateAction.properties) Trang view (Success.jsp) Trang web này không thay đổi so với phần kiểm lỗi bằng tay Nguyễn Nghiệm .java) Tập tin kiểm lỗi (ValidateAction-validate.CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK 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) Bước 1: trang input (Validate.Nhất nghệ 378 .

annotation.apache. } String id.struts2.Action. name.struts2.xwork2.java) CHƯƠNG 5: STRUTS 2X FRAMEWORK Không có phương thức kiểm lỗi validate(). } public void setEmail(String email) { this. org. } public String getName() { return name.convention.ActionSupport. password.apache. com. } public void setId(String id) { this.Result.annotation.action.struts2.struts.name = name.convention. } public void setPassword(String password) { this.Nhất nghệ 379 . import import import import org.opensymphony.CÔNG NGHỆ JAVA Bước 2: lớp action (ValidateAction. @Results(value={ @Result(name="input". } Nguyễn Nghiệm .jsp") }) public class ValidateAction extends ActionSupport { @Action(value="/validate") @Override public String execute() throws Exception { return "success".jsp").annotation. location="/Validate. moto. } public String getEmail() { return email.password = password.apache.Results. package nnghiem.id = id. org. @Result(name="success". location="/Success. chỉ cần khai báo trang input để khi gặp lỗi sẽ quay về. int age. } public String getPassword() { return password. notes. public String getId() { return id.email = email.convention. } public void setName(String name) { this.xml. email.

required"/> </field-validator> </field> <field name="email"> <field-validator type="requiredstring"> <message key="email. } } CHƯƠNG 5: STRUTS 2X FRAMEWORK Bước 3: tập tin khai báo kiểm lỗi (ValidateAction-validate. } public void setNotes(String notes) { this.com/xwork/xwork-validator-1. } public int getAge() { return age.CÔNG NGHỆ JAVA public String getMoto() { return moto. 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.2//EN" "http://www.moto = moto.dtd"> <validators> <field name="id"> <field-validator type="requiredstring"> <message key="id.0. } public String getNotes() { return notes.format"/> Nguyễn Nghiệm .opensymphony.0.properties (xem bước tiếp theo) <!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.required"/> </field-validator> </field> <field name="name"> <field-validator type="requiredstring"> <message key="name. } public void setAge(int age) { this.Nhất nghệ 380 .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).notes = notes.required"/> </field-validator> <field-validator type="email"> <message key="email. } public void setMoto(String moto) { this.2.age = age.

Nhất nghệ 381 .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.CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK </field-validator> </field> <field name="password"> <field-validator type="stringlength"> <param name="minLength">6</param> <message key="password.range=Age must be between ${min} and ${max} notes.range"/> </field-validator> </field> </validators> Bước 4: tập tin tài nguyên thông báo lỗi (ValidateAction.format=Email is invalid format Bước 5: trang view (Success.required=Id is required field 123 name.minlength=Notes must be greater than ${minLength} id.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.maxlength"/> </field-validator> </field> <field name="age"> <field-validator type="int"> <param name="min">18</param> <param name="max">55</param> <message key="age.format=Moto is invalid Saigon region password.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"> Nguyễn Nghiệm .format"/> </field-validator> </field> <field name="notes"> <field-validator type="stringlength"> <param name="maxLength">255</param> <message key="notes.required=Name is required field email.maxlength=Notes must be less than ${maxLength} moto.required=Email is required field email.

CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK <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.. <field-validator type="expression"> <param name="expression">.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..</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> Nguyễn Nghiệm .Nhất nghệ 382 ..123</param> <param name="maxExclusive">99.

7.Nhất nghệ 383 .jsp) Bước 1: Trang input (Validate.CÔNG NGHỆ JAVA </field-validator> </field> CHƯƠNG 5: STRUTS 2X FRAMEWORK  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.jsp) Nguyễn Nghiệm .jsp) Lớp action (ValidateAction.3 Kiểm lỗi bằng Annotation Khác với 2 phương pháp trước .properties) Trang view (Success. Trong bài này bạn cần phải tạo các thành phần sau đây     Trang input (Validate.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.java) Tập tin tài nguyên thông báo lỗi (ValidateAction.

validator.annotations.validator.annotations.apache.xwork2. } @RequiredStringValidator(key="name. int age. location="/Success.xwork2.id = id.anotation. @RequiredStringValidator(key="id.annotation.struts2.required") @EmailValidator(key="email. @Results(value={ @Result(name="input".validator.xwork2.opensymphony.annotations.xwork2.validator. email.format") public String getEmail() { return email.xwork2.opensymphony.opensymphony.name = name.apache. CHƯƠNG 5: STRUTS 2X FRAMEWORK import org.annotation.convention. import org.validator.struts.ActionSupport.jsp").Result.opensymphony.java) package nnghiem.convention. } public void setId(String id) { this.RegexFieldValidator. import import import import import import com. location="/Validate.struts2. password.opensymphony. } String id.annotation.RequiredStringValidator. com.required") public String getName() { return name. } @RequiredStringValidator(key="email. moto. } public void setEmail(String email) { this.IntRangeFieldValidator. import org. name.struts2.annotations.annotations.apache.xwork2.action. Nguyễn Nghiệm .opensymphony.EmailValidator.StringLengthFieldValidator. com.email = email.convention.jsp") }) public class ValidateAction extends ActionSupport { @Action(value="/validate") @Override public String execute() throws Exception { return "success". com.Action. @Result(name="success". } public void setName(String name) { this. com. notes.required") public String getId() { return id.Results.CÔNG NGHỆ JAVA Giống như trước đây Bước 2: Lớp action (ValidateAction.Nhất nghệ 384 . com.

password = password. 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. public class ValidateAction extends ActionSupport { @SkipValidation @Action(value="/validate") public String execute() throws Exception { Nguyễn Nghiệm . } public void setPassword(String password) { this. maxLength="255") public String getNotes() { return notes. minLength="6") public String getPassword() { return password. } @RegexFieldValidator(key="moto.jsp) Giống như trước đây Bỏ qua validate cho 1 phương thức action Thông thường.moto = moto. } @IntRangeFieldValidator(key="age. 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. Để thực hiện điều này. min="18".range".age = age. } public void setNotes(String notes) { this.format". max="55") public int getAge() { return age.notes = notes. bạn sử dụng annotation @SkipValidation.CÔNG NGHỆ JAVA } CHƯƠNG 5: STRUTS 2X FRAMEWORK @StringLengthFieldValidator(key="password. } @StringLengthFieldValidator(key="notes. } public void setAge(int age) { this. } } 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. } public void setMoto(String moto) { this. Đô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.Nhất nghệ 385 .maxlength". expression="^(5\\d-[A-Z]\\d-\\d{4})$") public String getMoto() { return moto.minlength".

} } CHƯƠNG 5: STRUTS 2X FRAMEWORK 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". shortCircuit = true) public String getEmail() { return email. } }  EmailValidator Kiểm lỗi định dạng email public class Employee extends ActionSupport{ @EmailValidator(message = "Default message". } }  DoubleRangeFieldValidator Kiểm lỗi phạm vi số thực public class Employee extends ActionSupport{ @DoubleRangeFieldValidator(message = "Default message". shortCircuit = true) public String getName() { return name. key = "i18n. key = "i18n.key". min = "2005/01/01". key = "i18n.key". key = "i18n. shortCircuit = true.Nhất nghệ 386 .CÔNG NGHỆ JAVA return "success". } }  DateRangeFieldValidator Kiểm lỗi phạm vi thời gian public class Employee extends ActionSupport{ @DateRangeFieldValidator(message = "Default message". max = "2005/12/31") public String getDOB() { return dob.key". minInclusive = "0.123". shortCircuit = true.987") public String getIncome() { return income.key". } } Nguyễn Nghiệm . maxInclusive = "99.

expression = "an OGNL expression" )  IntRangeFieldValidator Kiểm lỗi phạm vi số nguyên public class Employee extends ActionSupport{ @IntRangeFieldValidator(message = "Default message". shortCircuit = true.key".field".key". min = "0".key". } }  StringLengthFieldValidator Nguyễn Nghiệm . key = "i18n. shortCircuit = true. max = "42") public String getAge() { return age. trim = true) public String getName() { return name. } }  RegexFieldValidator Kiểm lỗi tùy vào biểu thức chính qui @RegexFieldValidator( key = "regex.Nhất nghệ 387 .CÔNG NGHỆ JAVA  ExpressionValidator CHƯƠNG 5: STRUTS 2X FRAMEWORK 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". shortCircuit = true. key = "i18n. } }  RequiredStringValidator Kiểm lỗi không để trống chuỗi public class Employee extends ActionSupport{ @RequiredStringValidator(message = "Default message". key = "i18n. key = "i18n. shortCircuit = true) public String getAge() { return age. expression = "yourregexp")  RequiredFieldValidator Kiểm lỗi null public class Employee extends ActionSupport{ @RequiredFieldValidator(message = "Default message".key".

} }  UrlValidator Kiểm lỗi định dạng url public class Employee extends ActionSupport{ @UrlValidator(message = "Default message". maxLength = "12") public String getName() { return name. shortCircuit = true. bạn dễ dàn triển khai layout chung cho website của bạn.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.jsp Nguyễn Nghiệm . trim = true.CÔNG NGHỆ JAVA Kiểm lỗi độ dài chuỗi CHƯƠNG 5: STRUTS 2X FRAMEWORK public class Employee extends ActionSupport{ @StringLengthFieldValidator(message = "Default message". shortCircuit = true) public String getURL() { return url. minLength = "5". 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.key". key = "i18n. } } 5. key = "i18n.  Trang Home.key". Với Tiles framework.Nhất nghệ 388 .

CÔNG NGHỆ JAVA  Trang AboutUs.jsp Trong trang Layout.Nhất nghệ 389 .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ế Nguyễn Nghiệm .jsp.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.css: bố cục chung Home.jsp và Layout. AboutUs.: các trang thành viên LayoutAction..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..jsp CHƯƠNG 5: STRUTS 2X FRAMEWORK Để 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.

charset=utf8" pageEncoding="utf8"%> taglib uri="http://java.com/jstl/fmt_rt" prefix="fmt" %> taglib uri="/struts-tags" prefix="s" %> taglib uri="http://tiles. margin: 10px auto. } #wrapper{ width: 950px. Nguyễn Nghiệm .com/jstl/core_rt" prefix="c" %> taglib uri="http://java.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. } #header{ height: 200px.apache.Nhất nghệ 390 .org/tags-tiles" prefix="tiles" %> <!DOCTYPE HTML> <html> <head> <title>Layout demo</title> <link href="css/Layout. font-size: 12px.css body{ background: gray.CÔNG NGHỆ JAVA o <%@ <%@ <%@ <%@ <%@ CHƯƠNG 5: STRUTS 2X FRAMEWORK @ignore: cho phép bỏ qua (không cung cấp nội dung) hay không page contentType="text/html.sun.sun.

} #right{ border-left:1px dotted lightgray.com/jstl/fmt_rt" prefix="fmt" %> taglib uri="/struts-tags" prefix="s" %> taglib uri="http://tiles. min-height: 400px. <%@ <%@ <%@ <%@ <%@ page contentType="text/html. text-decoration: none.CÔNG NGHỆ JAVA background-color: yellow. bottom: 5px. clear: both.sun.com/jstl/core_rt" prefix="c" %> taglib uri="http://java. background-color: lightgray. } #main{ width: 650px. position: relative. } #header #menu li a{ font-variant: small-caps. charset=utf8" pageEncoding="utf8"%> taglib uri="http://java. left: 10px. background-color: aqua. float: left. } Bước 2: Home. background-color: white. width: 299px. } #header #menu li a:hover{ color:red. font-size: 13px. border-top: 1px dashed gray. } #header #menu ul{ list-style: 0px. } #footer{ height: 50px.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.apache. } CHƯƠNG 5: STRUTS 2X FRAMEWORK #header #menu{ width:98%. padding: 0px 5px. position: absolute.sun.org/tags-tiles" prefix="tiles" %> Nguyễn Nghiệm . margin: 0px. min-height: 400px. float: right. padding: 0px.Nhất nghệ 391 . margin: 0px 2px. } #header #menu li{ display: inline-block.

@Result(name="feedback". @Result(name="faqs". } @Action(value="/faqs") public String faqs(){ Nguyễn Nghiệm .struts2.annotation.annotation.opensymphony. package nnghiem.jsp"> <tiles:putAttribute name="head" value=""/> <tiles:putAttribute name="main"> <h1>Home Page</h1> </tiles:putAttribute> </tiles:insertTemplate> Bước 3: LayoutAction.Action. location="/ContactUs. location="/FAQs.jsp"). @Result(name="about".struts2.Result.apache.CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK <tiles:insertTemplate template="Layout.ActionSupport. } @Action(value="/contact") public String contact(){ return "contact".jsp"). Mục đích là struts2 hoàn toàn việc truy xuất các trang.Nhất nghệ 392 . location="/Feedback.annotation. } @Action(value="/about") public String about(){ return "about". @Results(value={ @Result(name="home". import org.convention. location="/Home.jsp"). }) public class LayoutAction extends ActionSupport { @Action(value="/home") public String home(){ return "home".jsp"). } @Action(value="/feedback") public String feedback(){ return "feedback".jsp").struts.apache. @Result(name="account". import org.convention. import com. location="/AboutUs.apache. @Result(name="contact".Results.action.jsp").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ể.xwork2.struts2. import org. location="/MyAccount.convention.

Sau đây là nội dung trang index. } } CHƯƠNG 5: STRUTS 2X FRAMEWORK Bước 4: Web.action.action" /> </head> <body></body> </html> Nguyễn Nghiệm .dispatcher.URL=home.5"> <display-name>Struts2Example15</display-name> <listener> <listener-class>org.CÔNG NGHỆ JAVA return "faqs".tiles.com/xml/ns/javaee http://java.w3.sun.sun.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.xml <?xml version="1.filter.sun.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.ng.sun.Nhất nghệ 393 .xsd" id="WebApp_ID" version="2.apache. Trang index.com/xml/ns/javaee/web-app_2_5.org/2001/XMLSchema-instance" xmlns="http://java.xsd" xsi:schemaLocation="http://java.struts2.StrutsTilesListener</listener-class> </listener> <filter> <filter-name>struts2</filter-name> <filter-class> org. } @Action(value="/account") public String account(){ return "account".struts2.StrutsPrepareAndExecuteFilter </filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>index.jsp sẽ tự chuyển sang home.jsp <!DOCTYPE HTML> <html> <head> <meta http-equiv="Refresh" content="0.jsp.apache.com/xml/ns/javaee/web-app_2_5.com/xml/ns/javaee" xmlns:web="http://java.

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ữ đó.9. Tiếng Việt đang được chọn Tiếng Anh đang được chọn Nguyễn Nghiệm . Sau đây là minh họa của website đa ngôn ngữ (tiếng Anh và tiếng Việt).1 Giới thiệu CHƯƠNG 5: STRUTS 2X FRAMEWORK Website đa ngôn ngữ là website có khả năng tùy biến ít nhất là 2 ngôn ngữ.9 Đa ngôn ngữ 5.Nhất nghệ 394 .CÔNG NGHỆ JAVA 5.

resources=GlobalResources Nội dung của tập tin tài nguyên toàn cục như sau: GlobalResources.xml hay struts.about=About Us layout. 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.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).home=Trang Chủ layout.feedback=Góp Ý layout.9.account=My Account layout.feedback=Feedback layout.faqs=FAQs layout.flag = us.about=Giới Thiệu layout.gif GlobalResources_vi.properties layout.CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK Để thực hiện được điều này. Dòng khai báo tài nguyên toàn cục sau đây được đặt trong struts.account=Tài Khoản layout.properties. 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.contact=Liên Hệ layout.custom.gif Nguyễn Nghiệm .i18n.home=Home Page layout.properties layout.Nhất nghệ 395 . LocalResources GlobalResources LocalResources 5.contact=Contact Us layout.flag = vi.faqs=Hỏi-Đáp layout. 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.properties struts.

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. Nó buộc phải có tên giống với tên lớp action.name" size="20" /> <s:textfield name="salary" key="home.properties + CustomerAction_vi.home"/> để lấy giá trị của văn bản có key là layout.properties + GlobalResources_vi.properties).birthday" size="20" /> <s:submit name="submit" key="home.Nhất nghệ 396 .home"/></h1> <s:form action="locale"> <s:textfield name="name" key="home.salary" size="20" /> <s:textfield name="birthday" key="home. String[] args).home. <s:textfield name="name" key="home.name" />. Trong JSP bạn sử dụng thẻ <s:text name="layout. 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.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.properties + LayoutAction_vi. 5.properties và LayoutAction.CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK 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 đó. 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. Sau đây là một ví dụ: <h1><s:text name="layout.submit" /> Nguyễn Nghiệm . Bên cạnh đó website cũng có tài nguyên toàn cục là GlobalResources.properties đặt tại thư mục góc của mã nguồn.

9. @Result(name="faqs". location="/Feedback.Action.Results.properties và CustomerAction_vi.apache. 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.jsp là khung mẫu cho các trang thành viên  Home.java package nnghiem. location="/FAQs.properties và LayoutAction_vi. import org. Website được tổ chức các liên kết điều khiển đăt tại Layout.jsp") }) public class LayoutAction extends ActionSupport{ @Action(value="/home") public String home(){ Nguyễn Nghiệm .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. location="/AboutUs.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). <a href="?request_locale=en">English</a> <a href="?request_locale=vi">Tiếng Việt</a> 5. @Result(name="about".jsp và MyAccount.jsp").java.Nhất nghệ 397 .properties  Các tài nguyên toàn cục: GlobalResources.apache.opensymphony.CÔNG NGHỆ JAVA </s:form> CHƯƠNG 5: STRUTS 2X FRAMEWORK 5. location="/Home.struts.jsp").convention. @Result(name="contact". @Results(value={ @Result(name="home". CustomerAction. location="/ContactUs.struts2. bạn chỉ cần truyền tham số request_locale=<mã ngôn ngữ> cho bất kỳ action nào.properties o CustomerAction.convention.jsp"). LayoutAction.annotation.9.convention.Result.jsp là các trang thành viên  Web. Các thành phần trong website:  Các lớp action và tài nguyên cục bộ: o LayoutAction. import com.java.apache.annotation.ActionSupport. @Result(name="feedback".properties  Tập tin khai báo tài nguyên: struts.struts2.annotation. import org.struts2.jsp").properties  Layout.xwork2. import org.4 Lựa chọn ngôn ngữ Để lựa chọn ngôn ngữ hiển thị.

convention. } } CHƯƠNG 5: STRUTS 2X FRAMEWORK  LayoutAction.annotation.properties home.properties home.birthday = Birthday home.submit = Submit  LayoutAction_vi.Result.submit = \u0110\u1ED3ng ý  CustomerAction. location="/MyAccount.annotation.birthday = Ngày sinh home.apache. } @Action(value="/contact") public String contact(){ return "contact".struts. } @Action(value="/feedback") public String feedback(){ return "feedback".name = H\u1ECD và tên home. } @Action(value="/about") public String about(){ return "about".convention.salary = Salary home.ActionSupport.struts2. @Result(name="success". import org.name = Name home.CÔNG NGHỆ JAVA return "home". } @Action(value="/faqs") public String faqs(){ return "faqs".struts2.opensymphony.java package nnghiem. import com.jsp") public class CustomerAction extends ActionSupport{ @Action(value="/account") public String execute() throws Exception { return "success".apache.xwork2.salary = L\u01B0\u01A1ng home. } } Nguyễn Nghiệm .Action. import org.Nhất nghệ 398 .

sun.password=M\u1EADt Kh\u1EA9u  GlobalResources.custom.contact=Contact Us layout.CÔNG NGHỆ JAVA  CustomerAction.properties account.userId=Login Name account.properties struts.password=Password CHƯƠNG 5: STRUTS 2X FRAMEWORK  CustomerAction_vi.properties layout.home"/></a></li> <li><a href="about"><s:text name="layout. charset=utf8" pageEncoding="utf8"%> taglib uri="http://java.userId=Mã \u0110\u0103ng Nh\u1EADp account.org/tags-tiles" prefix="tiles" %> <!DOCTYPE HTML> <html> <head> <title>Layout demo</title> <link href="css/Layout.com/jstl/core_rt" prefix="c" %> taglib uri="http://java.flag"/>"/> <div id="menu"> <ul style="float:left"> <li><a href="home"><s:text name="layout.resources=GlobalResources  Layout.apache.home=Home Page layout.i18n.sun.about=About Us layout.account=My Account layout.about"/></a></li> <li><a href="contact"><s:text name="layout.faqs"/></a></li> <li><a href="account"><s:text name="layout.com/jstl/fmt_rt" prefix="fmt" %> taglib uri="/struts-tags" prefix="s" %> taglib uri="http://tiles.feedback"/></a></li> <li><a href="faqs"><s:text name="layout.contact"/></a></li> <li><a href="feedback"><s:text name="layout.feedback=Feedback layout.gif  struts.Nhất nghệ 399 .faqs=FAQs layout.jsp <%@ <%@ <%@ <%@ <%@ page contentType="text/html.flag = us.properties account.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.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> Nguyễn Nghiệm .

userId"/></li> <li><s:text name="account.password"/></li> Nguyễn Nghiệm .name" size="20" /> <s:textfield name="salary" key="home.apache. charset=utf8" pageEncoding="utf8"%> taglib uri="http://java.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.com/jstl/fmt_rt" prefix="fmt" %> taglib uri="/struts-tags" prefix="s" %> taglib uri="http://tiles.birthday" size="20" /> <s:submit name="submit" key="home.sun.org/tags-tiles" prefix="tiles" %> <tiles:insertTemplate template="Layout.account"/></h1> <ul> <li><s:text name="account.com/jstl/core_rt" prefix="c" %> taglib uri="http://java.com/jstl/fmt_rt" prefix="fmt" %> taglib uri="/struts-tags" prefix="s" %> taglib uri="http://tiles.jsp <%@ <%@ <%@ <%@ <%@ page contentType="text/html.com/jstl/core_rt" prefix="c" %> taglib uri="http://java.jsp <%@ <%@ <%@ <%@ <%@ page contentType="text/html.jsp"> <tiles:putAttribute name="head" value=""/> <tiles:putAttribute name="main"> <h1><s:text name="layout.salary" size="20" /> <s:textfield name="birthday" key="home.Nhất nghệ 400 .apache.sun.org/tags-tiles" prefix="tiles" %> <tiles:insertTemplate template="Layout. charset=utf8" pageEncoding="utf8"%> taglib uri="http://java.sun.submit" /> </s:form> </tiles:putAttribute> </tiles:insertTemplate>  MyAccount.CÔNG NGHỆ JAVA </ul> </div> </div> <div id="main"> <tiles:insertAttribute name="main"/> </div> <div id="right">RIGHT</div> <div id="footer">FOOTER</div> </div> </body> </html> CHƯƠNG 5: STRUTS 2X FRAMEWORK  Home.sun.

sun.struts2.struts2. Hibernate</display-name> <listener> <listener-class>org.Result.apache.sun.CÔNG NGHỆ JAVA </ul> </tiles:putAttribute> </tiles:insertTemplate> CHƯƠNG 5: STRUTS 2X FRAMEWORK  Web. import org.http.servlet.jsp</welcome-file> </welcome-file-list> </web-app> 5.dispatcher.apache.apache.struts.xsd" xsi:schemaLocation="http://java. import org.opensymphony.annotation.com/xml/ns/javaee http://java.apache. HttpSession hay ServletContext một cách dễ dàng theo 2 cách sau: Cách 1: sử dụng ServletActionContext package nnghiem.com/xml/ns/javaee/web-app_2_5. import import import import javax.FilterDispatcher</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>index.ServletContext. import com. javax.w3.com/xml/ns/javaee/web-app_3_0.ActionSupport.StrutsTilesListener</listener-class> </listener> <filter> <filter-name>struts2</filter-name> <filter-class>org.struts2.sun.convention.HttpServletRequest.servlet. import org.ServletActionContext.xml có cấu hình struts và tiles <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.struts2.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.http.org/2001/XMLSchema-instance" xmlns="http://java.0"> <display-name>Struts &amp. HttpServletResponse.convention.tiles.xsd" id="WebApp_ID" version="3.HttpSession.sun.struts2.com/xml/ns/javaee" xmlns:web="http://java. javax.xwork2. Nguyễn Nghiệm .apache.Nhất nghệ 401 .servlet.Action. javax.servlet.annotation.HttpServletResponse.http.

struts2.struts2.apache.HttpServletRequest.util. import javax.apache.struts2. HttpServletResponse resp = ServletActionContext.apache.getServletContext().getSession().annotation.Nhất nghệ 402 . location="/Success.http. ServletRequestAware. SessionAware.jsp") public class MyAction extends ActionSupport implements ServletRequestAware. ServletResponseAware.interceptor.ServletResponseAware. ServletContextAware{ @Action(value="/myAction") public String execute() throws Exception { return "success".servlet. org.apache.apache.Map.xwork2. org.SessionAware.jsp") public class MyAction extends ActionSupport{ @Action(value="/myAction") public String execute() throws Exception { HttpServletRequest req = ServletActionContext.opensymphony.struts. org. return "success".ServletContextAware.interceptor.ServletRequestAware.http.apache. org.servlet.servlet. location="/Success. import com.convention.Action. import javax.ActionSupport. org.getResponse(). ServletResponseAware.struts2.convention.struts2.ServletContext. } } Cách 2: thi hành theo các interface HttpSessionAware. } @Override public void setServletContext(ServletContext servletContext) { } @Override public void setSession(Map<String. import java.interceptor. @Result(name="success".annotation.getRequest(). Object> session) { } @Override public void setServletResponse(HttpServletResponse response) { } Nguyễn Nghiệm . ServletContextAware package nnghiem.HttpServletResponse. ServletContext application = ServletActionContext.struts2.Result. import javax. HttpSession session = req.CÔNG NGHỆ JAVA CHƯƠNG 5: STRUTS 2X FRAMEWORK @Result(name="success".util. import import import import import import org.

Nhất nghệ 403 .CÔNG NGHỆ JAVA } CHƯƠNG 5: STRUTS 2X FRAMEWORK @Override public void setServletRequest(HttpServletRequest request) { } Nguyễn Nghiệm .