Reputation: 64433
(This question is more about how a container includes a tag. And less about how a tag should be implemented. Thanks Ravi Thapliyal for pointing it out.)
I am new to JSP. I learned that JSP pages are finally turned into Servlets.
So I compared the JSP page using some JSTL tags and the servlet Java code generated by the container.
It seems each tag encapsulates a commonly used Java code block with some slots filled/controlled by the tag attributes. And the block is inserted into the _jspService()
method.
Is this the general mechanism how tag library contributes to the final servlet Java code?
I dig the generated servlet code for a JSP containing <c:forEach>
tag.
The JSP code is this:
Picture 1:
The generated servlet code is this:
Picture 2:
And
Picture 3:
It should be a 2-step process to generate the final response to client:
JSP (picture 1) ==> Servlet Java code (picture 2, 3)
Servlet Java code ==> HTML
(Container execute the _jspService()
method).My questions are:
Where does the code of picture 2 and 3 come from?
And who layout the code of picture 2 and 3 in the servlet class generated from the JSP?
By checking the code in picture 3 and for the org.apache.taglibs.standard.tag.rt.core.ForEachTag
class,
I guess the ForEachTag
type is kind of like an iterator
:
And to expose the iterated data:
scope
as a bridge to convey the current iterated item to the external world.While the outside _jspx_meth_c_005fforEach_005f0
method just use the ForEachTag
type to carry out iteration. Until ForEachTag
tells him to stop.
So I guess the code in Picture 2 and 3 are just part of the Web Container's JSP parsing logic which are used to support the JSTL tags.
If my analysis about the different responsibility between Web Container and Tab library, how does a container know how to generate code similar to picture 2 and 3 to support a new tag library?
Be it a simple/classic tag, Container only NEEDs to generate boilplate code to invoke their lifecycle methods. Below is an example of a simple tag:
Container only cares about the lifecycle methods. And if there's body, container will further parse the body for the classic tag. For simple tag, the doTag()
method covers everything.
After learning the classic tag lifecycle
, I understand that org.apache.taglibs.standard.tag.rt.core.ForEachTag
is a classic tag handler. The code in picture 3 is the Container invoking the classic lifecycle methods while evaluating the tag body.
The ForEachTag
:
Upvotes: 1
Views: 459
Reputation: 64433
After learning the classic tag lifecycle, I understand that org.apache.taglibs.standard.tag.rt.core.ForEachTag
is a classic tag handler. The code in picture 3 is the Container invoking the classic lifecycle methods while evaluating the tag body.
The ForEachTag:
Be it a simple/classic tag, Container only NEEDs to generate boilplate code to invoke their lifecycle methods. Below is an example of a simple tag:
The red ones are lifecycle methods invoking.
Container only cares about the lifecycle methods. And if there's body, container will further parse the body for the classic tag. For simple tag, the doTag()
method covers everything.
Upvotes: 0
Reputation: 51721
Yes, your observations are correct. A tag library behaves like a mini templating engine running Java code (as part of the final servlet) with tag attributes (optionally) customizing the Java implementation.
If you take a look at your JSP file header, that's using any JSTL tags, you'll notice that it imports a tag library descriptor by referencing its URI and assigns it a prefix used later when invoking one of the tags from the library.
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
The URI is mapped (by the conatiner) to a .tld
Tag Library Descriptor file that contains <tag>
entries mapping each tag to its implementing Java class and describing all the attributes the tag supports. If you were to implement a custom tag generating an on-screen keyboard, your entry might look like
<tag>
<description>Generates an on-screen keyboard</description>
<name>onScreenKB</name>
<tag-class>com.myapp.jsp.tags.OnScreenKBTag</tag-class>
<body-content>empty</body-content>
</tag>
This .tld file is dropped anywhere under the /WEB-INF
directory. The tag handler class needs to implement a specific interface but the container also provides a SimpleTagSupport
class that we can extend from.
public class OnScreenKBTag extends SimpleTagSupport {
public void doTag() throws JspException, IOException {
StringBuilder html = new StrinBuilder();
JspWriter out = getJspContext().getOut();
// tag logic
html.append(...);
...
// print response
out.print(html);
}
}
Then in your JSP file you would import
<%@ taglib uri="/WEB-INF/tags/myapp.tld" prefix="app" %>
and use your custom tag as
<div id="keyboard">
<app:onScreenKB />
</div>
Upvotes: 2