| Contents | Prev | Next |
|
The template is a JSP page, with place holders for the parts that need to change with each screen. Each of these place holders is referred to as a parameter of the template. For example, a simple template could include a title parameter for the top of the generated screen and a body parameter to refer to a JSP page for the custom content of the screen.
Once you have a template, you can generate different presentation screens from it simply by passing it different parameters.
main.jsp, is shown below. The first part of the page uses a set of nested tags-definition, screen, and parameter-to define a table of screen definitions for an application and select a specific definition based on the request attribute selectedScreen.
The template is instantiated by the<%@ taglib uri="/tlt" prefix="tlt" %> <tlt:definition name="tutorial" screen="<%= (String)request. getAttribute(\"selectedScreen\") %>"> <tlt:screen id="/home"> <tlt:parameter parameter="title" value="Home Page" direct="true"/> <tlt:parameter parameter="banner" value="/banner.jsp" direct="false"/> <tlt:parameter parameter="body" value="/home.jsp" direct="false"/> </tlt:screen> <tlt:screen id="/first"> <tlt:parameter parameter="title" value="First Page" direct="true"/> ... <tlt:screen id="/second"> ... </tlt:definition> The second part of the page uses theinserttag to insert parameters from the selected definition into the application screen. <html> <head> <title> <tlt:insert definition="tutorial" parameter="title"/> </title> </head> <body bgcolor="white"> <tlt:insert definition="tutorial" parameter="banner"/> <tlt:insert definition="tutorial" parameter="body"/> </body> </html>
Dispatcher servlet. This servlet first gets requested screen and stores as an attribute of the request. This is necessary because when the request is forwarded to main.jsp, the request URL info no longer reflects the original request (/home/example/*.jsp), but instead reflects the path (/template/main.jsp) of the forwarded page. Finally the servlet dispatches the request to main.jsp:
public class Dispatcher extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException {
request.setAttribute("selectedScreen",
request.getPathInfo());
try {
getServletConfig().
getServletContext().getRequestDispatcher(
"/main.jsp").forward(request, response);
} catch(Exception e) {
e.printStackTrace();
}
}
}
The following figures show the home and first pages of the application:
DefinitionTag, ScreenTag, ParameterTag, and InsertTag. These tag handlers demonstrate the use of cooperating tags. DefinitionTag, ScreenTag, and ParameterTag comprise a set of nested tags handlers in which private objects are shared between parent and child tags. DefinitionTag creates a named object called definition that is used by InsertTag.
In doStartTag, DefinitionTag creates a private object that contains a hashtable of screen definitions. A screen definition consists of a screen identifier and a set of parameters associated with the screen. The table of screen definitions is filled in by ScreenTag and ParameterTag from text provided as attributes to these tags. Table 6 shows the contents of the screen definitions hashtable for the JSP page discussed in the previous section.
|
Screen ID
|
Title
|
Banner
|
Body
|
|
|
Home Page |
|
|
|
|
First Page |
|
|
|
|
Second Page |
|
|
In doEndTag, DefinitionTag creates a public object of class Definition, selects a screen definition based on the URL passed in the request, and uses the definition to initialize the Definition. If the URL passed in the request is /home, the Definition contains the items from the first row of Table 6:
|
Title
|
Banner
|
Body
|
|
Home Page |
|
|
public int doStartTag() {
Hashtable screens = null;
try {
// look for the screens object or create if it does not exist
screens = (Hashtable) getValue("screens");
if (screens == null)
setValue("screens", new Hashtable());
else
...
} catch (Exception e) {
...
}
return EVAL_BODY_INCLUDE;
}
public int doEndTag()throws JspTagException {
try {
Definition definition = new Definition();
Hashtable screens = null;
ArrayList params = null;
TagSupport screen = null;
if (getValue("screens") != null)
screens = (Hashtable) getValue("screens");
if (screens != null)
params = (ArrayList) screens.get(screenId);
else
...
if (params == null)
...
Iterator ir = null;
if (params != null)
ir = params.iterator();
while ((ir != null) && ir.hasNext())
definition.setParam((Parameter) ir.next());
// put the definition in the page context
pageContext.setAttribute(
definitionName, definition);
} catch (Exception ex) {
ex.printStackTrace();
}
return EVAL_PAGE;
}
InsertTag uses the Definition object to insert parameters of the screen definition into the response. First it retrieves the definition object from the page context. The isDirect parameter attribute determines whether the parameter value is directly inserted into the response or treated as the name of a JSP file which is dynamically included into the response.
The definition for the URL /home is shown below. The definition specifies that the value of the Title parameter should be inserted directly into the output stream, but the values of Banner and Body should be dynamically included.
|
Parameter Name
|
title |
banner |
body |
|
Parameter Value
|
Home Page |
|
|
|
IsDirect
|
true |
false |
false |
public int doStartTag() {
// get the definition from the page context
try {
definition = (Definition) pageContext.
getAttribute(definitionName);
} catch (NullPointerException e) {
...
}
// get the parameter
if (parameterName != null && definition != null)
parameter = (Parameter)definition.
getParam(parameterName);
if (parameter != null)
directInclude = parameter.isDirect();
return SKIP_BODY;
}
public int doEndTag()throws JspTagException {
// flush data
try {
pageContext.getOut().flush();
} catch (Exception e) {
...
}
try {
// if parameter is direct, print to out
if (directInclude && parameter != null)
pageContext.getOut().print(parameter.getValue());
// if parameter is indirect,
// include results of dispatching to page
else {
if ((parameter != null) &&
(parameter.getValue() != null))
pageContext.getRequest().
getRequestDispatcher(
parameter.getValue()).include(
pageContext.getRequest(),
pageContext.getResponse());
}
} catch (Exception ex) {
ex.printStackTrace();
}
return EVAL_PAGE;
}
Dispatcher servlet is used to forward requests to the application template. The servlet-mapping element in the Web application deployment descriptor maps all URL patterns of the form /example/* to the dispatcher servlet. The servlet element then maps the dispatcher servlet to an instance of the Dispatcher class. The taglib element maps the logical name /tlt to the absolute location of the tag library descriptor. This allows a page author to use the logical name in the taglib page directive.
<servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/example/*</url-pattern> </servlet-mapping> <servlet-name>dispatcher</servlet-name> <servlet-class>Dispatcher</servlet-class> </servlet> <taglib> <taglib-uri>/tlt</taglib-uri> <taglib-location>/WEB-INF/taglib.tld</taglib-location> </taglib>