III. Định nghĩa các tag.
2. Taglibrary descriptor.
Tag library descriptor (TLD) là một tài liệu XML dùng để mơ tả thư viện
tag. Một TLD chứa toàn bộ thơng tin về thư viện và mỗi tag chứa trong thư viện.
JSP container và các cơng cụ phát triển JSP sử dụng TLD để xác định các tag. Các element của TLD sau dùng để định nghĩa thư viện tag:
Code 21: HelloWorldTag.java
<?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE taglib
PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library1.1//EN"
"http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd"> <!-- a tag library descriptor -->
<taglib>
<tlibversion> <!-- Phiên bản của thư viện tag -->
<!-- Phiên bản của JSP mà tag handler phụ thuộc --> <jspversion>
<!--Tên mặt định đơn giản cĩ thể dùng bởi cơng cụ tạo trang JSP để
tạo tên với giá trị gợi nhớ; chẳng hạn shortname cĩ thể được dùng
như giá trị tiếp đầu ngữ thích hợp trong taglibdirective và/hoặc tạo ra
các tiếp đầu ngữ cho các id --> <shortname>
<uri> <!-- URI duy nhất xác định tag library --> <info> <!-- Thơng tin mơ tả về tag library --> <tag> ... </tag> ... </taglib>
Tag element yêu cầu đối với mọi tag để xác định một lớp cĩ trong thư
viện tag. <tag> <tagclass>classname</tagclass> ... </tag> 3. Các ví dụ.
Để tạo các custom tag chúng ta cần hai import gĩi cơ bản:
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*; // tag extension
a) Các tag đơn giản.
-
- TTaagghhaannddlleerr
Đối với các tag đơn giản chỉ cần cài đặt hai phương thức của giao
tiếp Tag là doStartTag và doEndTag. doStartTag được triệu gọi khi
JSP container gặp start tag, nĩ trả về SKIP_BODY vì thân tag
container gọi doEndTag, trả về EVAL_PAGE nếu phần cịn lại của
trang cần phải định trị, nếu khơng trả về SKIP_PAGE.
Lớp tag handler sẽ được cài đặt như sau:
Code 22: HelloWorldTag.java
public HelloWorldTag extends TagSupport { public int doStartTag() throws JspException {
try { pageContext.getOut().print("Hello World."); } catch (Exception ex) {
throw new JspTagException("HelloWorldTag: " + e.getMessage());
}
return SKIP_BODY; }
public int doEndTag() { return EVAL_PAGE; }
}
-
- TTLLDDeelleemmeenntt
Các tag mà khơng cĩ thân phải khai báo nội dung của thân là rỗng.
Code 23: helloworld.tld
<?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE taglib
PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
"http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd"> <!--Nếu cĩ JSP v1.2 thì đổi lại
"http://java.sun.com/j2ee/dtds/jsptaglibrary_1_2.dtd"--> <!-- a tag library descriptor -->
<taglib> <tlibversion>1.0</tlibversion> <jspversion>1.1</jspversion> <shortname>legiang</shortname> <uri></uri> <info>
A tag library from authors at http://www.legiang.com/. </info>
<tag>
<name>helloWorld</name>
<tagclass>com.legiang.HelloWorldTag</tagclass> <info>Ví dụ với tag đơn giản nhất</info>
<!-- ‘EMPTY’ is insensitive case --> <bodycontent>EMPTY</bodycontent> </tag>
<!-- Other tags defined later... --> </taglib>
Đồ án tốt nghiệp Gvhd: Ts. Nguyễn Thúc Hải
Svth: Đinh Lê Giang Trang 39
- - JJSSPPppaaggee Code 24: hello.jsp <?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd"> <html> <head>
Code 24: hello.jsp (tiếp theo)
<%@ taglib uri = "helloworld.tld" prefix = "legiang" %> <title>
<legiang:helloWorld /> </title>
<!-- stylesheet để hiển thị các tag như h1, …--> <link rel = "stylesheet" href ="JSP-Styles.css" type = "text/css"/> </head> <body> <h1><legiang:helloWorld /></h1> <legiang:helloWorld /> </body> </html> b) Các tag cĩ thuộc tính. - - ĐĐịịnnhhnngghhĩĩaaccáácctthhuuộộccttíínnhhttrroonnggttaagghhaannddlleerr..
Đối với mỗi thuộc tínch của tag, chúng ta phải định nghĩa theo
phong cách của JavaBean, tức là phải cĩ phương thức get/set[Attribute] trong tag handler.
Hãy nhớ rằng, nếu thuộc tính được đặt tên là id và tag handler kết
thừa từ lớp TagSupport thì chúng ta khơng cần định nghĩa các phương thức
get/set[Attribute] bởi vì những thứ này đã được TagSupport làm sẵn.
Lớp tag handler sẽ được cài đặt như sau:
Code 25: HelloWorldTag.java (sữa lại trong Code 22 )
public HelloWorldTag extends TagSupport { private String name = “World.”;
public void setName(String name) { this.name = name;
}
public int doStartTag() throws JspException { try {
pageContext.getOut().print("Hello " + name); } catch (Exception ex) {
e.getMessage());
Code 25: HelloWorldTag.java (sữa lại trong Code 22) (tiếp theo)
}
return SKIP_BODY; }
public int doEndTag() { return EVAL_PAGE; }
}
-
- TTLLDDeelleemmeenntt
Đối với mỗi thuộc tính chúng ta phải xác định thuộc tính nào
được yêu cầu (bắt buộc) và giá trị nào cĩ thể được xác định bởi biểu thức. Nếu
thuộc tính của tag khơng bắt buộc thì tag handler nên cung ấp giá trị mật định.
TLD cho tag handler ở trên như sau:
Code 26: TLD file (overwrite helloworld.tld)
... <!-- đoạn này tương tự như mục 1) --> <tag>
<name>helloWorld</name>
<tagclass>com.legiang.HelloWorldTag</tagclass> <info>Ví dụ với tag đơn giản nhất</info>
<attribute>
<name>name</name> <required>false</required> <rtexprvalue>false</rtexprvalue> </attribute>
<!-- ‘EMPTY’ is insensitive case --> <bodycontent>EMPTY</bodycontent> </tag> - - JJSSPPppaaggee Code 27: paramtag.jsp <?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd"> <html>
Code 27: paramtag.jsp (tiếp theo)
<head>
<%@ taglib uri = "helloworld.tld" prefix = "legiang" %> <title> Tag With Attributes </title>
<!-- stylesheet để hiển thị các tag như h1, …--> <link rel = "stylesheet" href ="JSP-Styles.css" type = "text/css"/>
Đồ án tốt nghiệp Gvhd: Ts. Nguyễn Thúc Hải
Svth: Đinh Lê Giang Trang 41
</head> <body>
<h1><legiang:helloWorld name = "BKHN University" /></h1>
<legiang:helloWorld name = "DHBK Ha Noi" /> </body>
</html>
c) Các tag cĩ nội dung.
-
- TTaagghhaannddlleerr
Tag handler cho loại này được cài đặt khác nhau phụ thuộc vào tag handler cĩ tương tác với thân hay khơng. Tương tác cĩ nghĩa là tag handler đọc
hoặc sữa đổi nội dung của thân hoặc tạo ra giá trị lặp lại cho thân tag.
Các tag cĩ tương tác với phần thân: nếu tag handler khơng cần tương tác với phần thần thì tag handler này nên cài đặt giao tiếp Tag hoặc dẫn
xuất từ lớp TagSupport. Nếu thân của tag cần định trị thì doStartTag cần phải trả
về EVAL_BODY_INCLUDE, ngược lại trả về SKIP_BODY.
Các tag cĩ tương tác với phần thân: tag handler phải cài đặt giao
tiếp BodyTag hoặc BodyTagSupport, thường cài đặt phương thức doInitBody và
doAfterBody. Hai phương thức này tương tác với nội dung của thân được chuyển
vào tag handler bởi lớp cài đặt trang JSP. Đối tượng BodyContent cung cấp vài
phương thức để đọc và ghi nội dung của nĩ. Tag handler sử dụng các phương
thức getString, getReader của BodyContent để trích thơng tin từ phần thân và
phương thức writeOut(out) để ghi các nội dung của thân vào luồng xuất. Phương
thức getPreviousOut thường được sử dụng để bảo đảm rằng kết quả trả về của tag handler thì cĩ sẳn đối với toàn bộ tag handler. Các phương thức chính được
dùng trong loại tag này:
doInitBody: được gọi sau khi nội dung của thân được gán nhưng trước khi được định giá trị, thường được dùng để thực hiện khởi
tạo giá trị mà tuỳ thuộc vào nội dung của thân.
doAfterBody: được gọi sau khi nội dung của thân được định trị.
Nếu thân được trị nhiều lần lặp đi lặp lại nên trả về EVAL_BODY_TAG, ngược lại trả về SKIP_BODY.
release: tag handler nên xác lập lại trạng thái của nĩ và giải phĩng
các tài nguyên dành riêng bằng phương thức release.
Ví dụ sau đọc nội dung của thân, chuyển nội dung đĩ, và sau đĩ
ghi lại những thay đổi vào luồng xuất.
Code 28: TransformTag.java
public class TransformTag extends BodyTagSupport { public int doAfterBody() throws JspTagException { BodyContent bc = getBodyContent();
bc.clearBody(); try {
getPreviousOut().print(body.transform()); } catch (IOException e) {
throw new JspTagException("TransformTag: " + e.getMessage()); } return SKIP_BODY; } } - - TTLLDDeelleemmeenntt
TLD ở đây chỉ sữa đổi lại các ví dụ trên trong bodycontent tag và
đặt tên file là transform.tld <tag> ...
<bodycontent>JSP<bodycontent> <tag>
Với các tag cĩ phần thân thì bodycontent tag cĩ hai giá trị. Một là JSP, phần thân bao gồm custom tag, scripting element và văn bản HTML. Tất cả
các thứ cịn lại cĩ giá trị là tagdependent. Chú ý rằng giá trị của element này khơng ảnh hưởng tới tiến trình thơng dịch của thân.
- - JJSSPPppaaggee Code 29: transformtag.jsp <?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd"> <html> <head>
<%@ taglib uri = "transform.tld" prefix = "legiang" %> <title> Tag With Body </title>
<!-- stylesheet để hiển thị các tag như h1, …--> <link rel = "stylesheet" href ="JSP-Styles.css" type = "text/css"/>
</head> <body>
<h1> Tag With Body </h1> <legiang:transform>
Hi! BKHN University </legiang:transform> </body>
</html>
Đồ án tốt nghiệp Gvhd: Ts. Nguyễn Thúc Hải
Svth: Đinh Lê Giang Trang 43
-
- TTaagghhaannddlleerr
Tag handler đảm nhận việc tạo và gán đối tượng được tham chiếu
bởi biến kịch bản vào ngữ cảnh cĩ thể truy cập từ một trang. Để Làm được điều
này bằng cách dùng hoặc phương thức pageContext.setAttribute(name, value, scope) hoặc pageContext.setAttribute(name, value). Thơng thường một thuộc tính
chuyển vào custom tag phải xác định “tên” của biến đối tượng; Tên này cĩ thể
truy xuất bằng cách gọi phương thức get[Attribute] của thuộc tính (xem 2) Các
tag cĩ thuộc tính).
Nếu giá trị của biến kịch bản phụ thuộc vào đối tượng hiện tại trong
tag handler thì nĩ cĩ thể truy xuất đối tượng này bằng cách dùng
pageContext.setAttribute(name, scope). Các giá trị của tham số scope được tĩm
tắc trong bảng sau:
P
Phhạạmmvvii CCĩĩtthhểểttrruuyyccậậppttừừ TThhờờiiggiiaannssốốnngg
page Trang hiện hành
Cho tới khi lời đáp gởi
trở lại user hoặc yêu cầu được chuyển tới trang
mới
request
Trang hiện hành và bất
kỳ trang được include
hay forward nào
Cho tới khi lời đáp gởi
trở lại user
session
Yêu cầu hiện hành và bất kỳ yêu cầu tiếp theo
trong cùng browser
Đời sống của một phiên làm việc (session)
application
Bất kỳ yêu cầu hiện tại và tương lai nào từ cùng một ứng dụng
Đời sống của một ứng
dụng
Ngồi việc cài đặt giá trị của biến trong tag handler, chúng ta cịn phải định nghĩa một lớp dẫn xuất từ lớp TagExtrInfo. Lớp này cung cấp thơng tin cho JSP container về đặt tính của của biến kịch bản, phải cài đặt phương thức
getVariableInfo để trả về một mảng các đối tượng VariableInfo chứa các thơng
tin sau: tên biến, lớp của biến, liệu biến này cĩ tham khảo tới một giá trị đối tượng mới hay đã cĩ, tính sẳn dùng của biến này.
Bảng sau mơ tả tính sẳn dùng của biến kịch bản và các phương thức để xác lập và xác lập lại giá trị của biến.
Value Availability Methods
NESTED Giữa start tag và end tag.
Trong doInitBody và doAfterBody đối với tag handler cài đặt BodyTag;
AT_BEGIN Từ start tag cho đến cuối trang.
Trong doInitBody,
doAfterBody, và doEndTag đối
với tag handler cài đặt
BodyTag; ngược lại trong
doStartTag và doEndTag. AT_END Sau end tag cho
tới cuối trang. Trong doEndTag.
Lớp tag handler sau lấy dữ liệu từ JNDI lookup được lưu trữ như là
thuộc tính của đối tượng pageContext cùng với tên của biến kịch bản.
Code 30: LookupTag.java
public LookupTag extends TagSupport { private String type;
private String name;
public void setName(String name) { this.name = name;
}
public void setType(String type) { this. type = type;
}
public int doStartTag() { return SKIP_BODY; }
public int doEndTag() throws JspException { try {
InitialContext context = new InitialContext(); Object obj = (Object)context.lookup(name); pageContext.setAttribute(getId(), obj);
Code 30: LookupTag.java (tiếp theo)
} catch(javax.naming.NamingException e) {
throw new JspException("Unable to look up " + name + " due to " + e.getMessage());
}
return EVAL_PAGE; }
}
Biến kịch bản sẽ được định nghĩa trong lớp dẫn xuất từ lớp
TagExtraInfo. Do biến được truyền vào như các thuộc tính của tag nên sẽ được
truy xuất bởi phương thức getAttributeString của lớp TagData và dùng để lấp đầy
hàm tạo của VariableInfo. Để cho phép biến kịch bản được dùng trong phần cịn lại của trang thì phạm vi của biến nên gán bằng AT_END.
Code 31: LookupTagTei.java
Đồ án tốt nghiệp Gvhd: Ts. Nguyễn Thúc Hải
Svth: Đinh Lê Giang Trang 45
public VariableInfo[] getVariableInfo(TagData data) { VariableInfo info1 = new VariableInfo( data.getAttributeString("id"), data.getAttributeString("type"), true, VariableInfo.AT_END); VariableInfo[] info = { info1 } ; return info;
} }
-
- TTLLDDeelleemmeenntt
Chúng ta cần phải báo cho JSP container biết nĩ nên dùng lớp
TagExtraInfo để tạo ra biến kịch bản với phạm vi thích hợp. Đoạn TLD cĩ tên
lookup.tld như sau:
Code 32: TLD file ... <tag> <tagclass>com.legiang.LookupTag </tagclass> <teiclass>com.legiang.LookupTagTEI</teiclass> <attribute> <name>name</name> <required>true<required> <rtexprvalue>false</rtexprvalue> </attribute> <attribute> <name>type</name> <required>true<required> <rtexprvalue>false</rtexprvalue> </attribute> </tag> ... - - JJSSPPppaaggee Code 33: JSP file ...
<%@ taglib uri = "lookup.tld" prefix = "legiang" %> <!-- dùng trong body của JSP -->
<legiang:lookup id = "sv" type = "UserTransaction" name = "java:comp/ UserTransaction ">
<% sv.begin() %>