The JS JSP standard Tag library (JSP Standard tag Library,jstl) is a set of custom tag libraries that implement common functions commonly used in WEB applications, including iterative and conditional judgment, data management formatting, XML operations, and database access. In the first article on DeveloperWorks's new series, software engineer Mark Kolb showed you how to use the JSTL tag to avoid scripting elements in JSP pages. You will also learn how to simplify software maintenance by removing source code from the presentation layer. Finally, you'll learn about JSTL's simplified expression language, which allows you to specify dynamic property values for a JSTL operation without having to use a full-featured programming language.
JavaServer Pages (JSP) is the standard presentation layer technology for Java EE platform. JSP technology provides scripting elements and operations for performing calculations that dynamically generate page content. Scripting elements allow you to include program source code in a JSP page that can be executed when the page is rendered in response to a user request. Operations encapsulate calculation operations in markup that is much like an HTML or XML tag, and the template text for JSP pages typically contains these tags. The JSP specification defines only a few operations as standards, but starting with JSP 1.1, developers have been able to create their own operations in the form of custom tag libraries.
The JSP standard Tag library (JSTL) is a set of JSP 1.2 custom tag libraries that implement the basic functionality commonly used by server-side Java applications. By providing a standard implementation for typical presentation-layer tasks such as data formatting and iteration or conditional content, JSTL enables JSP authors to focus on application-specific development requirements rather than "reinvent the stick" for these generic operations.
Of course, you can use JSP scripting elements (scriptlet, expressions, and declarations) to implement such tasks. For example, you can use three scriptlet to implement conditional content, and the three scriptlet are highlighted in Listing 1. However, because scripting elements rely on embedding program source code (usually Java code) in a page, the complexity of the software maintenance task is greatly increased for JSP pages that use these scripting elements. For example, the scriptlet example in Listing 1 strictly relies on proper matching of curly braces. If you inadvertently introduce a syntax error, nested other scriptlet in the conditional content can cause serious damage, and it can be difficult to make the error message meaningful when the JSP container compiles the page.
Listing 1. Implement conditional content through Scriptlet <% if (user.getrole () = = "Member") {%>
<p>welcome, member!</p><%} else {%> <p>welcome, guest!</p><%}%>
|
Fixing this type of problem often requires considerable programming experience. Although the JSP is usually developed and maintained by designers who are very proficient in page layout and graphic design, the scripting elements on the same page have problems that require programmer intervention. This situation shares the responsibility of the code in a single file to multiple people, making it a cumbersome task to develop, debug, and enhance such JSP pages. By wrapping common functions into a standard collection of custom tag libraries, JSTL enables JSP authors to reduce the need for scripting elements, even without them, and to avoid associated maintenance costs.
JSTL 1.0
JSTL 1.0, published in June 2002, consists of four custom tag libraries (core, format, XML, and SQL) and a pair of universal Tag Library validators (SCRIPTFREETLV and PERMITTEDTAGLIBSTLV). The core tag library provides custom operations to manage data by restricting scoped variables, and to perform iterative and conditional operations on page content. It also provides tags for generating and manipulating URLs. As the name implies, the format tag library defines the operations that are used to format data, especially numbers and dates. It also supports the internationalization of JSP pages using a localized resource bundle. The XML library contains tags that manipulate the data represented through XML, and the SQL Library defines the operations that are used to query the relational database.
The two JSTL Tag Library Validator allows developers to enforce coding standards in their JSP applications. You can configure the SCRIPTFREETLV validator to disable various types of JSP script element-scriptlet, expressions, and declarations in the JSP page. Similarly, the PERMITTEDTAGLIBSTLV validator can be used to restrict the set of custom tag libraries (including JSTL tag libraries) that may be accessed by the application's JSP pages.
Although JSTL will eventually become a required component of the Java EE platform, only a handful of application servers currently include it. The JSTL 1.0 reference implementation can be obtained as part of the Jakarta Taglibs project (see Resources) of the Apache Software Foundation (Apache Software Foundation). The custom tag libraries in this reference implementation can be merged into any server that supports the JSP 1.2 and Servlet 2.3 specification to add support for JSTL.
Expression Language
In JSP 1.2, you can use a static string or an expression (if allowed) to specify the properties of the JSP operation. For example, in Listing 2, a static value is specified for the name and property properties of a <jsp:setProperty> operation, and its Value property is specified with an expression. The effect of this action is to assign the current value of the request parameter to the named Bean attribute. An expression used in this form is called the request-time property value (Request-time attribute value), which is the only mechanism built into the JSP specification to dynamically specify the property value.
Listing 2. JSP action for property values when merging requests
<jsp:setproperty name= "user" property= "timezonepref" value= ' <%= request.getparameter ("timezone")%> '/ >
|
Because property values are specified with expressions at request time, they often have the same software maintenance problems as other scripting elements. Therefore, the JSTL custom tag supports another mechanism for specifying dynamic property values. You can use a simplified expression language (EL) instead of a complete JSP expression to specify the property value of the JSTL operation. EL provides identifiers, accessors, and operators for retrieving and manipulating data residing in a JSP container. EL is based to some extent on EcmaScript (see Resources) and XML Path Language (XML Paths Language,xpath), so page designers and programmers should be familiar with its syntax. EL is good at finding objects and their attributes, and then performing simple operations on them; it's not a programming language, not even a scripting language. However, when used with the JSTL tag, it can use simple and convenient symbols to represent complex behavior. The format of the EL expression is this: in the dollar sign ({}), as shown in Listing 3.
Listing 3. Describes the JSTL operation of the EL expression delimiter
<c:out value= "${user.firstname}"/>
In addition, you can combine multiple expressions with static text to construct dynamic property values through string literals, as shown in Listing 4. An individual expression consists of identifiers, accessors, literals, and operators. Identifiers are used to refer to data objects stored in the datacenter. El has 11 reserved identifiers, corresponding to 11 EL implicit objects. Assume that all other identifiers refer to variables that limit the scope. An element that an accessor uses to retrieve an attribute or collection of an object. Text represents a fixed value-a number, character, String, Boolean, or null value. Operators allow you to combine and compare data and text.
Listing 4. Combine static text and multiple EL expressions to specify dynamic property values
<c:out value= "Hello ${user.firstname} ${user.lastname}"/>
Restricted scope variables
The JSP API allows data to be stored and retrieved from four different scopes within the JSP container through <jsp:useBean> operations. JSTL expands this capability by providing additional operations to specify and remove objects in these scopes. In addition, EL provides built-in support for retrieving these objects as scoped variables. In particular, any identifier that appears in an El expression but does not correspond to any El implicit object is automatically assumed to refer to an object that is stored in one of the four JSP scopes, four scopes:
·Page Scopes
·Request Scope
·Session scope
·Application Scopes
As you may recall, objects stored in the scope of the page cannot be retrieved until a page is processed for a particular request. If the object is stored in the request scope, these objects can be retrieved during processing of all pages participating in the processing of a request (for example, one or more <jsp:include> or <jsp:forward> operations are encountered in the processing of a request). If the object is stored in a session scope, during an interactive session with the WEB application, it can be retrieved by any page that the user accesses (that is, until the HttpSession object to which the user is associated is not valid). Objects stored in the scope of an application can be accessed by any user from any page until the WEB application itself is unloaded (usually due to the shutdown of the JSP container).
The object is stored in the scope by mapping the string to an object in the desired scope. You can then retrieve the object from the scope by supplying the same string. Finds a string in the mapping of the scope and returns the object being mapped. In the Servlet API, this class of objects is called the properties of the corresponding scope. However, in the context of EL, the string associated with the attribute is also treated as the name of the variable, which obtains a specific value through the way the property is mapped.
In EL, an identifier that is not associated with an implicit object is considered to be a name object stored in four JSP scopes. The page scope is first checked for the existence of such identifiers, followed by the request scope, then the session scope, and finally the application scope, and then test that the name of the identifier matches the name of an object stored in the scope. The first such match is returned as the value of the EL identifier. In this way, the EL identifier can be thought of as a reference that restricts scoped variables.
On a more technical note, an identifier that is not mapped to an implicit object is evaluated with the Findattribute () method of the PageContext instance, which represents the processing of the page on which the expression is currently being processed for the request. The name of the identifier is passed to this method as a parameter, and then the method searches the four scopes for an attribute with the same name in turn. and returns the first occurrence of the found match as the value of the Findattribute () method. If such a property is not found in these four scopes, NULL is returned.
Ultimately, scoped variables are properties of four JSP scopes that have names that can be used as EL identifiers. As long as you assign alphanumeric names to variables that limit the scope, you can create them from any mechanism provided in the JSP for setting properties. This includes built-in <jsp:useBean> operations, as well as the setattribute () method defined by several classes in the Servlet API. In addition, many of the custom tags defined in the four JSTL libraries can themselves set property values that are used as scoped variables.
an Implicit object
The identifiers for the 11 EL implicit objects are listed in table 1. Do not confuse these objects with a JSP implicit object (nine altogether), with only one object being common to them.
Table 1. EL-Implicit object
Category Identifier Description
JSP PageContext PageContext instance corresponds to the processing of the current page
Scope Pagescope the Map class associated with the name and value of the page scope property
Requestscope the Map class associated with the name and value of the request scope attribute
Sessionscope the Map class associated with the name and value of the session scope property
Applicationscope the Map class associated with the name and value of an application scope property
Request parameter param the Map class that stores the primary value of the request parameter by name
Paramvalues the Map class that stores all the values of the request parameter as a String array
Request Header Header The Map class that stores the main value of the request header by name
Headervalues the Map class that stores all the values of the request headers as String arrays
The Map class that stores the cookie that is included with the request by name in the cookie cookie
Initialization parameter Initparam a Map class that stores WEB application context initialization parameters by name
Although there is only one common object (PageContext) in JSP and El Implicit objects, other JSP implicit objects can be accessed through EL. The reason is that PageContext has an attribute to access all the other eight JSP implicit objects. In fact, this is the main reason to include it in an EL implicit object.
All remaining EL implicit objects are mappings that can be used to find objects that correspond to names. The first four mappings represent the various property scopes discussed earlier. You can use them to find identifiers in specific scopes without relying on the sequential lookup process that EL uses by default.
The next four mappings are used to get the value of the request parameter and the request header. Because the HTTP protocol allows request parameters and request headers to have multiple values, they each have a pair of mappings. The first mapping in each pair returns the primary value of the request parameter or header, usually the value that happens to be specified first in the actual request. The second mapping in each pair allows retrieving all values of the parameter or header. The keys in these mappings are the names of parameters or headers, but these values are an array of String objects, each of which is a single parameter value or a header value.
The cookie implicit object provides access to the cookie name set by the request. This object maps all the cookie names associated with the request to the cookie object that represents those cookie attributes.
The last EL implicit object Initparam is a mapping that stores the names and values of initialization parameters for all contexts associated with the WEB application. Initialization parameters are specified by the Web.xml deployment descriptor file, which is located in the application's Web-inf directory.
Access Device
Because EL identifiers are parsed as implicit objects or scoped variables (implemented by attributes), it is necessary to convert them to Java objects. EL can automatically wrap and wrap the base type in its corresponding Java class (for example, you can cast int to an Integer class in the background, or vice versa), but most identifiers will be pointers to the full Java object.
As a result, access to the attributes of these objects or to their elements (in the case of an array and a collection) is generally satisfactory. For this purpose, El provides two different accessors (the dot operator (.) and the Bracket operator ([]), and also supports the operation of attributes and elements via El.
The dot operator is typically used to access the attributes of an object. For example, in the expression ${User.firstname}, use the dot operator to access the attribute named FirstName for the object referenced by the user identifier. EL uses Java bean Conventions to access object attributes, so you must define the Getter method for this attribute (usually a method named Getfirstname ()) so that the expression is evaluated correctly. When the accessed attribute itself is an object, you can apply the dot operator recursively. For example, if our fictitious user object has an address attribute that is implemented as a Java object, you can also use the dot operator to access the object's attributes. For example, the expression ${user.address.city} will return the city attribute nested by this address object.
The brackets operator is used to retrieve the elements of an array and a collection. In the case of an array and an ordered set (i.e., a set of java.util.List interfaces), place the subscript of the element to be retrieved in square brackets. For example, the expression ${Urls[3]} returns the fourth element of the array or collection referenced by the URL identifier (as in the Java language and JavaScript, the subscript in EL is zero-based).
For a collection that implements the Java.util.Map interface, the bracket operator uses the associated key to find the value stored in the map. The key is specified in square brackets, and the corresponding value is returned as the value of the expression. For example, an expression ${commands["dir"} returns the value associated with the "dir" key in the Map referenced by the commands identifier.
For both of these cases, you can allow the expression to appear in square brackets. The result of a nested expression evaluation is used as a subscript or key to retrieve the appropriate elements of the collection or array. As with the dot operator, the bracket operator can also be recursively applied. This allows EL to retrieve elements from multidimensional arrays, nested collections, or any combination of both. In addition, the dot operator and the bracket operator can interoperate. For example, if the element of an array is itself an object, you can use the bracket operator to retrieve the elements of the array and, in conjunction with the dot operator, retrieve an attribute of the element (for example, ${Urls[3].protocol}).
Assuming El serves as a simplified language for specifying dynamic property values, El Accessors have an interesting feature (unlike the Java language accessor), which is that they do not throw exceptions when applied to null. If an object that applies an EL accessor (for example, ${foo.bar} and ${foo["bar") is null, the result of the application accessor is also null. It turns out that in most cases this is a fairly useful behavior that you will soon understand.
Finally, the dot operator and the bracket operator may achieve some degree of interchange. For example, you can also use the ${user["FirstName"]} to retrieve the FirstName attributes of the user object, just as you can use ${Commands.dir} to get the value associated with the "dir" key in the commands map.
operator
El can also traverse an object hierarchy that contains application data (by limiting the scope's variables) or information about the environment (via an EL implicit object) by using identifiers and accessors. However, just accessing this data is often not sufficient to implement the presentation logic required by many JSP applications.
Finally, El also includes several operators to manipulate and compare the data accessed by El Expressions. These operators are summarized in table 2.
Table 2. EL operator
Category operators
Arithmetic operators + 、-、 *,/(or DIV) and% (or mod)
Relational operator = = (or eq),!= (or NE), <</code> (or LT), > (or GT), <= (or Le), and >= (or GE)
logical operators && (OR and), | | (OR) and! (or not)
Validation operator Empty
Arithmetic operators support the addition, subtraction, multiplication, and division of numeric values. A remainder operator is also provided. Note: Both the division and the remainder operators have alternate, unsigned names (for consistency with XPath). A sample expression demonstrating the usage of arithmetic operators is shown in Listing 5. The result of applying arithmetic operators to several EL expressions is the result of applying the arithmetic operator to the values returned by those expressions.
Listing 5. An EL expression with arithmetic operators
${item.price * (1 + taxrate[user.address.zipcode])}
|
Relational operators allow you to compare numeric or textual data. The result of the comparison is returned as a Boolean value. Logical operators allow Boolean values to be merged to return a new Boolean value. Therefore, you can apply EL logical operators to the results of nested relationships or logical operators, as shown in Listing 6.
Listing 6. An EL expression that leverages relational and logical operators
${(x >= min) && (x <= max)}
|
The last EL operator is empty, which is particularly useful for validating data. The empty operator takes a single expression as its variable (that is, ${empty input}) and returns a Boolean value that indicates whether the result of an expression evaluation is not a "null" value. An expression that evaluates to Null is considered empty, that is, a collection or array without elements. The empty operator also returns true if the argument is the result of a zero-length String evaluation.
Table 3 shows the precedence of the EL operator. As shown in listings 5 and 6, you can group expressions with parentheses over normal precedence rules.
Table 3. EL operator Precedence (from top to bottom, left to right)
[], . () unary-, not 、!、 empty *,/, Div,%, mod +, Binary-() <</code>, >, <=, >=, lt, GT, le, ge = =,!=, eq, NE & &, and | |, or
|
text
In EL expressions, numbers, strings, Boolean values, and NULL can be specified as literal values. Strings can be bounded by single or double quotes. The Boolean value is specified as True and false.
Taglib pseudo Directive
As we discussed earlier, JSTL 1.0 includes four custom tag libraries. To demonstrate the interaction between the JSTL tag and the expression language, we'll look at several tags from the JSTL core library. As with any JSP custom tag library, you must include taglib pseudo directives in any page that you want to use for this library tag. Listing 7 shows the pseudo directives for this particular library.
Listing 7. taglib pseudo directive for JSTL Core Library EL version
<%@ taglib uri= "Http://java.sun.com/jstl/core" prefix= "C"%>
|
In fact, there are two taglib pseudo directives corresponding to the JSTL core library, because EL is optional in JSTL 1.0. All four JSTL 1.0 custom tag libraries have alternate versions that specify dynamic property values using a JSP expression instead of EL. Because these fallback libraries depend on the more traditional JSP's request-time attribute values, they are called RT libraries, while those that use the expression language are called EL libraries. Developers use different taglib pseudo directives to differentiate between these two versions of each library. Listing 8 shows a pseudo directive that uses the RT version of the core library. However, since we are now discussing the focus of EL, we need these pseudo directives first.
Listing 8. taglib pseudo directive for JSTL Core Library RT version
<%@ taglib uri= "Http://java.sun.com/jstl/core_rt" prefix= "C_rt"%>
|
variable marker
The first JSTL custom tag we want to consider is <c:set> operation. As has been explained, limiting scoped variables to play a key role in JSTL,<c:set> operations provide a mechanism based on markup to create and set limits on scoped variables. The syntax for the operation is shown in Listing 9, where the var attribute specifies the name of the variable that restricts the scope, and the Scope property indicates which scope the variable resides in, and the Value property specifies the values that are assigned to the variable. If the specified variable already exists, simply assigns the specified value to it. If it does not, create a new scoped variable and initialize the variable with that value.
Listing 9. Syntax for <c:set> operations
<c:set var= "name" scope= "scope" value= "expression"/>
|
The scope property is optional and the default value is page.
The two examples of <c:set> are shown in Listing 10. In the first example, the session scope variable is set to a String value. In the second example, you set the value by using an expression that assigns a variable named square in the page scope to the square of the value of the request parameter named X.
Listing 10. <c:set> Operations Example
<c:set var= "TimeZone" scope= "session" Value= "CST"/><c:set var= "Square" value= "${param[' x '] * param[' x ']}" >
|
You can also specify the value of scoped variables as the body content of the <c:set> action, rather than using attributes. With this approach, you can rewrite the first example in Listing 10, as shown in Listing 11. Also, as we can see immediately, the body content of the,<c:set> tag itself can use custom tags. All content generated within the <c:set> body is assigned as a String value to the specified variable.
Listing 11. Value of <c:set> action specified through body content
<c:set var= "TimeZone" scope= "session" >CST</c:set>
|
The JSTL Core Library contains a second tag-<c:remove> for managing variables that limit scope. As the name suggests, the,<c:remove> action is used to delete a scoped variable, and it gets two properties. The var attribute specifies the name of the variable to be deleted, and the scope property is optional, which indicates which scope the variable is to be deleted from, and the default is page, as shown in Listing 12.
Listing 12. <c:remove> Operations Example
<c:remove var= "TimeZone" scope= "session"/>
|
Output
Although <c:set> operations allow expression results to be assigned to scoped variables, developers typically want to display only the value of an expression without storing it. JSTL <c:out> Custom Tags assume this task, and its syntax is shown in Listing 13. The tag evaluates the expression specified by its Value property, and then prints the result. If an optional property default is specified,,<c:out> will print its value if the result of evaluating an expression on the Value property is null or empty String.
Listing 13. Syntax for <c:out> operations
<c:out value= "expression" default= "expression" escapexml= "Boolean"/>
|
The EscapeXML property is also optional. It controls whether characters such as "<", ">", and "&" (which have special meaning in HTML and XML) should be escaped when using the <c:out> tag output. If you set EscapeXML to True, these characters are automatically converted to the corresponding XML entities (the characters mentioned here are converted to <, > and & respectively).
For example, suppose you have a session scope variable named user, which is an instance of a class that defines two attributes for the User: username and company. Whenever a user accesses a site, the object is automatically assigned to the session, but the two attributes are not set until the user actually logs on. Assuming this scenario, consider the JSP fragment in Listing 14. After the user logs in, this fragment will display the word "Hello" followed by his/her username and an exclamation point. However, before the user logs on, the content generated by this fragment is the phrase "Hello guest!". In this case, because the username feature has yet to be initialized, the <c:out> tag will instead print the value of the default property (that is, the string "Guest").
Listing 14. Examples of <c:out> operations with default content Hello
<c:out value= "${user.username}" default== "Guest"/>!
|
Next, consider listing 15, which uses the EscapeXML property of the <c:out> tag. If you have set the company attribute to the Java String value "Flynn & Sons" In this case, the action will actually generate the Flynn & Sons. If this operation is part of a JSP page that generates HTML or XML content, the "&" symbol in the middle of the string may eventually be interpreted as an HTML or XML control character, thereby preventing the display or parsing of the content. However, if you set the EscapeXML property value to True, the generated content will be Flynn & Sons. The browser or parser does not have a problem with this content as it is interpreted. Assuming that HTML and XML are the most common content types in a JSP application, it is not surprising that the default value of the EscapeXML property is true.
Listing 15. Disabling the escaped <c:out> operations sample
<c:out value= "${user.company}" escapexml== "false"/>
|
set variables with default values
In addition to simplifying the display of dynamic data, the ability to specify default values when you pass <c:set> Set variable values is also useful for,<c:out>. As shown in Listing 11, the values that are assigned to scoped variables can be specified as the body contents of the <c:set> tag, or by their value properties. By nesting <c:out> operations in the body content of the <c:set> tag, variable assignment can take advantage of its default value capability.
This approach is illustrated in Listing 16. The outer <c:set> tag behavior is simple: it sets the value of the session scope timezone variable based on its principal content. In this case, however, the body content is generated through the <c:out> operation. The Value property of this nested operation is the expression ${cookie[' Tzpref '].value}, which attempts to return a cookie value named Tzpref through a cookie-implicit object. (The cookie-implicit object maps the cookie name to the corresponding cookie instance, which means that the actual data stored in the cookie must be retrieved by using the dot operator with the object's value attribute.) )
Listing 16. Merging <c:set> and <c:out> to provide default variable values
<c:set var= "TimeZone" scope== "session" > <c:out value= "${cookie[' Tzpref '].value}" default== "CST"/> </c:set>
|
However, consider the following scenario where the user is the first Web application to attempt to use this piece of code. As a result, a cookie named Tzpref is not provided in the request. This means that a lookup using an implicit object returns null, in which case the entire expression returns NULL. Because the result of evaluating the Value property of the <c:out> tag is null, the <c:out> tag will instead output the result of evaluating its default property. Here is the string CST. Therefore, the actual result is to set the scoped variable to the time zone stored in the user's Tzpref cookie, or, if not, use the default time zone CST. TimeZone
EL and JSP 2.0
Currently, the expression language can only be used to specify dynamic property values in JSTL custom tags. However, an extension of the JSTL 1.0 expression language has been proposed, which will be included in JSP 2.0, and a final review is currently underway. This extension will allow developers to use EL with their own custom tags. Page authors will be able to use EL expressions wherever they are currently allowed to use JSP expressions, such as inserting dynamic values into template text: <p>your preferred time zone is ${timezone}</p>.
This JSP 2.0 feature (like JSTL itself) will support page authors to further reduce reliance on JSP scripting elements, thereby improving the maintainability of JSP applications.
Concluding remarks
EL (combined with the operations provided by the four JSTL custom tag libraries) allows the page author to implement the presentation layer logic without using script elements. For example, compare the JSP code in Listing 1 at the beginning of this article with the same functionality that is implemented through the JSTL shown in Listing 17. (The remaining tags in the JSTL core library, including <c:choose> and their child tags, will be discussed in the next article in this series.) Although the conditional logic is clearly enforced, there is no Java language source code in the JSTL version, and the relationship between tags (especially about nesting requirements) should be familiar to anyone who is proficient in HTML syntax.
Listing 17. Merging <c:set> and <c:out> to provide default variable values
<c:choose><c:when test= "${user.role = = ' member '}" > <p>welcome, member!</p> </c: When><c:otherwise> <p>welcome, guest!</p> </c:otherwise></c:choose>
|
By providing a standard implementation of the most common features of most WEB applications, JSTL helps accelerate the development cycle. Combined with EL, JSTL can write code without requiring a presentation-tier program, which greatly simplifies the maintenance of JSP applications.
reference materials
The Sun's JSP Standard Tag Library home page is a good starting point for more information about JSTL.
The JSTL 1.0 specification is the final authoritative text for the EL and four JSTL tag libraries.
the Jakarta Taglibs project is the origin of the JSTL 1.0 reference implementation.
The JSTL in Action (Manning Publications co.,2002 year) of Shawn Bayern provides a wonderful exposition of all JSTL functions, and the author is the leader of this reference implementation.
David Geary, a popular author of Java Technology, also wrote a book about JSTL, the title of Core JSTL.
jsptags.com is a directory of JSP technology resources, particularly focused on custom tag libraries.
a discussion of JSTL is included in Sun's Java Web Services Tutorial.
the Using JSPs and custom tags within visualage for Java and WebSphere Studio (WebSphere Developer Garden) is a wbonline practical paper that demonstrates SE Use of Rvlet, JSP, and custom tag libraries.
Learn everything about custom tag libraries by Jeff Wilson's wonderful article, "Using custom tags to control JSP pages" (developerworks,2002 January).
Noel Bergman's article "JSP Tag Library: Designed for Better usability" (developerworks,2001 year December) shows you how declarative markup can help improve the usability of JSP pages.
For more information about EcmaScript, see Sing Li's "QuickStart Java Programming" (developerworks,2001 July).
up to hundreds of Java technical references can be found in the DeveloperWorks Java technology area.
about the author
Mark Kolb is a software engineer working in Austin, Texas. He often speaks in the industry on server-side Java themes and co-authored the Web Development with JavaServer Pages, the second edition of the book. You can contact Mark through mak@taglib.com.