Sie sind auf Seite 1von 18

An Introduction to JSP Custom Tags

Presented by Shireesh Thanneru, The Sycamore Group Inc.


http://www.TheSycamoreGroup.com
Table of Contents
If you're viewing this document online, you can click any of the topics below to link directly to that section.
1. Why Custom Tags 2
2. Tag Libraries 5
3. How Tag Libraries work 10
4. Example: HTML Encoding 12
5. Example: Simple Iteration 15
An Introduction to JSP Custom Tags Page 1
Section 1. Why Custom Tags
The Problem with Straight-up Servlets
In the beginning, servlets were invented, and the world saw that they were good.
Dynamic web pages based on servlets executed quickly, could be moved between
servers easily, and integrated well with back-end data sources. Servlets became widely
accepted as a premiere platform for server-side web development.
However, the commonly-used simple approach to generating HTML content, having
the programer write an out.println() call per HTML line, became a serious problem for
real servlet use. HTML content had to be created within code, an onerous and time
consuming task for long HTML pages. In addition, content creators had to ask
developers to make all content changes. People searched for a better way.
Enter JSP
With this new technology you could put snippets of Java code inside your HTML, and
the server would automatically create a servlet from the page. This helped quite a lot.
But having artists and developers working on the same file wasn't ideal, and having
Java inside HTML proved almost as awkward as having HTML inside Java. It could
easily create a hard to read mess.
So people matured in their use of JSP and started to rely more on JavaBeans. Beans
were written to contain business logic code needed by the JSP page. Much of the code
inside the JSP page could be moved out of the page into the bean with only minimal
hooks left behind where the page would access the bean.
More recently, people have started to note that JSP pages used this way are really a
"view". They're a component used to display the results of a client request. So people
thought, Why submit a request directly to a "view"? What if the targetted "view" isn't the
proper view for that request? After all, many requests have several possible resulting
views. For example, the same request might generate a success page, a database
exception error report, or a required parameter missing error report.
Why must a client directly submit its request to a view? Shouldn't the client make a
request to some general server component and let the server determine the JSP view
to return? This belief caused many people to adopt what has been called the "Model 2"
design, named after an architecture laid out in the JSP 0.92 specification and based on
the model-view-controller pattern. This was another improvement -- and where many
serious developers stand today.
With this design, requests are submitted to a servlet "controller" that performs business
logic and generates an appropriate data "model" to be displayed. This data is then
passed internally to a JSP page "view" for rendering, where it appears to the JSP page
like a normal embedded JavaBean. The appropriate JSP page can be selected to do
the display, depending on the logic inside the controlling servlet. The JSP page
becomes a nice template.
Presented by Shireesh Thanneru http://thanneru.net
An Introduction to JSP Custom Tags Page 2
The Problems with JSP
Java Code Too Tempting JSP makes it tempting to put Java code in the web page,
even though that's considered bad design.
Java Code Required Doing mundane things in JSP can actually demand putting Java
code in the page. For example, assume the page needs to determine the locale of the
current web user to create a link to the web app home page: In JSP this is best done
using Java code:
<a href="<%= session.getUserProfile().getLocale()
%>/index.html"> Home </a>
Lousy Looping Looping is overly difficult in JSP. Here's the JSP code to iterate over
an ArrayList of X objects printing the name of each.
<%
ArrayList list = (ArrayList) request.getParameter("list");
Iterator iter = list.iterator();
while (iter.hasNext()) {
%>
The next name is: <%= ((X)e.next()).getName()
%>
<br/>
<%
}
%>
The Solutions
Templating Engines
By using a template engine intended for this exact use instead of the general-purpose
JSP, the underlying design can be cleaner and the syntax can be clearer. Several
companies have built such engines, the most popular probably being WebMacro
(http://webmacro.org, from Semiotek) whose engine is free. But the templating engines
have their own drawbacks:
* No specification exists for how a template engine should behave.
* Template engines aren't widely known. Using template engines is a relatively
unknown alternative technique.
Custom Tags
Custom Tags offer an ideal solution for this "spaghetti code" problem. Tag libraries
improve the maintainability of web applications. This improved maintainance comes
from the implementation of the simple XML-based interface of the custom tag on the
JSP page.
Presented by Shireesh Thanneru http://thanneru.net
An Introduction to JSP Custom Tags Page 3
Advantages of Custom 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,
and out.
* modify the response generated by the calling page.
* create and initialize a JavaBeans component and introduce them as scripting
variables in a JSP.
* be nested within one another, allowing for complex interactions within a JSP
page.
* encapsulate both simple and complex behaviors in an easy to use syntax and
greatly simplify the readability of JSP pages.
Presented by Shireesh Thanneru http://thanneru.net
An Introduction to JSP Custom Tags Page 4
Section 2. Tag Libraries
The Components of a Tag Library
A simple custom tag consists of the following elements:
1. The Tag Handler: This is the actual core of a tag. A tag handler can reference
any outside material it needs (JavaBeans) and has access to all the information
from a JSP page (the pageContext object). Also the JSP page passes to the tag
handler all tag attributes that have been set as well as the content that resides
within the tag body statement on the JSP page. When the tag handler is finished
processing, it sends the output back to the JSP page.
2. The Tag Library Descriptor (tld file): This is a simple XML file which documents
the properties, information and location of the tag handler file. The JSP container
uses this file to map out where and how to use a called tag library.
3. The Web Site's web.xml File: This is the web application's initialization file and
within this file we define what custom tag libraries we are using in a web
application and which tld files are used to describe each custom tag library.
4. A Tag Library Declaration on the JSP Page: This is as simple as using a Taglib
directive to declare the existence of our tags. After the tag library has been
declared on the JSP page we can then use it freely within the JSP page.
The challenging part isn't the coding but rather hooking the pieces together correctly.
However, this layering is very important as it is one reason that tag libraries are flexible
and very portable.
The TLD File
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.
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
Presented by Shireesh Thanneru http://thanneru.net
An Introduction to JSP Custom Tags Page 5
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. 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(TEI) class. The TEI class specifies the name
of the scripting variable to be introduced, its class and its scope and also whether or
not to create a new one, if one is already not defined in the JSP page. If a
TagExtraInfo is to be used, the class must be defined using the
<teiclass>classname<teiclass> within the tag definition.
An Example TLD File
A sample TLD file 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>samples</shortname>
<info>Sample Tag library</info>
<!-A Simple tag -->
<tag>
<name>hello</name>
<tagclass>com.tsg.taglibs.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.
Presented by Shireesh Thanneru http://thanneru.net
An Introduction to JSP Custom Tags Page 6
</info>
<!-- Optional attributes -->
<!- personalized name -->
<attribute>
<name>name</name>
<required>false</required>
<rtexpvalue>true</rtexpvalue>
</attribute>
</tag>
</taglib>
An Example web.xml file
A sample web.xml looks like
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
"http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
<web-app>
<taglib>
<taglib-uri>
/tut
</taglib-uri>
<taglib-location>
/WEB-INF/tlds/taglib.tld
</taglib-location>
</taglib>
</web-app>
The Tag Handler
The Tag Handler The tag is defined in a handler class. TagSupport is generally used
as the base class used for simple tags. BodyTagSupport is generally used as the
base class used for tags complex tags. They can be found in the
javax.servlet.jsp.tagext package. What your tag is implementing will depend
on what methods could potentially be called and what needs to be implemented.
TagSupport and BodyTagSupport supply default implementations of the methods
listed below.
If your Tag:
has no attributes and no body
---implement doStartTag, doEndTag, release
has attributes
Presented by Shireesh Thanneru http://thanneru.net
An Introduction to JSP Custom Tags Page 7
---implement doStartTag, doEndTag, set/getAttribute1...N
has a body with no interaction
---implement doStartTag, doEndTag, release
has a body with interaction
---implement doStartTag, doEndTag, release, doInitBody, doAfterBody
An Example Tag Handler
The Java code for the tag defined in the sample TLD file would look like
package com.tsg.taglibs;
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;
/**
* Setter for the attribute name as defined in the tld file for this tag
*/
public void setName(String value) {
name = value;
}
/**
* Getter for the attribute name as defined in the tld file for this tag
*/
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();
if(name != null)
out.println("Hello " + name);
else
out.println("Hello World ");
} catch (IOException ex) {
throw new JspTagException("I/O Exception " + e.getMessage());
}
// Must return SKIP_BODY because we are not supporting a body for this tag.
return SKIP_BODY;
}
}
Presented by Shireesh Thanneru http://thanneru.net
An Introduction to JSP Custom Tags Page 8
The JSP with custom tags
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="/tut" prefix="sample" %>
<html>
<head>
<title>Hello World Demo</title>
</head>
<body>
<hr/>
<sample:hello name="<%= request.getParameter(\"name\")
%>"/>
<hr/>
</body>
</html>
The HTML source output from this JSP would look like:
<html>
<head>
<title>Hello World Demo</title>
</head>
<body>
<hr/>
Hello Don Leflar
<hr/>
</body>
</html>
You can see how the tag was evaluated and the contents of the tag inserted into the
output stream.
Presented by Shireesh Thanneru http://thanneru.net
An Introduction to JSP Custom Tags Page 9
Section 3. How Tag Libraries work
Page Translation
What happens during a JSP Page(with custom tags) Translation?
Page Execution
What happens during a JSP Page(with custom tags) execution?
Tag Life Cycle
The Life Cycle of a Simple Tag
Presented by Shireesh Thanneru http://thanneru.net
An Introduction to JSP Custom Tags Page 10
BodyTag Life Cycle
The Life Cycle of a Body Tag
Presented by Shireesh Thanneru http://thanneru.net
An Introduction to JSP Custom Tags Page 11
Section 4. Example: HTML Encoding
A Custom Tag for HTML Encoding
package com.tsg.taglibs;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.*;
import javax.servlet.jsp.*;
import java.io.IOException;
import java.util.Hashtable;
public class HTMLEncodeTag extends BodyTagSupport {
static private Hashtable translations = makeTranslationTable();
static private Hashtable makeTranslationTable () {
Hashtable table = new Hashtable();
table.put(new Character('<'), "&lt;");
table.put(new Character('>'), "&gt;");
table.put(new Character('&'), "&amp;");
table.put(new Character('\n'), "<BR/>");
table.put(new Character(' '), "&nbsp;");
return table;
}
static public String getTranslation (char c) {
return (String) translations.get(new Character(c));
}
public int doAfterBody () throws JspException {
BodyContent body = getBodyContent();
String orig = body.getString();
body.clearBody();
int length = orig.length();
StringBuffer result = new StringBuffer(Math.round(length * 1.1f));
for (int i = 0; i < length; ++i) {
char c = orig.charAt(i);
String translation = getTranslation(c);
if (translation == null) {
result.append(c);
} else {
result.append(translation);
}
}
try {
getPreviousOut().print(result.toString());
}
catch (IOException e) {
throw new JspException("unexpected IO error");
}
return SKIP_BODY;
}
}
The TLD and the web.xml file
The TLD
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE taglib
PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
"http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
Presented by Shireesh Thanneru http://thanneru.net
An Introduction to JSP Custom Tags Page 12
<taglib>
<tlibversion>1.0</tlibversion>
<jspversion>1.1</jspversion>
<shortname>HTMLFormat</shortname>
<uri>HTMLFormat</uri>
<info>HTML Formatting Tags </info>
<tag>
<name>HTMLEncode</name>
<tagclass>com.tsg.taglibs.HTMLEncodeTag</tagclass>
<info> Encode HTML</info>
</tag>
</taglib>
The web.xml file
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
"http://java.sun.com/j2ee/dtds/web-app_2.2.dtd">
<web-app>
<taglib>
<taglib-uri>
HTMLFormat
</taglib-uri>
<taglib-location>
/WEB-INF/HTML_Format_Tags_1_4.tld
</taglib-location>
</taglib>
</web-app>
Using the HTML Encode Tag
The JSP
<%@ taglib uri="HTMLFormat" prefix="HTMLFormat" %>
<html>
<head>
</head>
<body>
<pre>
<HTMLFormat:HTMLEncode>
< Sample HTML Encode Tag Output >
</HTMLFormat:HTMLEncode>
</pre>
</body>
</html>
Presented by Shireesh Thanneru http://thanneru.net
An Introduction to JSP Custom Tags Page 13
The Output
The input:
< Sample HTML Encode Tag Output >
will be output as:
&lt; Sample HTML Encode Tag Output &gt;
and hence, will be displayed as:
< Sample HTML Encode Tag Output >
Presented by Shireesh Thanneru http://thanneru.net
An Introduction to JSP Custom Tags Page 14
Section 5. Example: Simple Iteration
A Custom Tag for Simple Iteration
package com.tsg.taglibs;
import java.io.IOException;
import java.util.Iterator;
import java.util.Collection;
import javax.servlet.*;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
/**
* This class is a custom action for looping through the elements
* of an Iterator. The action body is evaluated once for each element.
*/
public class LoopTag extends BodyTagSupport {
// Property variables
private String name;
private String loopId;
private String className;
// Iterator, that is used for iteration
private Iterator iter;
/**
* Sets the name attribute, i.e. the name of the variable holding
* a reference to the iterator.
*
* @param name the bean variable name
*/
public void setName(String name) {
this.name = name;
}
/**
* Sets the loopId attribute, i.e. the name of the variable to
* hold the element reference in the body.
*
* @param property the property name
*/
public void setLoopId(String loopId) {
this.loopId = loopId;
}
/**
* Sets the class attribute, i.e. the name of the class for the
* multi-value property elements.
*
* @param class the element class name
*/
public void setClassName(String className) {
this.className = className;
}
/**
* Extracts the Iterator and makes the first element available to
* the body in a variable with the name specified by the loopId
* attribute.
*/
public int doStartTag() throws JspException {
// Extract the Iterator object
Object obj = pageContext.findAttribute(name);
if (obj == null) {
throw new JspException("Variable " + name + " not found");
}
if (Collection.class.isAssignableFrom(obj.getClass())) {
Presented by Shireesh Thanneru http://thanneru.net
An Introduction to JSP Custom Tags Page 15
Collection col = (Collection) obj;
iter = (Iterator) col.iterator();
}
// Set the first loop value, if any
if (iter != null && iter.hasNext()) {
Object currValue = iter.next();
pageContext.setAttribute(loopId, currValue);
return EVAL_BODY_TAG;
}
else {
return SKIP_BODY;
}
}
/**
* Makes the next element available to the body in a variable
* with the name specified by the loopId attribute, or returns
* SKIP_BODY if all elements have been processed.
*/
public int doAfterBody() throws JspException {
try {
BodyContent bc = getBodyContent();
getPreviousOut().print(bc.getString());
bc.clearBody();
}
catch (IOException e) {}
if(iter.hasNext()) {
Object currValue = iter.next();
pageContext.setAttribute(loopId, currValue);
return EVAL_BODY_TAG;
}
else {
return SKIP_BODY;
}
}
/**
* Releases all instance variables.
*/
public void release() {
name = null;
loopId = null;
className = null;
iter = null;
super.release();
}
}
The TEI
package com.tsg.taglibs;
import javax.servlet.jsp.tagext.*;
/**
* This class provides information about the variable created by the
* LoopTag to the JSP container at translation-time.
*/
public class LoopTagExtraInfo extends TagExtraInfo {
public VariableInfo[] getVariableInfo(TagData data) {
return new VariableInfo[]
{
new VariableInfo(data.getAttributeString("loopId"),
data.getAttributeString("className"),
true,
Presented by Shireesh Thanneru http://thanneru.net
An Introduction to JSP Custom Tags Page 16
VariableInfo.NESTED)
};
}
}
The TLD
<taglib>
<shortname> tut </shortname>
<uri> /tut </uri>
<info>
A simple tab library for TSG utilities.
</info>
<tag>
<name>loop</name>
<tagclass>com.tsg.taglibs.LoopTag</tagclass>
<teiclass>com.tsg.taglibs.LoopTagExtraInfo</teiclass>
<bodycontent>JSP</bodycontent>
<info>
Evaluates the body for each element in the Iterator
</info>
<attribute>
<name>name</name>
<required>true</required>
</attribute>
<attribute>
<name>loopId</name>
<required>true</required>
</attribute>
<attribute>
<name>className</name>
<required>true</required>
</attribute>
</tag>
</taglib>
The JSP and the output
The JSP
<%@ taglib uri="/tut" prefix="tut" %>
<html>
<body>
<%
java.util.ArrayList al = new java.util.ArrayList();
al.add("VWR");
al.add("AD");
al.add("Ben Franklin");
al.add("Wyeth");
al.add("Hawthorn");
Presented by Shireesh Thanneru http://thanneru.net
An Introduction to JSP Custom Tags Page 17
pageContext.setAttribute("al", al);
%>
List of Clients:
<ul>
<tut:loop name="al" loopId="clientName"
className="java.lang.String">
<li> <%= clientName %> </li>
</tut:loop>
</ul>
</body>
</html>
The output
<html>
<body>
List of Clients:
<ul>
<li> VWR </li>
<li> AD </li>
<li> Ben Franklin </li>
<li> Wyeth </li>
<li> Hawthorn </li>
</ul>
</body>
</html>
Colophon
This tutorial was written entirely in XML. IBM developerWorks Toot-O-Matic tutorial generator
was used to translate this XML file into multiple formats. The Toot-O-Matic tool is an XSLT
stylesheet and several XSLT extension functions that convert an XML file into a number of
HTML pages, a zip file, JPEG heading graphics, and two PDF files. The ability to generate
multiple text and binary formats from a single source file illustrates the power and flexibility of
XML. I customized this tool by editing several XSLT style-sheets to suit my needs and to give
it a Sycamore look and feel.
Presented by Shireesh Thanneru http://thanneru.net
An Introduction to JSP Custom Tags Page 18

Das könnte Ihnen auch gefallen