Apache Tapestry - Linh kiện
Như đã thảo luận trước đó, Thành phần và Trang giống nhau ngoại trừ Trang là thành phần gốc và bao gồm một hoặc nhiều thành phần con. Các thành phần luôn nằm bên trong một trang và thực hiện hầu hết các chức năng động của trang.
Các thành phần của tấm thảm hiển thị một liên kết HTML đơn giản đến chức năng lưới phức tạp với interactive AJAX. Một thành phần cũng có thể bao gồm một thành phần khác. Các thành phần của tấm thảm bao gồm các mục sau:
Component Class - Lớp Java chính của thành phần.
XML Template- Mẫu XML tương tự như mẫu Trang. Lớp thành phần hiển thị mẫu như là đầu ra cuối cùng. Một số thành phần có thể không có mẫu. Trong trường hợp này, đầu ra sẽ được tạo bởi chính lớp thành phần bằng cách sử dụngMarkupWriter lớp học.
Body- Thành phần được chỉ định bên trong mẫu trang có thể có đánh dấu tùy chỉnh và nó được gọi là “Nội dung thành phần”. Nếu mẫu thành phần có<body />thì phần tử <body /> sẽ được thay thế bằng phần thân của thành phần. Điều này tương tự như bố cục đã thảo luận trước đó trong phần mẫu XML.
Rendering - Kết xuất là một quá trình chuyển đổi khuôn mẫu và nội dung XML của thành phần thành đầu ra thực tế của thành phần.
Parameters - Được sử dụng để tạo giao tiếp giữa các thành phần và các trang và do đó truyền dữ liệu giữa chúng.
Events- Ủy quyền chức năng từ các thành phần cho vùng chứa / cha của nó (các trang hoặc một thành phần khác). Nó được sử dụng rộng rãi trong mục đích điều hướng trang.
Kết xuất
Việc kết xuất một thành phần được thực hiện trong một loạt các giai đoạn được xác định trước. Mỗi pha trong hệ thống thành phần cần có một phương thức tương ứng được xác định theo quy ước hoặc chú thích trong lớp thành phần.
// Using annotaion
@SetupRender
void initializeValues() {
// initialize values
}
// using convention
boolean afterRender() {
// do logic
return true;
}
Các giai đoạn, tên phương thức của nó và các chú thích của nó được liệt kê bên dưới.
Chú thích | Tên phương pháp mặc định |
---|---|
@SetupRender | setupRender () |
@BeginRender | beginRender () |
@BeforeRenderTemplate | beforeRenderTemplate () |
@BeforeRenderBody | beforeRenderBody () |
@AfterRenderBody | afterRenderBody () |
@AfterRenderTemplate | afterRenderTemplate () |
@AfterRender | afterRender () |
@CleanupRender | cleanupRender () |
Mỗi giai đoạn có một mục đích cụ thể và chúng như sau:
SetupRender
SetupRender khởi động quá trình kết xuất. Nó thường thiết lập các tham số của thành phần.
BeginRender
BeginRender bắt đầu hiển thị thành phần. Nó thường hiển thị thẻ bắt đầu / bắt đầu của thành phần.
BeforeRenderTemplate
BeforeRenderTemplate được sử dụng để trang trí mẫu XML, thêm đánh dấu đặc biệt xung quanh mẫu. Nó cũng cung cấp một tùy chọn để bỏ qua việc kết xuất mẫu.
BeforeRenderBody
BeforeRenderTemplate cung cấp một tùy chọn để bỏ qua việc kết xuất phần thân của thành phần.
AfterRenderBody
AfterRenderBody sẽ được gọi sau khi phần thân của thành phần được kết xuất.
AfterRenderTemplate
AfterRenderTemplate sẽ được gọi sau khi mẫu của thành phần được hiển thị.
AfterRender
AfterRender là bản sao của BeginRender và thường hiển thị thẻ đóng.
CleanupRender
CleanupRender là bản sao của SetupRender. Nó giải phóng / xử lý tất cả các đối tượng được tạo ra trong quá trình kết xuất.
Luồng của các giai đoạn kết xuất không chỉ chuyển tiếp. Nó đi qua lại giữa các pha tùy thuộc vào giá trị trả về của một pha.
Ví dụ: nếu phương thức SetupRender trả về false, thì kết xuất sẽ chuyển sang giai đoạn CleanupRender và ngược lại. Để hiểu rõ ràng về dòng chảy giữa các pha khác nhau, hãy kiểm tra dòng chảy trong sơ đồ dưới đây.
Thành phần đơn giản
Hãy để chúng tôi tạo một thành phần đơn giản, Xin chào sẽ có thông báo đầu ra là “Xin chào, Tấm thảm”. Sau đây là mã của thành phần Hello và mẫu của nó.
package com.example.MyFirstApplication.components;
public class Hello {
}
<html
xmlns:t = "https://tapestry.apache.org/schema/tapestry_5_4.xsd"
xmlns:p = "tapestry:parameter">
<div>
<p>Hello, Tapestry (from component).</p>
</div>
</html>
Thành phần Hello có thể được gọi trong một mẫu trang là:
<html title = "Hello component test page"
xmlns:t = "https://tapestry.apache.org/schema/tapestry_5_4.xsd"
xmlns:p = "tapestry:parameter">
<t:hello />
</html>
Tương tự, thành phần có thể hiển thị cùng một đầu ra bằng cách sử dụng MarkupWriter thay vì mẫu như được hiển thị bên dưới.
package com.example.MyFirstApplication.components;
import org.apache.tapestry5.MarkupWriter;
import org.apache.tapestry5.annotations.BeginRender;
public class Hello {
@BeginRender
void renderMessage(MarkupWriter writer) {
writer.write("<p>Hello, Tapestry (from component)</p>");
}
}
Hãy để chúng tôi thay đổi mẫu thành phần và bao gồm phần tử <body /> như được hiển thị trong khối mã bên dưới.
<html>
xmlns:t = "https://tapestry.apache.org/schema/tapestry_5_4.xsd"
xmlns:p = "tapestry:parameter">
<div>
<t:body />
</div>
</html>
Bây giờ, mẫu trang có thể bao gồm phần thân trong phần đánh dấu thành phần như được hiển thị bên dưới.
<html title = "Hello component test page"
xmlns:t = "https://tapestry.apache.org/schema/tapestry_5_4.xsd"
xmlns:p = "tapestry:parameter">
<t:hello>
<p>Hello, Tapestry (from page).</p>
</t:hello>
</html>
Đầu ra sẽ như sau:
<html>
<div>
<p>Hello, Tapestry (from page).</p>
</div>
</html>
Thông số
Mục đích chính của các tham số này là tạo kết nối giữa trường của thành phần và thuộc tính / tài nguyên của trang. Sử dụng các tham số, thành phần và trang tương ứng của nó giao tiếp và truyền dữ liệu giữa nhau. Đây được gọi làTwo Way Data Binding.
Ví dụ, một thành phần hộp văn bản được sử dụng để biểu thị độ tuổi trong trang quản lý người dùng nhận giá trị ban đầu của nó (có sẵn trong cơ sở dữ liệu) thông qua tham số. Một lần nữa, sau khi tuổi của người dùng được cập nhật và gửi lại, thành phần sẽ gửi lại tuổi được cập nhật thông qua cùng một tham số.
Để tạo một tham số mới trong lớp thành phần, hãy khai báo một trường và chỉ định một @Parameterchú thích. @Parameter này có hai đối số tùy chọn, là:
required- làm cho tham số là bắt buộc. Tấm thảm làm tăng ngoại lệ nếu nó không được cung cấp.
value - chỉ định giá trị mặc định của tham số.
Tham số phải được chỉ định trong mẫu trang dưới dạng thuộc tính của thẻ thành phần. Giá trị của các thuộc tính phải được chỉ định bằng cách sử dụng Binding Expression / Expansion, mà chúng ta đã thảo luận trong các chương trước. Một số mở rộng mà chúng ta đã học trước đó là:
Property expansion (prop:«val») - Lấy dữ liệu từ thuộc tính của lớp trang.
Message expansion (message:«val») - Lấy dữ liệu từ khóa được xác định trong tệp index.properties.
Context expansion (context:«val») - Lấy dữ liệu từ thư mục ngữ cảnh web / src / main / webapp.
Asset expansion (asset:«val») - Lấy dữ liệu từ các tài nguyên được nhúng trong tệp jar, / META-INF / asset.
Symbol expansion (symbol:«val») - Lấy dữ liệu từ các ký hiệu được xác định trong AppModule.javafile.
Tấm thảm có nhiều mở rộng hữu ích hơn, một số trong số đó được đưa ra dưới đây -
Literal expansion (literal:«val») - Một chuỗi ký tự.
Var expansion (var:«val») - Cho phép một biến kết xuất của thành phần được đọc hoặc cập nhật.
Validate expansion (validate:«val»)- Một chuỗi chuyên dùng để chỉ định quy tắc xác nhận của một đối tượng. Ví dụ, xác thực: bắt buộc, minLength = 5.
Translate (translate:«val») - Được sử dụng để chỉ định lớp Translator (chuyển đổi biểu diễn phía máy khách sang phía máy chủ) trong xác thực đầu vào.
Block (block:«val») - Id của phần tử khối trong khuôn mẫu.
Component (component:«val») - Id của một thành phần khác trong khuôn mẫu.
Tất cả các mở rộng ở trên là chỉ đọc ngoại trừ mở rộng Thuộc tính và mở rộng Var. Chúng được thành phần sử dụng để trao đổi dữ liệu với trang. Khi sử dụng mở rộng làm giá trị thuộc tính,${...}không nên được sử dụng. Thay vào đó, chỉ sử dụng phần mở rộng không có ký hiệu đô la và dấu ngoặc nhọn.
Thành phần sử dụng tham số
Hãy để chúng tôi tạo một thành phần mới, HelloWithParameter bằng cách sửa đổi thành phần Hello để hiển thị động thông báo bằng cách thêm name tham số trong lớp thành phần và thay đổi mẫu thành phần và mẫu trang cho phù hợp.
Tạo một lớp thành phần mới HelloWithParameter.java.
Thêm một trường riêng tư và đặt tên nó bằng @Parameterchú thích. Sử dụng đối số bắt buộc để làm cho nó bắt buộc.
@Parameter(required = true)
private String name;
Thêm trường riêng tư, kết quả bằng @Properychú thích. Thuộc tính kết quả sẽ được sử dụng trong mẫu thành phần. Mẫu thành phần không có quyền truy cập vào các trường được chú thích bằng@Parameter và chỉ có thể truy cập vào các trường được chú thích bằng @Property. Biến có sẵn trong các mẫu thành phần được gọi là Biến kết xuất.
@Property
private String result;
Thêm một phương thức RenderBody và sao chép giá trị từ tham số tên sang thuộc tính kết quả.
@BeginRender
void initializeValues() {
result = name;
}
Thêm một mẫu thành phần mới HelloWithParamter.tml và sử dụng thuộc tính kết quả để hiển thị thông báo.
<div> Hello, ${result} </div>
Thêm thuộc tính mới, Tên người dùng trong trang thử nghiệm (testhello.java).
public String getUsername() {
return "User1";
}
Sử dụng thành phần mới được tạo trong mẫu trang và đặt thuộc tính Tên người dùng trong tham số tên của HelloWithParameter thành phần.
<t:helloWithParameter name = "username" />
Danh sách đầy đủ như sau:
package com.example.MyFirstApplication.components;
import org.apache.tapestry5.annotations.*;
public class HelloWithParameter {
@Parameter(required = true)
private String name;
@Property
private String result;
@BeginRender
void initializeValues() {
result = name;
}
}
<html
xmlns:t = "https://tapestry.apache.org/schema/tapestry_5_4.xsd"
xmlns:p = "tapestry:parameter">
<div> Hello, ${result} </div>
</html>
package com.example.MyFirstApplication.pages;
import org.apache.tapestry5.annotations.*;
public class TestHello {
public String getUsername() {
return "User1";
}
}
<html title = "Hello component test page"
xmlns:t = "https://tapestry.apache.org/schema/tapestry_5_4.xsd"
xmlns:p = "tapestry:parameter">
<t:helloWithParameter name = "username" />
</html>
Kết quả sẽ như sau:
<div> Hello, User1 </div>
Thông số nâng cao
Trong các chương trước, chúng ta đã phân tích cách tạo và sử dụng một tham số đơn giản trong một thành phần tùy chỉnh. Thông số nâng cao cũng có thể chứa đánh dấu hoàn chỉnh. Trong trường hợp này, đánh dấu phải được chỉ định bên trong thẻ thành phần, chẳng hạn như phần phụ trong mẫu trang. Thành phần if tích hợp có đánh dấu cho cả điều kiện thành công và thất bại. Đánh dấu thành công được chỉ định làm phần thân của thẻ thành phần và đánh dấu thất bại được chỉ định bằng cách sử dụngelseparameter.
Hãy để chúng tôi xem cách sử dụng ifthành phần. Thành phần if có hai tham số -
test - Tham số dựa trên thuộc tính đơn giản.
Else - Tham số nâng cao được sử dụng để chỉ định đánh dấu thay thế, nếu điều kiện không thành công
Tapestry sẽ kiểm tra giá trị của thuộc tính thử nghiệm bằng cách sử dụng logic sau và trả về true hoặc false. Đây được gọi làType Coercion, một cách chuyển đổi một đối tượng thuộc kiểu này sang kiểu khác có cùng nội dung.
Nếu kiểu dữ liệu là String, “Đúng” nếu không trống và không phải là chuỗi chữ “Sai” (không phân biệt chữ hoa chữ thường).
Nếu kiểu dữ liệu là Number, Đúng nếu khác 0.
Nếu kiểu dữ liệu là Collection, Đúng nếu không trống.
Nếu kiểu dữ liệu là Object, Đúng (miễn là nó không rỗng).
Nếu điều kiện vượt qua, thành phần sẽ hiển thị phần thân của nó; nếu không, nó sẽ hiển thị phần thân của tham số else.
Danh sách đầy đủ như sau:
package com.example.MyFirstApplication.pages;
public class TestIf {
public String getUser() {
return "User1";
}
}
<html title = "If Test Page"
xmlns:t = "http://tapestry.apache.org/schema/tapestry_5_4.xsd"
xmlns:p = "tapestry:parameter">
<body>
<h1>Welcome!</h1>
<t:if test = "user">
Welcome back, ${user}
<p:else>
Please <t:pagelink page = "login">Login</t:pagelink>
</p:else>
</t:if>
</body>
</html>
Sự kiện thành phần / Điều hướng trang
Ứng dụng tấm thảm là một collection of Pagestương tác với nhau. Cho đến bây giờ, chúng ta đã học cách tạo các trang riêng lẻ mà không cần bất kỳ giao tiếp nào giữa chúng. Mục đích chính của sự kiện Thành phần là cung cấp sự tương tác giữa các trang (cả trong các trang) bằng cách sử dụng các sự kiện phía máy chủ. Hầu hết các sự kiện thành phần bắt nguồn từ các sự kiện phía máy khách.
Ví dụ: khi người dùng nhấp vào liên kết trong một trang, Tapestry sẽ gọi chính trang đó với thông tin mục tiêu thay vì gọi trang mục tiêu và tăng sự kiện phía máy chủ. Trang tấm thảm sẽ nắm bắt sự kiện, xử lý thông tin mục tiêu và thực hiện chuyển hướng phía máy chủ đến trang mục tiêu.
Tấm thảm sau một Post/Redirect/Get (RPG) design patternđể điều hướng trang. Trong RPG, khi người dùng thực hiện yêu cầu đăng bằng cách gửi biểu mẫu, máy chủ sẽ xử lý dữ liệu đã đăng, nhưng không trả lại phản hồi trực tiếp. Thay vào đó, nó sẽ thực hiện chuyển hướng phía máy khách sang một trang khác, điều này sẽ xuất ra kết quả. Mẫu RPG được sử dụng để ngăn việc gửi biểu mẫu trùng lặp thông qua nút quay lại trình duyệt, nút làm mới trình duyệt, v.v., Tapestry cung cấp mẫu RPG bằng cách cung cấp hai loại yêu cầu sau.
Component Event Request- Loại yêu cầu này nhắm mục tiêu đến một thành phần cụ thể trong một trang và nêu ra các sự kiện trong thành phần đó. Yêu cầu này chỉ thực hiện chuyển hướng và không xuất ra phản hồi.
Render Request - Những loại yêu cầu này nhắm mục tiêu một trang và truyền phản hồi trở lại máy khách.
Để hiểu các sự kiện thành phần và điều hướng trang, chúng ta cần biết mẫu URL của yêu cầu tấm thảm. Mẫu URL cho cả hai loại yêu cầu như sau:
Component Event Requests -
/<<page_name_with_path>>.<<component_id|event_id>>/<<context_information>>
Render Request -
/<<page_name_with_path>>/<<context_information>>
Một số ví dụ về các mẫu URL là:
Trang chỉ mục có thể được yêu cầu bởi https://«domain»/«app»/index.
Nếu trang Chỉ mục có sẵn dưới quyền quản trị thư mục con, thì trang này có thể được yêu cầu bởi https://«domain»/«app»/admin/index.
Nếu người dùng nhấp vào ActionLink component với id test trong trang chỉ mục, thì URL sẽ là https://«domain»/«app»/index.test.
Sự kiện
Theo mặc định, Tapestry tăng OnPassivate và OnActivatesự kiện cho tất cả các yêu cầu. Đối với loại yêu cầu sự kiện Thành phần, thảm trang trí thêm một hoặc nhiều sự kiện tùy thuộc vào thành phần. Thành phần ActionLink tăng sự kiện Hành động, trong khi thành phần Biểu mẫu tăng nhiều sự kiện, chẳng hạn nhưValidate, Success, Vân vân.,
Các sự kiện có thể được xử lý trong lớp trang bằng cách sử dụng trình xử lý phương thức tương ứng. Trình xử lý phương thức được tạo thông qua quy ước đặt tên phương thức hoặc thông qua@OnEventchú thích. Định dạng của quy ước đặt tên phương thức làOn«EventName»From«ComponentId».
Một sự kiện hành động của thành phần ActionLink với id test có thể được xử lý bằng một trong các phương pháp sau:
void OnActionFromTest() {
}
@OnEvent(component = "test", name = "action")
void CustomFunctionName() {
}
Nếu tên phương thức không có bất kỳ thành phần cụ thể nào, thì phương thức sẽ được gọi cho tất cả thành phần có sự kiện phù hợp.
void OnAction() {
}
Sự kiện OnPassivate và OnActivate
OnPassivate được sử dụng để cung cấp thông tin ngữ cảnh cho trình xử lý sự kiện OnActivate. Nói chung, Tapestry cung cấp thông tin ngữ cảnh và nó có thể được sử dụng làm đối số trong trình xử lý OnActivateevent.
Ví dụ: nếu thông tin ngữ cảnh là 3 kiểu int, thì sự kiện OnActivate có thể được gọi là -
void OnActivate(int id) {
}
Trong một số trường hợp, thông tin ngữ cảnh có thể không có sẵn. Trong tình huống này, chúng tôi có thể cung cấp thông tin ngữ cảnh cho trình xử lý sự kiện OnActivate thông qua trình xử lý sự kiện OnPassivate. Kiểu trả về của trình xử lý sự kiện OnPassivate nên được sử dụng làm đối số của trình xử lý sự kiện OnActivate.
int OnPassivate() {
int id = 3;
return id;
}
void OnActivate(int id) {
}
Giá trị trả lại của trình xử lý sự kiện
Tapestry vấn đề chuyển hướng trang dựa trên các giá trị trả về của trình xử lý sự kiện. Trình xử lý sự kiện sẽ trả về bất kỳ giá trị nào sau đây.
Null Response- Trả về giá trị null. Tapestry sẽ tạo URL của trang hiện tại và gửi cho khách hàng dưới dạng chuyển hướng.
public Object onAction() {
return null;
}
String Response- Trả về giá trị chuỗi. Tapestry sẽ tạo URL của trang phù hợp với giá trị và gửi đến khách hàng dưới dạng chuyển hướng.
public String onAction() {
return "Index";
}
Class Response- Trả về một lớp trang. Tapestry sẽ xây dựng URL của lớp trang được trả về và gửi đến máy khách dưới dạng chuyển hướng.
public Object onAction() {
return Index.class
}
Page Response- Trả về một trường được chú thích bằng @InjectPage. Tapestry sẽ tạo URL của trang được đưa vào và gửi đến máy khách dưới dạng chuyển hướng.
@InjectPage
private Index index;
public Object onAction(){
return index;
}
HttpError- Trả về đối tượng HTTPError. Tấm thảm sẽ gây ra lỗi HTTP phía máy khách.
public Object onAction(){
return new HttpError(302, "The Error message);
}
Link Response- Trả về một thể hiện liên kết trực tiếp. Tapestry sẽ tạo URL từ đối tượng Liên kết và gửi đến máy khách dưới dạng chuyển hướng.
Stream Response - Trả về StreamResponsevật. Tapestry sẽ gửi luồng dưới dạng phản hồi trực tiếp đến trình duyệt của khách hàng. Nó được sử dụng để tạo báo cáo và hình ảnh trực tiếp và gửi cho khách hàng.
Url Response - Trả về java.net.URLvật. Tapestry sẽ lấy URL tương ứng từ đối tượng và gửi đến máy khách dưới dạng chuyển hướng.
Object Response- Trả về bất kỳ giá trị nào khác với các giá trị đã chỉ định ở trên. Tấm thảm sẽ gây ra lỗi.
Bối cảnh sự kiện
Nói chung, trình xử lý sự kiện có thể lấy thông tin ngữ cảnh bằng cách sử dụng các đối số. Ví dụ: nếu thông tin ngữ cảnh là 3 kiểu int, thì trình xử lý sự kiện sẽ là:
Object onActionFromTest(int id) {
}
Tapestry xử lý đúng thông tin ngữ cảnh và cung cấp thông tin đó cho các phương thức thông qua các đối số. Đôi khi, Tapestry có thể không xử lý được đúng cách do sự phức tạp của chương trình. Khi đó, chúng tôi có thể nhận được thông tin ngữ cảnh đầy đủ và tự xử lý.
Object onActionFromEdit(EventContext context) {
if (context.getCount() > 0) {
this.selectedId = context.get(0);
} else {
alertManager.warn("Please select a document.");
return null;
}
}