Các mục tiêu Trong hướng dẫn này sẽ: tiếp tục nhìn tổng quan về các tính năng của JSF và học cách làm việc với tất cả các thành phần JSF; xây dựng một ứng dụng đơn giản quản lý các mối g
Trang 1Khởi đầu với JavaServer Faces 1.2, Phần 2: Vòng đời, phép chuyển đổi, duyệt
tính hợp lệ, và trình nghe pha của JSF
Richard Hightower, CTO, ArcMind
Tóm tắt: Loạt bài hướng dẫn bao gồm cách làm thế nào để bắt đầu khởi động
công nghệ Java™ Server Faces (JSF), một khung công tác phía máy chủ, cung cấp một cách tiếp cận dựa vào thành phần để phát triển giao diện người dùng web Phần 1 dẫn bạn bắt đầu với một tổng quan JSF 1.2 và một ứng dụng cơ bản Phần tiếp theo này sẽ làm cho bạn nắm vững các tính năng cao cấp hơn của JSF: các trình duyệt tính hợp lệ, các trình chuyển đổi và trình nghe pha tùy biến theo yêu cầu Cùng với hướng dẫn này bạn sẽ hiểu rõ về vòng đời của ứng dụng JSF
Trước khi bạn bắt đầu
Về loạt bài này
Giới thiệu mở đầu về công nghệ Java™ Server Faces (JSF), một khung công tác thành phần giao diện người dùng phía máy chủ cho các ứng dụng web dựa trên Java Loạt bài này dành cho các nhà phát triển, những người mới bắt đầu tìm hiểu JSF và muốn tiến nhanh — không chỉ với JSF, mà với cả việc sử dụng các thành phần JSF để giảm công sức Loạt bài này trình bày chỉ những điều cốt yếu, với rất nhiều ví dụ
JSF là một môi trường phát triển GUI khá truyền thống, giống như AWT, SWT,
và Swing Một trong những lợi ích chính của nó là nó làm cho việc phát triển Web
dễ dàng hơn bằng cách giao những công việc khó khăn cho các nhà phát triển khung công tác, chứ không phải cho các nhà phát triển ứng dụng Cứ cho là bản thân JSF phức tạp hơn nhiều so với các khung công tác Web khác, nhưng sự phức tạp này được che giấu không để cho các nhà phát triển ứng dụng biết Phát triển các ứng dụng Web trong JSF dễ dàng hơn nhiều so với hầu hết các khung công tác khác: nó đòi hỏi viết mã ít hơn, ít phức tạp hơn, và ít việc cấu hình hơn
Nếu bạn đang thực hiện phát triển Java phía máy chủ, JSF là khung công tác dễ nhất để tìm hiểu Nó được định hướng để tạo các ứng dụng Web (không chỉ là các trang web) Nó cho phép bạn tập trung vào việc mã hóa Java của bạn mà không cần đối phó với các đối tượng yêu cầu, các đối tượng phiên, các thông số yêu cầu, hoặc đối phó với các tệp tin XML phức tạp Với JSF, nhiều thứ thực hiện nhanh hơn so với các khung công tác Web Java khác
Trang 2
Về hướng dẫn này
Về hướng dẫn này Phần 1 đã để lại Nếu bạn là người mới bắt đầu với JSF, hoặc chỉ muốn ôn lại, thì hãy đọc bài đã đăng đầu tiên trước khi bạn bắt đầu phần này Thậm chí nếu bạn là một người chuyên nghiệp về JSF già dặn, có một hay hai khả năng được đánh giá cao thì điều đó cũng sẽ giúp bạn
Mặc dù hỗ trợ công cụ là một lợi ích chính của JSF, bạn sẽ không sử dụng các công cụ ưa thích hay sự hỗ trợ của IDE trong hướng dẫn này Hướng dẫn này đề cập những điểm cốt yếu, với thông tin nền tảng để tiếp tục trình bày và để giữ cho bạn cách học tập có hiệu quả việc sử dụng JSF để xây dựng các ứng dụng Web
Các mục tiêu
Trong hướng dẫn này sẽ: tiếp tục nhìn tổng quan về các tính năng của JSF và học cách làm việc với tất cả các thành phần JSF; xây dựng một ứng dụng đơn giản quản lý các mối giao tiếp — một danh sách liệt kê CRUD cơ bản (tạo, đọc, cập nhật, xóa); sau khi tìm hiểu về vòng đời của ứng dụng JSF, cải tiến ứng dụng này với các trình chuyển đổi (converter) và các trình duyệt tính hợp lệ (validator) Hướng dẫn này uốn khúc với một chút hương vị về lập trình JSF cao cấp: tạo một khung công tác duyệt tính hợp lệ mức đối tượng bằng cách sử dụng một trình nghe pha
Ai nên tìm hiểu hướng dẫn này?
Nếu bạn là người mới bắt đầu tìm hiểu JSF, hướng dẫn này để dành cho bạn Ngay
cả khi bạn đã sử dụng JSF nhưng chưa thử nghiệm các tính năng JSF 1.2 hoặc chỉ
sử dụng các công cụ GUI để xây dựng các ứng dụng JSF, bạn sẽ có khả năng học hỏi được rất nhiều từ cả hai hướng dẫn trong loạt bài này
Trang 3
Các yêu cầu tiên quyết
Hướng dẫn này được viết cho các nhà phát triển Java có kinh nghiệm ở mức bắt đầu tới mức trung cấp Bạn cần phải có hiểu biết chung về cách sử dụng ngôn ngữ Java, cùng với một số kinh nghiệm phát triển giao diện đồ họa người dùng (GUI)
Trang 4Ứng dụng CRUD JSF mẫu
Phần này giới thiệu một ứng dụng CRUD đơn giản mà bạn sẽ xây dựng trong các phần tiếp sau để tìm hiểu về:
Từng thành phần HTML tiêu chuẩn của JSF
Tạo các trình biến đổi tùy biến
Làm việc với các trình duyệt tính hợp lệ
Làm việc với các trình nghe pha
Một ứng dụng quản lý các mối giao tiếp
Ứng dụng mà bạn sẽ xây dựng trong phần này là một ứng dụng quản lý giao tiếp
có cấu trúc giống như ứng dụng máy tính bỏ túi trong Phần 1 Như bạn có thể thấy trong Hình 1, ứng dụng này là một danh sách CRUD tiêu chuẩn Nó không yêu cầu các quy tắc dẫn hướng do toàn bộ ứng dụng sử dụng chỉ một khung nhìn đơn (trang contacts.jsp)
Hình 1 Ứng dụng mẫu quản lý các mối giao tiếp
Hình 2 Cho thấy lưu đồ cơ sở của ứng dụng:
Trang 5Hình 2 Ứng dụng mẫu quản lý các mối giao tiếp, sơ đồ liên kết
Ứng dụng CRUD này bao gồm các phần tử sau đây:
ContactController: Trình điều khiển JSF
Contact: Đối tượng mô hình để mô tả thông tin về các mối giao tiếp
ContactRepository: Đối tượng mô hình để tạo, đọc, cập nhật, và xóa các đối tượng Contact
contacts.jsp: Trang JavaServer Pages (JSP) để bố trí cây thành phần JSF quản lý các giao tiếp
faces-config.xml: Cấu hình JSF, nơi bạn khai báo ContactController và ContactRepository như là các bean quản lý và nội xạ ContactRepository và ContactController
Trang 6
Trình điều kiển giao tiếp (ContactController)
ContactController hậu thuẫn trang contacts.jsp Listing 1 hiển thị mã cho ContactController:
public class ContactController {
/** Contact Controller collaborates with contactRepository */
private ContactRepository contactRepository;
Trang 7/** The current contact that is being edited */
private Contact contact = new Contact();
/** Contact to remove */
private Contact selectedContact;
/** The current form */
private UIForm form;
/** Add new link */
private UICommand addNewCommand;
/** Persist command */
private UICommand persistCommand;
/** For injection of collaborator */
public void setContactRepository(ContactRepository contactRepository) { this.contactRepository = contactRepository;
}
public void addNew() {
form.setRendered(true);
Trang 8public void read() {
contact = selectedContact;
form.setRendered(true);
Trang 9 biểu mẫu (form) được bật lên để người sử dụng có thể nhập vào một giao tiếp mới — form.setRendered(true)
addNewCommand được tắt đi — addNewCommand.setRendered(false)
nhãn của persistCommand được đặt là Add —
persistCommand.setValue("Add")
Trang 10Phương thức persist() vừa xử lý cập nhật mối giao tiếp hiện có và vừa xử lý bổ sung thêm mối giao tiếp mới bằng cách sử dụng contactRepository Phương thức persist() tắt form bật addNewCommand Phương thức remove() loại bỏ mối giao tiếp ra khỏi hệ thống bằng cách sử dụng contactRepository
Phương thức read() sao chép selectedContact (có kiểu là Contact) vào một mối giao tiếp (Mối giao tiếp — cũng có kiểu là Contact — có giá trị liên kết với biểu mẫu) Bạn có thể tự hỏi selectedContact bắt nguồn từ đâu Nó được chọn khi người dùng nhấn vào một mối giao tiếp trong danh sách các mối giao tiếp (Hướng dẫn này sẽ đề cập khi thảo luận về JSP.) Như trong Phần 1, addStatusMessage bổ sung thêm các thông báo trạng thái để bạn có thể hiển thị chúng với
<h:messages>
Khung nhìn các mối giao tiếp
Trang JSP sử dụng một <h:dataTable> (một thành phần không được giới thiệu trong Phần 1), như hiển thị trong Listing 2:
Listing 2 contacts.jsp
<?xml version="1.0" encoding="ISO-8859-1" ?>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
Trang 11<h:form binding="#{contactController.form}" rendered="false"
styleClass="form">
Trang 12<h:message for="firstName" errorClass="errorClass" />
Trang 13rendered="#{not empty contactController.contacts}"
Trang 14</h:commandLink>
<h:commandLink value="edit" action="#{contactController.read}"> <f:setPropertyActionListener
target="#{contactController.selectedContact}" value="#{contact}" /> </h:commandLink>
<h:dataTable> là giá trị được liên kết để hiển thị các mối giao tiếp từ
contactController, khi sử dụng "#{contactController.contacts}" Mỗi mối giao tiếp được ánh xạ vào bảng bằng cách sử dụng thuộc tính: var="contact" Trong
contacts.jsp, các kiểu dáng (style) oddRow và evenRow (được định nghĩa trong một tệp tin CSS) được đặt vào trong thuộc tính rowClasses với
rowClasses="oddRow, evenRow" Điều này cho phép <h:dataTable> sử dụng các kiểu dáng luân phiên cho các hàng trong bảng Hãy kiểm tra tài liệu hướng dẫn trực tuyến <h:dataTable> để tìm một danh sách đầy đủ về những cái có thể làm với <h:dataTable> và các kiểu dáng, bởi vì <h:dataTable> có khá nhiều khả năng (Xem Tài nguyên để tìm liên kết đến JSF API Javadocs)
Trang 15Bạn cũng có thể thiết lập một kiểu dáng cho toàn bộ <h:dataTable>
vớistyleClass="contactTable" hoặc cho vùng tiêu đề của nó với
headerClass="headerTable" Hoặc bạn có thể thực hiện các kiểu dáng luân phiên tương tự như thế cho các cột bằng cách sử dụng thuộc tính columnClasses:
columnClasses="normal,centered" <h:dataTable> được thiết lập để nó không hoàn trả nếu không có mối giao tiếp: rendered="#{not empty
contactController.contacts}"nào Thành phần <h:dataTable> rất linh hoạt và dễ sử dụng
Bên trong <h:dataTable>, bạn sử dụng các <h:column> để hiển thị các giá trị theo các thuộc tính Mỗi cột định nghĩa một phần tiêu đề trong một thẻ <f:facet> Một facet là một thành phần tên mà các thành phần khác sử dụng Vậy thì sau <f:facet>
và bên trong thành phần <h:column> bạn hãy sử dụng thành phần <h:outputText>
để đưa ra các thuộc tính firstName và lastName
Mỗi hàng có một liên kết loại bỏ và một liên kết chỉnh sửa, mỗi liên kết sử dụng một <h:commandLink> commandLink loại bỏ được liên kết với phương thức contactController.remove Liên kết chỉnh sửa được liên kết với phương thức
contactController.read Thuộc tính contactController.selectedContact được điền bằng hàng hiện tại theo cách bạn cấu hình <f:setPropertyActionListener>
<f:setPropertyActionListener> làm cho mối giao tiếp của hàng hiện tại được sao chép vào selectedContact trước khi phương thức hành động được gọi
Tệp faces-config.xml cho ứng dụng CRUD của các mối giao tiếp
Tệp tin faces-config.xml nối ContactRepository vào trong ContactController, như hiển thị trong Listing 3:
Listing 3 faces-config.xml
<managed-bean>
<managed-bean-name>contactRepository</managed-bean-name>
Trang 17cộng tác vào trong trình điều khiển để hỗ trợ việc duy trì mô hình và khung nhìn riêng biệt, và nó cho phép bạn nội xạ các đối tượng giả để sau này có thể được thay thế bằng các đối tượng thực Nhiều hơn một lần, tôi đã làm giả một đối tượng
mô hình như ContactRepository và sau đó thay thế nó bằng phiên bản thực sau khi hoàn thành GUI
Mô hình của ứng dụng là khá đơn giản, như hiển thị trong các Listings 4 và 5 Listing 4 hiển thị lớp Contact:
Listing 4 Contact
package com.arcmind.contact.model;
public class Contact { private String firstName;
private String lastName; protected long id;
public Contact(String firstName, String lastName) {
this.firstName = firstName; this.lastName =
lastName; }
public Contact() { }
public String getFirstName() { return firstName; }
public void setFirstName(String firstName) {
Trang 18this.firstName = firstName; }
public String getLastName() { return lastName; }
public void setLastName(String lastName) {
this.lastName = lastName; }
@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + (int) (id ^ (id >>> 32)); return result; }
@Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return
false; final Contact other = (Contact) obj; if (id
!= other.id) return false; return true; }
@Override public String toString() { return
String.format("Contact: %s %s", firstName,
lastName); }
public long getId() { return id; }
Trang 19public void setId(long id) { this.id = id; }
public class ContactRepository {
private Map<Long, Contact> contacts = new LinkedHashMap<Long,
Contact>();
private static long counter = 1l;
Trang 20public List<Contact> getContacts() {
return new ArrayList<Contact>(contacts.values());
Trang 21Hình 3 cho thấy các thành phần này xuất hiện trong GUI như thế nào:
Hình 3 Quản lý các mối giao tiếp với một số lượng lớn các thành phần JSF phổ biến
Các khung nhìn phụ
Trang 22Như bạn có thể hình dung, thật khó để bao gồm tất cả các thành phần JSF của bạn trên một trang web May mắn thay, bạn có thể phân chia các thành phần JSF theo các khung nhìn riêng biệt bằng cách sử dụng một <f:subview>, như hiển thị trong Listing 6:
Listing 6 Các khung nhìn phụ contacts.jsp
Trang 23<f:subview>, do đó bạn có thể cần sử dụng chúng ngay cả khi bạn đang sử dụng JSF 1.2 hoặc phiên bản mới hơn
Ứng dụng quản lý các mối giao tiếp (phiên bản thứ 2) sử dụng
<h:selectOneMenu> Để điều này hoạt động, bạn bổ sung thêm ba đối tượng mô hình mới: Group (chỉ ra trong Listing 7), Thẻ (Tag), và ContactType Bạn cũng thêm hai đối tượng kho lưu trữ mới: GroupRepository và TagRepository, tương tự như ContactRepository ContactType không cần có một kho lưu trữ bởi vì nó là một Bảng kê (Enum) Lớp Contact hiện nay có ba thuộc tính mới dành cho nhóm
có nó ở trong đó (được gọi là group), dành cho các thẻ có kết hợp với nó (tags), và cuối cùng là dành cho kiểu của nó type
Listing 7 Các khung nhìn phụ contacts.jsp/form.jsp
Trang 24
<% Group %>
<h:outputLabel value="Group" for="group" accesskey="g" />
<h:selectOneMenu id="group" validatorMessage="required"
value="#{contactController.selectedGroupId}">
<f:selectItems value="#{contactController.groups}" />
<f:validateLongRange minimum="1" />
</h:selectOneMenu>
<h:message for="group" errorClass="errorClass" />
Lưu ý rằng selectOneMenu sử dụng thuộc tính giá trị để liên kết selectOneMenu với selectedGroupId Phần thân của selectOneMenu chứa một <f:selectItems>, đó
là giá trị liên kết với thuộc tính các nhóm: value=#{contactController.groups} Bạn tạo ra một danh sách các nhóm trong bean phía sau Mã cho thuộc tính
selectedGroupId và thuộc tính các nhóm có trong Listing 8:
Listing 8 Xây dựng một danh sách của các nhóm
Trang 25
public List<SelectItem> getGroups() {
List<Group> groups = groupRepository.list();
List<SelectItem> list = new ArrayList<SelectItem>(groups.size()+1);
list.add(new SelectItem(Long.valueOf(-1L), "select one"));
for (Group group : groups) {
SelectItem selectItem = new SelectItem(group.getId(), group.getName()); list.add(selectItem);
Thuộc tính các nhóm (groups) trả về một danh sách các SelectItem Lớp
SelectItem được sử dụng để biểu diễn một mục trong một danh sách Nó được cả hai thành phần UISelectMany và UISelectOne sử dụng Lưu ý rằng phương thức getGroups sử dụng groupRepository, đây là một đối tượng kho lưu trữ, được nội
xạ như contactRepository để nhận một danh sách các nhóm The groupRepository quản lý các đối tượng Group Một Group đại diện cho một nhóm Một Contact đại diện một mối giao tiếp Phương thức getGroups() tạo ra một danh sách các
SelectItem bằng cách sử dụng thuộc tính group.id như là một giá trị và thuộc tính group.name như là một nhãn
Lưu ý rằng bạn thêm một SelectItem "chọn một" với giá trị là -1 Bạn sử dụng giá trị này để xác định một mục có được lựa chọn không Nếu nó không được lựa chọn, bạn chọn mục chưa được chọn bằng cách sử dụng <f:validateLongRange minimum="1" /> ở trong selectOneMenu (xem lại Listing 7) Cũng cần chú ý rằng
Trang 26selectOneMenu sử dụng validatorMessage="required" để hiển thị một thông báo lỗi ngắn
Chú ý rằng Listing 8 gọi trực tiếp kho lưu trữ Nếu kho lưu trữ đã thực sự đang trao đổi với một cơ sở dữ liệu hoặc bộ nhớ cache, bạn muốn thực hiện lời gọi đến phương thức hành động để thực hiện xử lý lỗi ở đó và phơi bày ra các kết quả như các mục đã chọn trong thuộc tính
Khi biểu mẫu (form) được gửi đi selectedGroupId được thiết lập Phương thức persist() được liên kết với nút cập nhật và nút tạo ra, sẽ sử dụng selectedGroupId
để tìm kiếm nhóm trong kho lưu trữ, như hiển thị trong Listing 9:
Listing 9 Cập nhật persist() để sử dụng selectedGroupId
public class ContactController {
public void persist() {
/* Setup the group into contact */
Trang 27public void read() {
/* Prepare selected contact */
Trang 28Mã Java tương tự như Listing 8, ngoại trừ bây giờ bạn đang làm việc với một mảng các ID được chọn các (số nguyên dài), thay cho một số nguyên dài, như hiển thị trong Listing 11:
Listing 11 Mã Java để hậu thuẫn selectManyCheckbox
Trang 29
public class ContactController {
private Long[] selectedTagIds;
private TagRepository tagRepository;
public List<SelectItem> getAvailableTags() {
List<Tag> tags = tagRepository.list();
List<SelectItem> list = new ArrayList<SelectItem>(tags.size()); for (Tag tag : tags) {
SelectItem selectItem = new SelectItem(tag.getId(), tag.getName()); list.add(selectItem);
/* Setup the tags into contact */
List<Tag> tags = new ArrayList<Tag>(selectedTagIds.length);
Trang 30for (Long selectedTagId : selectedTagIds) {
/* Prepare selected tag IDs */
List<Tag> tags = contact.getTags();
List<Long> tagIds = new ArrayList<Long>(tags.size());
for (Tag tag : tags) {
Trang 31contact.tags bằng với các giá trị đã tìm thấy Phương thức read() khởi tạo các selectedTagId dựa trên cơ sở các Thẻ (Tags) có trong thuộc tính contact.tags
Lớp UISelectMany hậu thuẫn <h:selectManyCheckbox>, nhưng nó cũng hậu thuẫn <h:selectManyListbox> và <h:selectManyMenu> Bạn có thể sử dụng
chúng thay cho <h:selectManyCheckbox>, như hiển thị trong Listings 12 và 13, và Hình 4
Trang 32Hình 4: <selectManyListbox> và <selectManyMenu>
Lưu ý rằng thiết lập cho tất cả ba thẻ là như nhau
JSF 1.2 có các trình biến đổi cho các Enum, do đó, bạn không cần phải tìm kiếm các giá trị Bạn có thể sử dụng chúng trực tiếp và liên kết với chúng mà không cần
có một thuộc tính trung gian trong trình điều khiển giống như bạn đã dành cho các thẻ và nhóm (xem Listing 8 và Listing 11) Lớp Contact có một thuộc tính enum, như hiển thị trong Listing 14:
Listing 14 Contact sử dụng enum cho thuộc tính kiểu (type)
Trang 33public class Contact implements Serializable {
private Group group;
private List<Tag> tags;
Trang 34<h:selectOneRadio id="type" value="#{contactController.contact.type}">
<f:selectItem itemValue="PERSONAL" itemLabel="personal" />
<f:selectItem itemValue="BUSINESS" itemLabel="business" />
</h:selectOneRadio>
Listing 15 cũng giải thích việc sử dụng <f:selectItem>, nó tạo ra các giá trị đơn Trình biến đổi kèm sẵn của JSF cho các Enum chờ đợi đầu vào là các giá trị chuỗi
ký tự — thực sự đó là các tên trong các Enum Bạn cũng có thể sử dụng một
<h:selectOneListbox>, như hiển thị trong Listing 16:
Listing 16 Sử dụng <h:selectOneListbox>
<h:selectOneListbox id="type" value="#{contactController.contact.type}">
<f:selectItem itemValue="PERSONAL" itemLabel="personal"/>
<f:selectItem itemValue="BUSINESS" itemLabel="business"/>
</h:selectOneListbox>
Các thành phần khác của ứng dụng quản lý các mối giao tiếp
Ứng dụng CRUD quản lý các mối giao tiếp cũng giải thích việc sử dụng
<h:selectBooleanCheckbox> và <h:inputTextarea>, như hiển thị trong Listing 17:
Listing 17 Sử dụng <h:selectBooleanCheckbox> and <h:textArea>
Trang 35<h:outputLabel value="Description" for="description"
accesskey="d" style="font: large;" />
<h:inputTextarea id="description" cols="80" rows="5"
value="#{contactController.contact.description}" />
<h:message for="description" errorClass="errorClass" />
<h:inputTextarea> có hai thuộc tính bổ sung được đặt với cols="80" rows="5" Các liên kết hoạt động như trước
Listing 18 cho thấy các thuộc tính mà bạn liên kết tới trong Listing 17:
Listing 18 Lớp Contact
Trang 36
public class Contact implements Serializable {
private String description;
private boolean active;
protected long id;
Trang 37có ("trình biến đổi dữ liệu JSF") Trong một phần sau của hướng dẫn này ("Các trình biến đổi dữ liệu JSF"- JSF data converters), bạn sẽ tìm hiểu về các trình biến đổi và tạo ra một số cái cho ứng dụng này Giữa bây giờ và sau này, hãy tham gia một hành trình ngắn bên lề đi vào vòng đời của ứng dụng JSF
Vòng đời của ứng dụng JSF
Bạn có thể (trái với suy nghĩ chung) viết các ứng dụng JSF mà không hiểu biết mọi chi tiết nhỏ về cách thức hoạt động của công nghệ này; bạn có thể học được rất nhiều chỉ bằng cách tự mình kiếm một dự án và ráp nối lại thông qua nó Tuy nhiên, sự hiểu biết các nguyên tắc cơ bản nhất định sẽ làm cho các nỗ lực phát triển của bạn được đền đáp nhiều hơn — và tiêu tốn ít thời gian hơn Phần này vòng ra ngoài, cách xa khỏi ứng dụng quản lý các mối giao tiếp và đưa bạn dạo qua sáu pha trong vòng đời yêu cầu – xử lý của JSF Hãy xem xét những gì xảy ra trong mỗi pha và các pha liên kết với nhau như thế nào Cuộc thảo luận này sẽ thông báo công việc bạn sẽ làm trong phần còn lại của hướng dẫn này
Trang 38Các pha của vòng đời của ứng dụng JSF
Sáu pha trong vòng đời của ứng dụng JSF là:
Bạn cũng có thể chọn bỏ hẳn JSF và khi đó có lẽ giao việc cho servlet hay một khung công tác ứng dụng khác Trong trường hợp này, bạn có thể phát ra một lời gọi phương thức FacesContext.responseComplete để chuyển hướng người dùng đến một trang Web hoặc nguồn tài nguyên Web khác, sau đó sử dụng bộ điều vận (dispatcher) yêu cầu (lấy ra từ đối tượng yêu cầu trong FacesContext) để chuyển tiếp đến một nguồn tài nguyên Web thích hợp Ngoài ra, bạn cũng có thể gọi FacesContext.renderResponse để hoàn trả lại khung nhìn gốc
Vấn đề là cho phép vòng đời ứng dụng cấu trúc các nỗ lực phát triển của bạn nhưng không cảm thấy hoàn toàn bị buộc vào nó Bạn có thể thay đổi vòng đời mặc định khi cần mà không lo sợ làm đổ vỡ ứng dụng của bạn Trong hầu hết trường hợp, bạn sẽ nhận thấy rằng vòng đời JSF đáng được tuân theo vì nó khá logic
Các biểu mẫu phải được duyệt tính hợp lệ trước khi có thể thực hiện bất kỳ logic ứng dụng nào, và dữ liệu của trường phải được biến đổi trước khi duyệt tính hợp
lệ Việc bám sát vòng đời giải phóng cho bạn, để tập trung suy nghĩ về các chi tiết trong duyệt tính hợp lệ và biến đổi, hơn là nghĩ về chính các pha của quá trình xử
Trang 39lý yêu cầu Cũng rất quan trọng khi lưu ý rằng các khung công tác Web khác cũng
có vòng đời tương tự; chỉ có điều không được quảng cáo hay giải thích tốt
Một số nhà phát triển khi sử dụng JSF có thể chẳng bao giờ viết một thành phần hoặc mở rộng một khung công tác trong khi những người khác chỉ tập trung vào các nhiệm vụ đó Mặc dù vòng đời của JSF sẽ giống nhau với hầu hết các dự án, bạn sẽ có khả năng đề cập đến nó ở các giai đoạn khác nhau dựa trên vai trò của bạn trong dự án Nếu bạn đang tập trung nhiều hơn về phát triển ứng dụng tổng thể, có nhiều khả năng bạn sẽ quan tâm đến các pha giữa của chu kỳ xử lý yêu cầu:
Áp dụng các giá trị yêu cầu
Trang 40Hình 5 Vòng đời của ứng dụng JSF
Pha 1: Khôi phục khung nhìn
Trong pha đầu của vòng đời JSF — khôi phục khung nhìn — một yêu cầu đi qua
FacesServlet Servlet xem xét yêu cầu và trích ra mã nhận dạng ID của khung nhìn, được xác định bởi tên của trang JSP
Trình điều khiển của khung công tác JSF sử dụng mã nhận dạng khung nhìn để tìm kiếm các thành phần dùng cho khung nhìn hiện tại Nếu khung nhìn còn chưa tồn tại, trình điều khiển JSF tạo ra nó Nếu khung nhìn đã tồn tại, trình điều khiển JSF sử dụng nó Khung nhìn có chứa tất cả các thành phần GUI
Pha này của vòng đời đưa ra ba cá thể khung nhìn: khung nhìn mới, khung nhìn khởi đầu, và khung nhìn hiện lại (postback), mỗi khung nhìn được xử lý khác nhau Trong trường hợp khung nhìn mới, JSF xây dựng khung nhìn của trang Faces và nối các trình xử lý sự kiện và trình duyệt tính hợp lệ tới các thành phần Khung nhìn được lưu trong một đối tượng FacesContext