by Mr Ramanjaneyulu Dayinaboyina 9/6/2011
In this article you'll learn
- what a custom tag library is,
- why you want to use a custom tag library,
- the composition of a tag library, and
- how to build and use a complete library.
What
a Custom Tag Library Is
If you've ever had the opportunity
to build a web application using Java technology, chances are you have used
Java Server Pages (JSP) for content display. JSP is the technology that helps
separate the front end presentation from the middle and backend tiers. The
custom tag library is a powerful feature of JSP v1.1 that aids in that
separation. This technology is valuable to anyone who is building
production-quality web applications, and it is very applicable in today's
market.
Custom tag libraries allow the Java
programmer to write code that provides data access and other services, and they
make those features available to the JSP author in a simple to use XML-like
fashion. An action in a web application -- for example, gaining database access
-- can be customized by using a custom tag in a JSP page. The JSP author
doesn't have to understand the underlying detail to complete the action. In
short, a tag library is a collection of custom actions presented as tags.
Custom tags have many features that
make them attractive to use from any JSP. Custom tags can
- be customized via attributes passed from the calling page, either staticly or determined at runtime;
- have access to all the objects available to JSP pages including request, response, in and out;
- modify the response generated by the calling page;
- communicate with each other; you can create and initialize a JavaBeans component, create a variable that refers to that bean in one tag, and then use the bean in another tag;
- be nested within one another, allowing for complex interactions within a JSP page; and
- encapsulate both simple and complex behaviors in an easy to use syntax and greatly simplify the readability of JSP pages.
Any of these points is reason enough
to consider using a tag library.
Let's look at what makes up a tag
library and build one step by step.
The
Composition of a Tag Library
There are two types of components for
a tag library: the tag library descriptor file and the tag handlers. With these
a JSP is able to use tags contained in the library within its page.
The TLD File
A tag library descriptor (TLD) file is an XML document that describes the library. A TLD contains information about the library as a whole and about each tag contained in the library. TLDs are used by a JSP container to validate the tags.
A tag library descriptor (TLD) file is an XML document that describes the library. A TLD contains information about the library as a whole and about each tag contained in the library. TLDs are used by a JSP container to validate the tags.
There is typically some header
information followed by elements used to define the tag library. The elements are
<taglib>
|
The tag library itself.
|
<tlibversion>
|
The tag library's version.
|
<jspversion>
|
The JSP specification version the
tag library depends on.
|
<shortname>
|
A simple default name with a
mnemonic value. For example, <shortname> may be used as the preferred
prefix value in taglib directives and/or to create prefixes for IDs.
|
<uri>
|
A optional URI that uniquely
identifies the tag library.
|
<info>
|
Descriptive information about the
tag library.
|
Then each tag contained in the
library is described. There can be one or many tags per library. There is only
one TLD element required for all tags, and that is the one used to specify a
tag handler's class: <tagclass>classname</tagclass>
There are various other elements
used to describe tags. Which elements a tag uses will depend on how the tag is
implemented in the handler. We'll get to that discussion in the section below.
If a tag has attributes associated
with it, then each attribute must be described within the <tag> element. If an attribute is required by a tag, <required> is set to "true" or "yes". To allow a
runtime expression value to be used by the tag, the <rtexpvalue> is set to "true" or "yes". For each
attribute of a tag, a Bean-like getter/setter method needs to be defined in the
handler class. It's also possible to define scripting variables for use in
tags. This is accomplished using a TagExtraInfo class and will be discussed in the tag handler section. If
a TagExtraInfo is to be
used, the class must be defined using the <teiclass>classname<teiclass> within the tag definition.
A sample TLD named oreillySample.tld looks like
<?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">
<taglib>
<tlibversion>1.0</tlibversion>
<jspversion>1.1</jspversion>
<shortname>oreillySamples</shortname>
<info>OReilly Sample Tag
library</info>
<!-A Simple tag -->
<tag>
<name>hello</name>
<tagclass>oreilly.examples.Hello
</tagclass>
<!--Body content can have a value of
empty: no body
JSP: body that is evaluated by container,
then possibly processed by the tag
tagdependent: body is only processed by
tag; JSP in body is not evaluated.
-->
<bodycontent>empty</bodycontent>
<info>
This is a simple hello tag.
</info>
<!-- Optional attributes -->
<!- personalized name -->
<attribute>
<name>name</name>
<required>false</required>
<rtexpvalue>false</rtexpvalue>
</attribute>
</tag>
</taglib>
The Tag Handler
The tag is defined in a handler class. TagSupport is the base class used for simple tags. It can be found in the javax.servlet.tagext package. What your tag is implementing will depend on what methods could potentially be called and what needs to be implemented. TagSupport and TagBodySupport supply default implementations of the methods listed below.
The tag is defined in a handler class. TagSupport is the base class used for simple tags. It can be found in the javax.servlet.tagext package. What your tag is implementing will depend on what methods could potentially be called and what needs to be implemented. TagSupport and TagBodySupport supply default implementations of the methods listed below.
If your Tag Handler:
|
You need to implement the
following methods:
|
has no attributes and no body
|
doStartTag, doEndTag, release
|
has attributes
|
doStartTag, doEndTag,
set/getAttribute1...N
|
has a body with no interaction
|
doStartTag, doEndTag, release
|
has a body with interaction
|
doStartTag, doEndTag, release,
doInitBody, doAfterBody
|
A more advanced feature is the use
of scripting variables. Typically an attribute is passed to the tag that
contains the ID of the object to be used. The usual operation is that the tag
handler retrieves a scripting variable value object using pageContext.getAttribute(name), performs some processing on it, and then sets the
scripting variable's value using the pageContext.setAttribute(name,
object). In addition to setting the value
of the variable within the tag handler, you must define a class derived from TagExtraInfo that provides information to the JSP container about the
nature of the variable. That class is then listed in the <teiclass> attribute of the tag.
The Java code for the tag defined in
the oreillySample.tld file would look like
package
oreilly.examples
import
javax.servlet.jsp.*;
import
javax.servlet.jsp.tagext.*;
/**
* This is a simple tag example to show how
content is added to the
* output stream when a tag is encountered in a
JSP page.
*/
public
class Hello extends TagSupport {
private String name=null;
/**
* Getter/Setter for the attribute name as
defined in the tld file
* for this tag
*/
public
void setName(String value){
name = value;
}
public String getName(){
return(name);
}
/**
*
doStartTag is called by the JSP container when the tag is encountered
*/
public int doStartTag() {
try {
JspWriter out = pageContext.getOut();
out.println("<table
border="\1\">");
if (name != null)
out.println("<tr><td> Hello " + name + "
</td></tr>");
else
out.println("<tr><td> Hello World
</td></tr>");
} catch (Exception ex) {
throw new Error("All is not well in the world.");
}
// Must return SKIP_BODY because we are not supporting a body for this
// tag.
return SKIP_BODY;
}
/**
* doEndTag is called by the JSP container when
the tag is closed
*/
public int doEndTag(){
try {
JspWriter
out = pageContext.getOut();
out.println("</table>");
} catch (Exception ex){
throw new Error("All is
not well in the world.");
}
}
}
The
JSP
Once your TLD and tag handlers are
created, you can begin accessing the tags in your JSP. You declare that a JSP
page will use tags defined in a tag library by including a taglib directive in the page before any custom tag is used. The
prefix attribute is a shortcut to referencing the library throughout the page.
Sample Hello.jsp:
<%@
taglib uri="/oreillySample.tld" prefix="sample" %>
<html>
<head>
<title>Your Standard
Hello World Demo</title>
</head>
<body
bgcolor="#ffffff">
<hr />
<sample:hello
name="Sue"/>
<hr />
</body>
</html>
The HTML source output from this JSP
would look like:
<html>
<head>
<title>Your Standard
Hello World Demo</title>
</head>
<body
bgcolor="#ffffff">
<hr />
<table border="1">
<tr><td> Hello Sue
</td></tr>
</table>
<hr />
</body>
</html>
You can see how the tag was
evaluated and the contents of the tag inserted into the output stream.
If you wanted to add functionality
to our tag to make it more flexible, say to evaluate a body a certain number of
times and make the name attribute evaluated at runtime, you can do so fairly
easily with a few changes. First you would make the following changes to the
TLD file. The tag definition would look like
<tag>
<name>hello</name>
<tagclass>oreilly.examples.Hello
</tagclass>
<!-- Allow for a body to be included
for this tag -->
<bodycontent>JSP</bodycontent>
<info>
This is a simple hello tag.
</info>
<!-- Optional attributes -->
<!-- personalized name -->
<attribute>
<name>name</name>
<required>false</required>
<rtexpvalue>true</rtexpvalue>
</attribute>
<!-allow for the jsp coder to specify
how many times to iterate -->
<attribute>
<name>iterations</name>
<required>false</required>
<rtexpvalue>false</rtexpvalue>
</attribute>
</tag>
Then you must alter the handler
class by extending TagBodySupport and implementing the body methods if you wanted different
behavior from that provided in the base class implementation. The handler class
would now look like
public
class Hello extends BodyTagSupport {
private String name=null;
private int iterations=1;
/**
* Getter/Setter for the attribute name as
defined in the tld file
* for this tag
*/
public void setName(String value){
name = value;
}
public String getName(){
return(name);
}
/**
* Getter/Setter for the attribute
iterations as defined in the tld file
* for this tag
*/
public void setIterations(String value){
try {
iterations = Integer.parseInt(value);
}
catch(NumberFormatException nfe) {
iterations = 1;
}
}
public String getIterations(){
return(Integer.toString(iterations));
}
public int doStartTag() throws
JspTagException{
try {
JspWriter out = pageContext.getOut();
out.println("<table
border=\"1\">");
if (name != null)
out.println("<tr><td> Hello " + name + "
</td></tr>");
else
out.println("<tr><td> Hello World
<td></tr>");
} catch (Exception ex) {
throw new JspTagException("All is not well in the world." + ex
);
}
// Evaluate the body if there is one
return EVAL_BODY_TAG;
}
public int doEndTag()throws
JspTagException {
try {
JspWriter
out = pageContext.getOut();
out.println("</table>");
} catch (Exception ex){
throw new
JspTagException("All is not well in the world." + ex);
}
}
public int doAfterBody() throws
JspTagException {
if (iterations-- >= 1) {
BodyContent body = getBodyContent();
try {
// Make sure we put anything in
the output stream in the
// body to the output stream of
the JSP
JspWriter out =
body.getEnclosingWriter();
out.println(body.getString());
body.clearBody(); // Clear for next
evaluation
} catch(IOException ioe) {
throw new JspTagException("Error
in Hello tag doAfterBody " + ioe);
}
return(EVAL_BODY_TAG);
} else {
return(SKIP_BODY);
}
}
Now let's make the simple changes in
the JSP file. Our sample Hello.jsp looks like
<%@
taglib uri="/oreillySample.tld" prefix="sample" %>
<%!
// allow a username to be passed in the
request
String userName =
request.getParameter("NAME");
%>
<html>
<head>
<title>Your Standard
Hello World Demo</title>
</head>
<body
bgcolor="#ffffff">
<hr />
<sample:hello
name="<%= userName %>" iterations="2">
<tr><td><b>Have
a nice day</b></td></tr>
</sample:hello>
<hr />
</body>
</html>
If our JSP page was called like hello.jsp?NAME=Sue our output would look like
<html>
<head>
<title>Your Standard
Hello World Demo</title>
</head>
<body bgcolor="#ffffff">
<hr />
<table border="1">
<tr><td> Hello Sue
</td></tr>
<tr><td><b>Have a nice
day</b></td></tr>
<tr><td><b>Have a nice
day</b></td></tr>
</table>
<hr />
</body></html>This simple example is but a small glimpse at the power of
custom tag libraries. We examined how to create and use a simple tag library
and then easily extend its functionality. The next article will examine some of
the advanced features of tags, including defining scripting variables and
cooperating tags. It will also go through working examples of each.
కామెంట్లు లేవు:
కామెంట్ను పోస్ట్ చేయండి