(这个问题更多的是关于容器如何包含标签。而不是如何实现标签。感谢 Ravi Thapliyal 指出它。)
我是JSP的新手。我了解到JSP页面最终变成了Servlets。
所以我使用一些JSTL标记和容器生成的servlet Java代码比较了JSP页面。
似乎每个标记都封装了一个常用的Java代码块,其中一些插槽由标记属性填充/控制。并将块插入_jspService()
方法。
这是标记库如何为最终的servlet Java代码做出贡献的一般机制吗?
我为包含<c:forEach>
标记的JSP挖掘生成的 servlet 代码。
JSP代码是这样的:
图片1:
生成的servlet代码如下:
图片2:
和
图3:
应该是一个两步过程来生成对客户的最终响应:
JSP (picture 1) ==> Servlet Java code (picture 2, 3)
Servlet Java code ==> HTML
(容器执行_jspService()
方法)。我的问题是:
图片2和3的代码来自哪里?
谁在JSP生成的servlet类中布局图片2和3的代码?
通过检查图3中的代码和org.apache.taglibs.standard.tag.rt.core.ForEachTag
类,
我猜ForEachTag
类型有点像iterator
:
并公开迭代数据:
scope
作为桥梁将当前迭代项目传达给外部世界。虽然外部_jspx_meth_c_005fforEach_005f0
方法只使用ForEachTag
类型来执行迭代。直到ForEachTag
告诉他停止。
所以我猜图2和图3中的代码只是Web容器的JSP解析逻辑的一部分,用于支持JSTL标记。
如果我对Web容器和Tab库之间的不同责任进行分析,容器如何知道如何生成类似于图片2和3的代码以支持新的标签库?
无论是简单/经典标签,容器只需要生成boilplate代码来调用其生命周期方法。下面是一个简单标记的示例:
Container只关心生命周期方法。如果有身体,容器将进一步解析身体的经典标签。对于简单标记,doTag()
方法涵盖了所有内容。
在学习classic tag lifecycle
之后,我了解org.apache.taglibs.standard.tag.rt.core.ForEachTag
是一个经典的标记处理程序。图3中的代码是Container在评估标签主体时调用经典生命周期方法。
ForEachTag
:
答案 0 :(得分:2)
是的,您的观察是正确的。标记库的行为类似于运行Java代码(作为最终servlet的一部分)的迷你模板引擎,带有标记属性(可选)自定义Java实现。
如果您查看JSP文件头,即使用任何JSTL标记,您会注意到它通过引用其URI来导入标记库描述符,并为其分配一个前缀,以便在以后调用其中一个标记时使用库。
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
URI(由conatiner)映射到.tld
标记库描述符文件,该文件包含将<tag>
条目映射到其实现的Java类并描述标记支持的所有属性。如果要实现生成屏幕键盘的自定义标记,则输入可能类似于
<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>
此.tld文件将被删除到/WEB-INF
目录下的任何位置。标记处理程序类需要实现特定的接口,但容器还提供了我们可以扩展的SimpleTagSupport
类。
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);
}
}
然后在JSP文件中导入
<%@ taglib uri="/WEB-INF/tags/myapp.tld" prefix="app" %>
并将您的自定义标记用作
<div id="keyboard">
<app:onScreenKB />
</div>
答案 1 :(得分:0)
在学习经典标签生命周期后,我了解org.apache.taglibs.standard.tag.rt.core.ForEachTag
是一个经典的标签处理程序。图3中的代码是Container在评估标签体时调用经典生命周期方法。
ForEachTag:
无论是简单/经典标签,容器只需要生成boilplate代码来调用其生命周期方法。下面是一个简单标记的示例:
红色的是生命周期方法调用。
Container只关心生命周期方法。如果有身体,容器将进一步解析身体的经典标签。对于简单标记,doTag()
方法涵盖了所有内容。