📄 jsptags7.html
字号:
<a name="wp90593"> </a><p class="pBody">When you develop a tag handler you are responsible for creating and setting the object referenced by the variable into a context accessible from the page. You do this by using the JspContext().setAttribute(name, value) or <code class="cCode">JspContext.setAttribute(name,</code> <code class="cCode">value,</code> <code class="cCode">scope)</code> method. You retrieve the page context with the <code class="cCode">getJspContext</code> method of <code class="cCode">SimpleTag</code>.</p><a name="wp90594"> </a><p class="pBody">Typically, an attribute passed to the custom tag specifies the name of the variable and the value of the variable is dependent on another attribute. For example, the <code class="cCode">iterator</code> tag retrieves the name of the variable from the <code class="cCode">var</code> attribute and determines the value of the variable from a computation performed on the <code class="cCode">group</code> attribute.</p><div class="pPreformattedRelative"><pre class="pPreformattedRelative">public void doTag() throws JspException, IOException { if (iterator == null) return; while (iterator.hasNext()) { getJspContext().setAttribute(var, iterator.next()); getJspBody().invoke(null); }}public void setVar(String var) { this.var = var;}public void setGroup(Collection group) { this.group = group; if(group.size() > 0) iterator = group.iterator();}<a name="wp90595"> </a></pre></div><a name="wp90599"> </a><p class="pBody">The scope that an variable can have is summarized in <a href="JSPTags7.html#wp90607">Table 15-13</a>. The scope constrains the accessibility and lifetime of the object.</p><div align="left"><table border="1" summary="Scope of Objects" id="wp90607"> <caption><a name="wp90607"> </a><div class="pTableTitle">Table 15-13 Scope of Objects </div></caption> <tr align="center"> <th><a name="wp90613"> </a><div class="pCellHeading">Name</div></th> <th><a name="wp90615"> </a><div class="pCellHeading">Accessible From</div></th> <th><a name="wp90617"> </a><div class="pCellHeading">Lifetime</div></th></tr> <tr align="left"> <td><a name="wp90619"> </a><div class="pCellBody"><code class="cCode">page</code></div></td> <td><a name="wp90621"> </a><div class="pCellBody">Current page</div></td> <td><a name="wp90623"> </a><div class="pCellBody">Until the response has been sent back to the user or the request is passed to a new page</div></td></tr> <tr align="left"> <td><a name="wp90625"> </a><div class="pCellBody"><code class="cCode">request</code></div></td> <td><a name="wp90627"> </a><div class="pCellBody">Current page and any included or forwarded pages</div></td> <td><a name="wp90629"> </a><div class="pCellBody">Until the response has been sent back to the user</div></td></tr> <tr align="left"> <td><a name="wp90631"> </a><div class="pCellBody"><code class="cCode">session</code></div></td> <td><a name="wp90633"> </a><div class="pCellBody">Current request and any subsequent request from the same browser (subject to session lifetime)</div></td> <td><a name="wp90635"> </a><div class="pCellBody">The life of the user's session</div></td></tr> <tr align="left"> <td><a name="wp90637"> </a><div class="pCellBody"><code class="cCode">application</code></div></td> <td><a name="wp90639"> </a><div class="pCellBody">Current and any future request in the same Web application</div></td> <td><a name="wp90641"> </a><div class="pCellBody">The life of the application</div></td></tr></table></div><p class="pBody"></p><a name="wp90643"> </a><h5 class="pHeading4">TagExtraInfo Class</h5><a name="wp90647"> </a><p class="pBody">In <a href="JSPTags6.html#wp90424">Declaring Tag Variables for Tag Handlers</a> we discussed how to provide information about tag variable in the tag library descriptor. Here we describe another approach: defining a tag extra info class. You define a tag extra info class by extending the class <code class="cCode">javax.servlet.jsp.tagext.TagExtraInfo</code>. A <code class="cCode">TagExtraInfo</code> must implement the <code class="cCode">getVariableInfo</code> method to return an array of <code class="cCode">VariableInfo</code> objects containing the following information:</p><div class="pSmartList1"><ul class="pSmartList1"><a name="wp90648"> </a><div class="pSmartList1"><li>Variable name</li></div><a name="wp90649"> </a><div class="pSmartList1"><li>Variable class</li></div><a name="wp90650"> </a><div class="pSmartList1"><li>Whether the variable refers to a new object</li></div><a name="wp90651"> </a><div class="pSmartList1"><li>The availability of the variable</li></div></ul></div><a name="wp90652"> </a><p class="pBody">The Web container passes a parameter of type <code class="cCode">javax.servlet.jsp.tagext.TagData </code>to the <code class="cCode">getVariableInfo</code> method that contains attribute-value tuples for each of the tag's attributes. These attributes can be used to provide the <code class="cCode">VariableInfo</code> object with an EL variable's name and class.</p><a name="wp90653"> </a><p class="pBody">The following example demonstrates how to provide information about the variable created by the <code class="cCode">iterator</code> tag in a tag extra info class. Since the name (<code class="cCode">var</code>) and class (<code class="cCode">type</code>) of the variable are passed in as tag attributes, they can be retrieved with the <code class="cCode">data.getAttributeString</code> method and used to fill in the <code class="cCode">VariableInfo</code> constructor. To allow the variable <code class="cCode">var</code> to be used only within the tag body, the scope of the object is set to be <code class="cCode">NESTED</code>.</p><div class="pPreformattedRelative"><pre class="pPreformattedRelative">package iterator;public class IteratorTei extends TagExtraInfo { public VariableInfo[] getVariableInfo(TagData data) { String type = data.getAttributeString("type"); if (type == null) type = "java.lang.Object"; return new VariableInfo[] { new VariableInfo(data.getAttributeString("var"), type, true, VariableInfo.NESTED) }; }}<a name="wp90655"> </a></pre></div><a name="wp90656"> </a><p class="pBody">The fully qualified name of the tag extra info class defined for an EL variable must be declared in the TLD in the <code class="cCode">tei-class</code> subelement of the <code class="cCode">tag</code> element. Thus, the <code class="cCode">tei-class</code> element for <code class="cCode">IteratorTei</code> would be as follows:</p><div class="pPreformattedRelative"><pre class="pPreformattedRelative"><tei-class> iterator.IteratorTei</tei-class><a name="wp90657"> </a></pre></div><a name="wp90660"> </a><h3 class="pHeading2">Cooperating Tags</h3><a name="wp90661"> </a><p class="pBody">Tags cooperate by sharing objects. JSP technology supports two styles of object sharing.</p><a name="wp90662"> </a><p class="pBody">The first style requires that a shared object be named and stored in the page context (one of the implicit objects accessible to both JSP pages and tag handlers). To access objects created and named by another tag, a tag handler uses the <code class="cCode">pageContext.getAttribute(name,</code> <code class="cCode">scope)</code> method.</p><a name="wp90663"> </a><p class="pBody">In the second style of object sharing, an object created by the enclosing tag handler of a group of nested tags is available to all inner tag handlers. This form of object sharing has the advantage that it uses a private namespace for the objects, thus reducing the potential for naming conflicts.</p><a name="wp90664"> </a><p class="pBody">To access an object created by an enclosing tag, a tag handler must first obtain its enclosing tag with the static method <code class="cCode">SimpleTagSupport.findAncestorWithClass(from,</code> <code class="cCode">class)</code> or the <code class="cCode">SimpleTagSupport.getParent</code> method. The former method should be used when a specific nesting of tag handlers cannot be guaranteed. Once the ancestor has been retrieved, a tag handler can access any statically or dynamically created objects. Statically created objects are members of the parent. Private objects can also be created dynamically. Such objects can be stored in a tag handler with the <code class="cCode">setValue</code> method and retrieved with the <code class="cCode">getValue</code> method.</p><a name="wp90665"> </a><p class="pBody">The following example illustrates a tag handler that supports both the named and private object approaches to sharing objects. In the example, the handler for a query tag checks whether an attribute named <code class="cCode">connectionId</code> has been set. If the <code class="cCode">connectionId</code> attribute has been set, the handler retrieves the connection object from the page context. Otherwise, the tag handler first retrieves the tag handler for the enclosing tag, and then retrieves the connection object from that handler.</p><div class="pPreformattedRelative"><pre class="pPreformattedRelative">public class QueryTag extends SimpleTagSupport { public int doTag() throws JspException { String cid = getConnectionId(); Connection connection; if (cid != null) { // there is a connection id, use it connection =(Connection)pageContext. getAttribute(cid); } else { ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, ConnectionTag.class); if (ancestorTag == null) { throw new JspTagException("A query without a connection attribute must be nested within a connection tag."); } connection = ancestorTag.getConnection(); ... } }}<a name="wp90666"> </a></pre></div><a name="wp90667"> </a><p class="pBody">The query tag implemented by this tag handler could be used in either of the following ways:</p><div class="pPreformattedRelative"><pre class="pPreformattedRelative"><tt:connection cid="con01" ... > ... </tt:connection><tt:query id="balances" connectionId="con01"> SELECT account, balance FROM acct_table where customer_number = ? <tt:param value="${requestScope.custNumber}" /></tt:query><tt:connection ... > <tt:query cid="balances"> SELECT account, balance FROM acct_table where customer_number = ? <tt:param value="${requestScope.custNumber}" /> </tt:query></tt:connection><a name="wp90668"> </a></pre></div><a name="wp90669"> </a><p class="pBody">The TLD for the tag handler indicates that the <code class="cCode">connectionId</code> attribute is optional with the following declaration:</p><div class="pPreformattedRelative"><pre class="pPreformattedRelative"><tag> ... <attribute> <name>connectionId</name> <required>false</required> </attribute></tag><a name="wp90670"> </a></pre></div><a name="wp90673"> </a><h3 class="pHeading2">Examples</h3><a name="wp90674"> </a><p class="pBody">The custom tags described in this section demonstrate solutions to two recurring problems in developing JSP applications: minimizing the amount of Java programming in JSP pages and ensuring a common look and feel across applications. In doing so, they illustrate many of the styles of tags discussed in the first part of the chapter.</p><a name="wp90675"> </a><h4 class="pHeading3">An Iteration Tag</h4><a name="wp90676"> </a><p class="pBody">Constructing page content that is dependent on dynamically generated data often requires the use of flow control scripting statements. By moving the flow control logic to tag handlers, flow control tags reduce the amount of scripting needed in JSP pages.</p><a name="wp90678"> </a><p class="pBody">The <code class="cCode">iterator </code>tag retrieves objects from a collection stored in a JavaBeans component and assigns them to an EL variable. This tag is a very simplified example of the an iterator tag. Web applications requiring such functionality should use the JSTL <code class="cCode">forEach</code> tag, which is discussed in <a href="JSTL4.html#wp63713">Iterator Tags</a>. The body of the tag retrieves information from the variable. While elements remain in the collection, the <code class="cCode">iterator</code> tag causes the body to be reevaluated. </p><a name="wp90682"> </a><h5 class="pHeading4">JSP Page</h5><a name="wp90683"> </a><p class="pBody">The <code class="cCode">index.jsp</code> page invokes the <code class="cCode">iterator</code> tag to iterate through a collection of department names. Each item in the collection is assigned to the <code class="cCode">departmentName</code> variable.</p><div class="pPreformattedRelative"><pre class="pPreformattedRelative"><%@ taglib uri="/tlt" prefix="tlt" %><html> <head> <title>Departments</title> </head> <body bgcolor="white"> <jsp:useBean id="myorg" class="myorg.Organization"/> <table border=2 cellspacing=3 cellpadding=3> <tr> <td><b>Departments</b></td> </tr> <tlt:iterator var="departmentName" type="java.lang.String" group="${myorg.departmentNames}"> <tr> <td><a href="list.jsp?deptName=${departmentName}"> ${departmentName}</a></td> </tr> </tlt:iterator>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -