📄 package-summary.html
字号:
described in the JSP Fragments section and it is passed to the setter. If the tag is declared to have a <code>body-content</code> of "<code>tagdependent</code>" the <code>JspFragment</code> must echo the body's contents verbatim. Otherwise, if the tag is declared to have a <code>body-content</code> of type "<code>scriptless</code>", the <code>JspFragment</code> must evaluate the body's contents as a JSP scriptless body.</li> </ul> </li> <li>The <code>doTag()</code> method is invoked.</li> <li>The implementation of <code>doTag()</code> performs its function, potentially calling other tag handlers (if the tag handler is implemented as a tag file) and invoking fragments.</li> <li>The <code>doTag()</code> method returns, and the tag handler instance is discarded. If <code>SkipPageException</code> is thrown, the rest of the page is not evaluated and the request is completed. If this request was forwarded or included from another page (or Servlet), only the current page evaluation stops.</li> <li>For each tag scripting variable declared with scopes <code>AT_BEGIN</code> or <code>AT_END</code>, the appropriate scripting variables and scoped attributes are declared, as with classic tag handlers.</li></ol><a name="fragment"><h2>7. JSP Fragments</h2></a><p>JSP Fragments are represented in Java by an instance of the <code>javax.servlet.jsp.tagext.JspFragment abstract class</code>.Pieces of JSP code are translated into JSP fragments in the context of a tag invocation. JSP Fragments are created when providing the body of a <jsp:attribute> standard action for an attribute that is definedas a fragment or of type JspFragment, or when providing the body of a tag invocation handled by a Simple Tag Handler.</p><p>Before being passed to a tag handler, the <code>JspFragment</code> instance is associated with the <code>JspContext</code> of the surrounding page in an implementation-dependent manner. In addition, it is associated with the parent <code>Tag</code> or <code>SimpleTag</code> instance for collaboration purposes, so that when a custom action is invoked from within the fragment, <code>setParent()</code> can be called with the appropriate value. The fragment implementation must keep these associations for the duration of the tag invocation in which it is used.</p><p>The <code>invoke()</code> method executes the body and directs all output to either the passed in <code>java.io.Writer</code> or the <code>JspWriter</code> returned by the <code>getOut()</code> method of the <code>JspContext</code> associated with the fragment.</p><p>The implementation of each method can optionally throw a <code>JspException</code>, which must be handled by the invoker. Note that tag library developers and page authors should not generate<code>JspFragment</code> implementations manually.</p><p>The following sections specify the creation and invocation lifecycles of a JSP Fragment in detail, from the JSP Container's perspective.</p><h3>Creation of a JSP Fragment</h3><p>When a JSP fragment is created, the following steps occur (in order):<ol> <li>An instance of a class implementing the <code>JspFragment</code> abstract class is obtained (may either be created or can optionally be cached) each time the tag is invoked. This instance must be configured to produce the contents of the body of the fragment when invoked. If the fragment is defining the body of a <jsp:attribute>, the fragment must evaluate the body each time it is invoked. Otherwise, if the fragment is defining the body of a simple tag, the behavior of the fragment when invoked varies depending on the <code>body-content</code> declared for the tag: <ul> <li>If the <code>body-content</code> is "<code>tagdependent</code>", then the fragment must echo the contents of the body verbatim when invoked.</li> <li>If the <code>body-content</code> is "<code>scriptless</code>", then the fragment must evaluate the body each time it is invoked.</li> </ul> </li> <li>The <code>JspFragment</code> instance is passed a reference to the current <code>JspContext</code>. Whenever the fragment invokes a tag handler, it must use this value when calling <code>setJspContext()</code>.</li> <li>The <code>JspFragment</code> instance is associated with an instance of the tag handler of the nearest enclosing tag invocation, or with <code>null</code> if there is no enclosing tag. Whenever the fragment invokes a tag handler, the fragment must use this value when calling <code>setParent()</code>.</li></ol><h3>Invocation of a JSP Fragment</h3><p>After a JSP fragment is created, it is passed to a tag handler for later invocation. JSP fragments can be invoked either programmatically from a tag handler written in Java, or from a tag file using the <jsp:invoke> or <jsp:doBody> standard action.</p><p>JSP fragments are passed to tag handlers using a bean property of type <code>JspFragment</code>. These fragments can be invoked by calling the <code>invoke()</code> method in the <code>JspFragment</code> abstract class. Note that it is legal (and possible) for a fragment to recursively invoke itself, indirectly.</p><p>The following steps are followed when invoking a JSP fragment:</p><ol> <li>The tag handler invoking the fragment is responsible for setting the values of all declared <code>AT_BEGIN</code> and <code>NESTED</code> variables in the <code>JspContext</code> of the calling page/tag, before invoking the fragment. Note that this is not always the same as the <code>JspContext</code> of the fragment being invoked, as fragments can be passed from one tag to another. In the case of tag files, for each variable declared in scope <code>AT_BEGIN</code> or <code>NESTED</code>, if a page scoped attribute exists with the provided name in the tag file, the JSP container must generate code to create/update the page scoped attribute of the provided name in the calling page/tag. If a page scoped attribute with the provided name does not exist in the calling page, and a page scoped attribute of the provided name is present in the tag file, the scoped attribute is removed from the tag file's page scope. See the chapter on Tag Files for details.</li> <li>If <jsp:invoke> or <jsp:doBody> is being used to invoke a fragment, if the <code>var</code> attribute is specified, a custom <code>java.io.Writer</code> is created that can expose the result of the invocation as a <code>java.lang.String</code> object. If the <code>varReader</code> attribute is specified, a custom <code>java.io.Writer</code> object is created that can expose the resulting invocation as a <code>java.io.Reader</code> object.</li> <li>The <code>invoke()</code> method of the fragment is invoked, passing in an optional <code>Writer</code>.</li> <li>Before executing the body of the fragment, if a non-null value is provided for the writer parameter, then the value of <code>JspContext.getOut()</code> and the implicit "out" object must be updated to send output to that writer. To accomplish this, the container must call <code>pushBody( writer )</code> on the current <code>JspContext</code>, where <code>writer</code> is the instance of <code>java.io.Writer</code> passed to the fragment upon invocation.</li> <li>The body of the fragment is then evaluated by executing the generated code. The body of the fragment may execute other standard or custom actions. If a classic Custom Tag Handler is invoked and returns <code>SKIP_PAGE</code>, or if a Simple Tag Handler is invoked and throws <code>SkipPageException</code>, the <code>JspFragment</code> must throw <code>SkipPageException</code> to signal that the calling page is to be skipped.</li> <li>Once the fragment has completed its evaluation, even if an exception is thrown, the value of <code>JspContext.getOut()</code> must be restored via a call to <code>popBody()</code> on the current <code>JspContext</code>.</li> <li>The fragment returns from invoke()</li> <li>If <jsp:invoke> or <jsp:doBody> is being used to invoke a fragment, if the <code>var</code> or <code>varReader</code> attribute is specified, a scoped variable with a name equal to the value of the <code>var</code> or <code>varReader</code> attribute is created (or modified) in the page scope, and the value is set to a <code>java.lang.String</code> or <code>java.io.Reader</code> respectively that can produce the results of the fragment invocation.</li> <li>The <code>invoke()</code> method can be called again, zero or more times. When the tag invocation defining the fragment is complete, the tag must discard the fragment instance since it might be reused by the container.</li></ol><a name="sths"><h2>8. Example Simple Tag Handler Scenario</h2></a><p>The following non-normative example is intended to help solidify some of the concepts relating to Tag Files, JSP Fragments and SimpleTag Handlers. In the first section, two sample input files are presented, a JSP (my.jsp), and a simple tag handler implemented using a tag file (simpletag.tag). One possible output of the translation process is presented in the second section.</p><p>Although short, the example shows all concepts, including the variable directive. In practice most uses of tags will be much simpler, but probably longer.</p><p>The sample generated code is annotated with comments that point to lifecycle steps presented in various sections. The notation is as follows:</p><ul> <li>"Step T.x" = Annotated step x from "Lifecycle of Simple Tag Handlers" earlier in this Chapter.</li> <li>"Step C.x" = Annotated step x from "Creation of a JSP Fragment" earlier in this Chapter.</li> <li>"Step F.x" = Annotated step x from "Invocation of a JSP Fragment" earlier in this Chapter.</li></ul><h3>Sample Source Files</h3><p>This section presents the sample source files in this scenario, from which the output files are generated.</p><h4>Original JSP (my.jsp)</h4><pre><%@ taglib prefix="my" tagdir="/WEB-INF/tags" %><my:simpleTag x="10"> <jsp:attribute name="y">20</jsp:attribute> <jsp:attribute name="nonfragment"> Nonfragment Template Text </jsp:attribute> <jsp:attribute name="frag"> Fragment Template Text ${var1} </jsp:attribute> <jsp:body> Body of tag that defines an AT_BEGIN scripting variable ${var1}. </jsp:body></my:simpleTag></pre><h4>Original Tag File (/WEB-INF/tags/simpletag.tag)</h4><pre><%-- /WEB-INF/tags/simpletag.tag --%><%@ attribute name="x" %><%@ attribute name="y" %><%@ attribute name="nonfragment" %><%@ attribute name="frag" fragment="true" %><%@ variable name-given="var1" scope="AT_BEGIN" %><%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>Some template text.<c:set var="var1" value="${x+y}"/><jsp:invoke fragment="frag" varReader="var1"/>Invoke the body:<jsp:doBody/></pre><h3>Sample Generated Files</h3><p>This section presents sample output files that might be generated by a JSP compiler, from the source files presented in the previous section.</p><h4>Helper class for JspFragment (JspFragmentBase.java)</h4><pre>public abstract class JspFragmentBase implements javax.servlet.jsp.tagext.JspFragment{ protected javax.servlet.jsp.JspContext jspContext; protected javax.servlet.jsp.tagext.JspTag parentTag; public void JspFragmentBase( javax.servlet.jsp.JspContext jspContext, javax.servlet.jsp.tagext.JspTag parentTag ) { this.jspContext = jspContext; this.parentTag = parentTag; }}</pre><h4>Relevant Portion of JSP Service Method</h4><pre>// Step T.1 - Initial creationMySimpleTag _jsp_mySimpleTag = new MySimpleTag();// Step T.2 - Set page context and parent (since parent is null,// no need to call setParent() in this case)_jsp_mySimpleTag.setJspContext( jspContext );// Step T.3 - XML element attributes evaluated and set_jsp.mySimpleTag.setX( "10" );// Step T.4 - <jsp:attribute> elements evaluated and set// - parameter y// (using PageContext.pushBody() is one possible implementation - // one limitation is that this code will only work for Servlet-based code).out = ((PageContext)jspContext).pushBody();out.write( "20" );_jsp_mySimpleTag.setY( ((javax.servlet.jsp.tagext.BodyContent)out).getString() );out = jspContext.popBody();// - parameter nonfragment// (using PageContext.pushBody() is one possible implementation - // one limitation is that this code will only work for Servlet-based code).// Note that trim is enabled by default, else we would have "\n Non..."out = ((PageContext)jspContext).pushBody();out.write( "Nonfragment Template Text" );_jsp_mySimpleTag.setNonfragment( ((javax.servlet.jsp.tagext.BodyContent)out).getString() );out = jspContext.popBody();// - parameter frag_jsp_mySimpleTag.setFrag( // Step C.1 - New instance of fragment created // Step C.2 - Store jspContext // Step C.3 - Association with nearest enclosing Tag instance new JspFragmentBase( jspContext, _jsp_mySimpleTag ) { public void invoke( java.io.Writer writer ) { javax.servlet.jsp.JspWriter out; // Step F.1-F.3 done in tag file (see following example) // Step F.4 - If writer provided, push body: if( out == null ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -