SoFunction
Updated on 2025-04-07

JSP Template Application Guide (Part 2)

Execution template
The templates discussed here will be executed under three custom tags:

Template: insert

Template: put

Template: get

The insert tag contains a template, but before including, the put tag stores some information—name, URI, and Boolean values ​​(used to specify whether the content is included or displayed directly)—about what the template contains. The specified content is included (or displayed) in the template:get, and this information will be accessed.

template:put stores the bean in the request area (but not directly stored), because if the two templates use the same content name, a nested template will overwrite the contents in the encapsulation template.

To ensure that each template can only access its own information, template:insert retains a hashtable stack. Each insert starts the tag to create a hashtable and put it on the stack. The encapsulated put tags create beans and save them to the recently created hashtable. Then, the bean in the hashtable is accessed in the get tag contained in the included template. Figure 4 shows how the stack is preserved.


Figure 4. Store template parameters in the request area Click to enlarge (24 KB)

In Figure 4, each template accesses the correct footer, and footer_2.html. If the bean is stored directly in the request area, step 5 in Figure 4 will overwrite the footer bean specified in step 2.

Template tag execution
Next we will analyze the execution of three template tags: insert, put, and get. Let's start with Figure 5. This chart illustrates the order in which insert and put tag events are executed when a template is used.


Figure 5. Put and insert tag execution order Click to enlarge (24 KB)

If a template stack already does not exist, the insert start tag creates one and places it in the request area. A hashtable is then created and placed on the stack.

Each put start tag creates a PageParameter bean and stored in a hashtable created by the encapsulated insert tag.

The Insert end tag contains this template. This template uses the get tag to access beans created by the put tag. After the template is processed, the hashtable created by the insert starts the tag is cleared from the stack.

Figure 6 shows the sequence chart of template:get.


Figure 6. Sequence chart of get tags Click to enlarge (11 KB)

Template tag list
Tag handler is simple. In the example, the Insert tag class - tag handler is listed.

Example.

;

import ;

import ;

import ;

import ;

import ;

public class InserttagextendstagSupport {

private Stringtemplate;

private Stack stack;

// setter method fortemplate property

public void setTemplate(Stringtemplate) {

=template;

}

public int doStartTag() throws JspException {

stack = getStack(); // obtain a reference to thetemplate stack

(new Hashtable()); // push new hashtable onto stack

return EVAL_BODY_INCLUDE; // pass tagbody through unchanged

}

public int doEndTag() throws JspException {

try {

(template); // includetemplate

}

catch(Exception ex) { // IOException or ServletException

throw new JspException(()); // recast exception

}

(); // pop hashtable off stack

return EVAL_PAGE; // evaluate the rest of the page after the tag

}

// taghandlers should always implement release() because

// handlers can be reused by the JSP container

public void release() {

template = null;

stack = null;

}

public Stack getStack() {

// try to get stack from request scope

Stack s = (Stack) attribute(

"template-stack",

PageContext.REQUEST_SCOPE);

// if the stack's not present, create a new one and

// put it into request scope

if(s == null) {

s = new Stack();

attribute ("template-stack", s,

PageContext.REQUEST_SCOPE);

}

return s;

}

}

Example List Put tag class and tag handler:

Example.

;

import ;

import ;

import ;

import ;

import ;

public class PuttagextendstagSupport {

private String name, content, direct="false";

// setter methods for Put tag attributes

public void setName(String s) { name = s; }

public void setContent(String s) {content = s; }

public void setDirect(String s) { direct = s; }

public int doStartTag() throws JspException {

// obtain a reference to enclosing insert tag

Inserttagparent = (InsertTag)getAncestor(

"");

// puttags must be enclosed in an insert tag

if(parent == null)

throw new JspException("(): " +

"No Inserttagancestor");

// gettemplate stack from insert tag

Stacktemplate_stack = ();

//template stack should never be null

if(template_stack == null)

throw new JspException("PutTag: notemplate stack");

// peek at hashtable on the stack

Hashtable params = (Hashtable)template_stack.peek();

// hashtable should never be null either

if(params == null)

throw new JspException("PutTag: no hashtable");

// put a new PageParameter in the hashtable

(name, new PageParameter(content, direct));

return SKIP_BODY; // not interested in tagbody, if present

}

// taghandlers should always implement release() because

// handlers can be reused by the JSP container

public void release() {

name = content = direct = null;

}

// convenience method for finding ancestor names with

// a specific class name

privatetagSupport getAncestor(String className)

throws JspException {

Class klass = null; // can't name variable "class"

try {

klass = (className);

}

catch(ClassNotFoundException ex) {

throw new JspException(());

}

return (TagSupport)findAncestorWithClass(this, klass);

}

}

A PageParameter bean is created – listed in the example – and then stored in the request area.

Example.

package ;

public class PageParameter {

private String content, direct;

public void setContent(String s) {content = s; }

public void setDirect(String s) { direct = s; }

public String getContent() { return content;}

public boolean isDirect() { return (direct).booleanValue(); }

public PageParameter(String content, String direct) {

= content;

= direct;

}

}

PageParameter will be used as a simple placeholder. Let's take a look at the Gettag class and tag handler in the example:

Example.

;

import ;

import ;

import ;

import ;

import ;

import ;

public class GettagextendstagSupport {

private String name;

// setter method for name attribute

public void setName(String name) {

= name;

}

public int doStartTag() throws JspException {

// obtain reference totemplate stack

Stack stack = (Stack) attribute (

"template-stack", PageContext.REQUEST_SCOPE);

// stack should not be null

if(stack == null)

throw new JspException("(): " +

"NO STACK");

// peek at hashtable

Hashtable params = (Hashtable)();

// hashtable should not be null

if(params == null)

throw new JspException("(): " +

"NO HASHTABLE");

// get page parameter from hashtable

PageParameter param = (PageParameter)(name);

if(param != null) {

String content = ();

if(()) {

// print content if direct attribute is true

try {

().print(content);

}

catch( ex) {

throw new JspException(());

}

}

else {

// include content if direct attribute is false

try {

().flush();

(content);

}

catch(Exception ex) {

throw new JspException(());

}

}

}

return SKIP_BODY; // not interested in tagbody, if present

}

// taghandlers should always implement release() because

// handlers can be reused by the JSP container

public void release() {

name = null;

}

}

The page parameter bean is returned from the request area and the content and direct properties are obtained from the bean. The content can then be selected based on the direct attribute value whether to be included or displayed.

in conclusion
Template is a simple and very useful concept. The encapsulation layout of the template can minimize the impact of layout changes. Moreover, templates can distinguish different contents according to different users, and they can also be nested into other templates and JSP pages.

<Full text end>