📄 index.xtp
字号:
<document><header><product>resin</product><version>Resin 3.0</version><type>tutorial</type><title>Tag Reuse</title><description><p>Tag libraries must follow important conventions for initializingtag fields. The JSP specification lets a JSP container, like Resin,reuse tag handler instances for efficiency and performance.Because this optimization restricts how tags can use fields,even experienced developers will benefit from this tutorial.</p></description> <tutorial-startpage>index.jsp</tutorial-startpage></header><body><summary/><s1 title="Files in this tutorial"><deftable><tr><td><viewfile-link file="index.jsp"/> </td><td>The jsp page that uses the tags</td></tr><tr><td><viewfile-link file="WEB-INF/message.tld"/> </td><td>The taglib descriptor</td></tr><tr><td><viewfile-link file="WEB-INF/classes/example/taglib/MessageTag.java"/> </td><td>The class corresponding to <msg:message></td></tr><tr><td><viewfile-link file="WEB-INF/classes/example/taglib/MessageAddTag.java"/> </td><td>The class corresponding to <msg:add>, used within the body of <msg:message></td></tr></deftable></s1><s1 title="Resin reuses tag handler instances"><glossary title="tag handler instance">An instance of the class that is associated with an xml-style custom JSP tag.</glossary><p>Resin aggressively reuses tag handler instances. Any tag with the sameset of attributes is a candidate for reuse. For example, a tag<msg:message> with an attribute title="Test-1" may share the sametag handler instance as a <msg:message> with an attribute title="Test-2".</p><p>This ability for Resin to reuse instances of the tag handler isdescribed in the JSP specification.</p><blockquote title="From the JSP 2.0 specification">"The JSP container may reuse classic tag handler instances for multipleoccurrences of the corresponding custom action, in the same page or indifferent pages, but only if the same set of attributes are used forall occurrences."</blockquote><p>In this tutorial, the <msg:message> prints its id to showthe instance of the object that is created.</p><example title="index.jsp"> <msg:message title="Test Message"> <msg:add text="Hello"/> <msg:add text="World"/> </msg:message> <msg:message> <msg:add text="Hello Again"/> <msg:add text="World"/> </msg:message> <msg:message title="Test Message"> <msg:add text="Goodbye"/> <msg:add text="World"/> </msg:message></example><p>The instance created for the first <msg:message> tag,<code>MessageTag@10000</code>, is reused for the third <msg:message> tag.Resin can reuse the tag handler instance the attributes set for thefirst and third objects are the same: {title}. The second tag uses anew instance, <code>MessageTag@100000</code>, because it hasa different attribute set: {text}.</p><results> +--------------------------------------------+ | instance: example.taglib.MessageTag@10000 | |--------------------------------------------| | Test Message | |--------------------------------------------| | Hello | | World | +--------------------------------------------+ +---------------------------------------------+ | instance: example.taglib.MessageTag@29000 | |---------------------------------------------| | default title | |---------------------------------------------| | Hello Again | | World | +---------------------------------------------+ +--------------------------------------------+ | instance: example.taglib.MessageTag@10000 | |--------------------------------------------| | Test Message | |--------------------------------------------| | Goodbye | | World | +--------------------------------------------+</results><s2 title="Lifecycle"><ol><li>Handle the first <msg:message> tag:<ol><li>Instantiate the tag handler instance, <code>MessageTag@9681e0</code></li><li>Set the attributes, <code>setTitle("Test Message")</code></li><li>Call the <code>doStartTag</code> method.</li><li>Process the contents</li><li>Call the <code>doEndTag</code> method.</li></ol></li><li>Handle the second <msg:message> tag</li><li>Handle the third <msg:message> tag:<ol><li>Set any attribute values which differ from the first tag.In this case, all the values are the same the same, so Resin doesn'tcall any setter.</li><li>Call the <code>doStartTag</code> method.</li><li>Process the contents</li><li>Call the <code>doEndTag</code> method.</li></ol></li><li>At the end of the page, clean up the tag handler instances:<ol><li>Call <code>release()</code> for the first instance, <code>MessageTag@10000</code></li><li>Call <code>release()</code> for the second instance, <code>MessageTag@29000</code></li><li>Call <code>release()</code> for the <msg:add> instances.</li></ol></li></ol><p>Resin <b>does not</b> call <code>release()</code> between the first andthird <msg:message> tags. It only calls <code>release()</code> at the end of the page. This behavior follows the JSP spec, butsurprises some tag library developers.</p></s2></s1><s1 title="Treat attributes as read-only"> <p>Since tag handler instances are reused, the fieldscorresponding to tag attributes must be read-only. OnlyResin may call the attribute setters; the tag's code must nevermodify the corresponding fields.</p><example title="WEB-INF/classes/example/taglib/MessageTag.java" language="java"> /* tag attributes * * member variables to store the value of tag attributes are treated * as read-only. Resin will set the values using setXXXX() based on * the values passed as attributes to the tag, and the code in the * class will never change the values. */ private String _attrTitle; public void setTitle(String title) { // this is the only place where _attrTitle is ever set _attrTitle = title; }</example></s1><s1 title="Initializing member variables in doStartTag"><p>Tags must initialize internal variables in the first action method called,for example <code>doStartTag</code>. Because of tag instance reuse,the tag must assume that all internal variables are unset, i.e. set tounknown, bogus values. The initialization code must initialize thosevalues.</p><p>Often in a tag it is necessary to have additional member variablesother than those that hold the value of tag attributes. In this case,the only safe way to initialize the variables is in the<code>doStartTag()</code>, before anything else is done.</p><p>Because the tag instance will be reused, you cannot simply initializethe tag in the constructor. And, because the <code>release()</code> methodis only called at the end of the page, the tag cannot call initializationcode in the <code>release()</code> method.There may be many calls to <code>doStartTag()</code> and<code>doEndTag()</code> before <code>release()</code> is called.</p><p>In this tutorial, an <code>init()</code> method is used forinitialization of these internal member variables, and a call to<code>init()</code> is the first thing done in<code>doStartTag()</code>.<example title="WEB-INF/classes/example/taglib/MessageTag.java" language="java"> String _title; <b>StringBuffer _msg;</b> <b>void init()</b> { _title = _attrTitle; if (_title == null) _title = "Default Title"; <b>_msg = new StringBuffer();</b> } public int doStartTag() throws JspException { // initialize internal member variables <b>init();</b> return EVAL_BODY_BUFFERED; }</example></p></s1><s1 title="Initializing member variables in doEndTag"><p>Tag libraries need to initialize their variables in the firsttag method called. Most often, this will be in <code>doStartTag</code>,but some tags only implement <code>doEndTag</code>. Tags whichonly have a <code>doEndTag</code> may initialize in <code>doEndTag</code>.</p><p>Because Resin can analyze which methods are implemented by a tag andgenerated better code for the default <code>TagSupport</code> methods,it's a good idea to only implement those tag methods which are absolutelynecessary.</p></s1><s1 title="Default values for attributes"><p>If an attribute of a tag is not used, the corresponding setter willnot be called. In many causes you will want to provide a defaultvalue for the attribute, and then the default value will be dependenton other member variables. Even though it is not always necessary,the best way to set a default value for a missing attribute is thesame way the internal member variables are set in the previousexample.</p><example title="WEB-INF/classes/example/taglib/MessageTag.java" language="java"> // read-only attribute field private String _attrTitle; // tag field initialized by init() private String _title; public void setTitle(String title) { _attrTitle = title; } public int doStartTag() throws JspException { // initialize internal member variables <b>init();</b> ... // main tag processing return EVAL_BODY_BUFFERED; } protected void init() { <b>_title = _attrTitle; if (_title == null) _title = "Default Title";</b> _msg = new StringBuffer(); }</example></s1></body></document>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -