JSP 标签库的工作方式是否类似于某种模板化的 JAVA 代码生成?
Does JSP tag libraries work like some kind of tempated JAVA code generation?
(这个问题更多是关于容器如何包含标签。而不是关于标签应该如何实现。感谢 Ravi Thapliyal 指出。)
我是 JSP 的新手。我了解到 JSP 页面终于变成了 Servlet。
所以我比较了使用一些JSTL标签的JSP页面和容器生成的servletJava代码。
似乎每个标签都封装了一个常用的Java代码块,标签属性带有一些插槽filled/controlled。并且该块被插入到 _jspService()
方法中。
这是标记库对最终 servlet Java 代码的贡献的一般机制吗?
加 1
我挖掘生成的 servlet 代码用于包含 <c:forEach>
标签的 JSP。
JSP代码是这样的:
图片1:
生成的servlet代码是这样的:
图片二:
和
图3:
它应该是一个 2 步 过程来生成对客户端的最终响应:
JSP (picture 1) ==> Servlet Java code (picture 2, 3)
Servlet Java code ==> HTML
(容器执行_jspService()
方法)。
我的问题是:
图2和图3的代码哪里来的
谁在JSP生成的servletclass中布置图2和图3的代码?
添加 2
通过检查图 3 中的代码,对于 org.apache.taglibs.standard.tag.rt.core.ForEachTag
class,
我猜 ForEachTag
类型有点像 iterator
:
- 它被赋予了要迭代的项目集合。
- 它为外部世界提供了一些API来控制迭代过程。
并公开迭代数据:
- 它使用一个
scope
作为一个桥梁,将当前迭代的item传递给外界。
而外面的_jspx_meth_c_005fforEach_005f0
方法只是使用ForEachTag
类型进行迭代。直到 ForEachTag
让他停止。
所以我猜图 2 和图 3 中的代码只是 Web 容器的 JSP 解析逻辑的一部分,用于支持 JSTL 标签。
加 3
如果我分析Web Container和Tab库的不同职责,容器怎么知道如何生成类似于图2和图3的代码来支持一个新的标签库 ?
回答加3
无论是 simple/classic 标签,容器只需要生成样板代码来调用它们的生命周期方法。下面是一个简单标签的示例:
容器只关心生命周期方法。如果有正文,容器将进一步解析正文以获得 classic 标签。对于简单的标签,doTag()
方法涵盖所有内容。
加 4
学习了classic tag lifecycle
后,我明白了org.apache.taglibs.standard.tag.rt.core.ForEachTag
是一个classic标签处理器。图 3 中的代码是 Container 在评估标签体时调用 classic 生命周期方法。
ForEachTag
:
- 包含要循环的收集数据
- 保持循环状态
- 并使用其生命周期方法来控制循环。
是的,您的观察是正确的。标签库的行为类似于迷你模板引擎 运行 Java 代码(作为最终 servlet 的一部分),带有标签属性(可选)自定义 Java 实现。
如果您查看 JSP 文件头,它使用了任何 JSTL 标记,您会注意到它通过引用其 URI 导入标记库描述符并为其分配一个前缀,稍后在调用时使用库中的标签之一。
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
URI 被(由容器)映射到一个 .tld
标签库描述符文件,该文件包含 <tag>
个条目,将每个标签映射到它的实现 Java class 和描述标签支持的所有属性。如果您要实现生成屏幕键盘的自定义标签,您的条目可能看起来像
<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
目录下的任何位置。标签处理程序 class 需要实现一个特定的 接口 但容器还提供了一个 SimpleTagSupport
class 我们可以从中扩展。
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>
学习了经典的tag lifecycle,明白了org.apache.taglibs.standard.tag.rt.core.ForEachTag
是一个经典的tag handler。图3中的代码是Container在评估标签体时调用经典的生命周期方法。
ForEachTag:
- 包含要循环的收集数据
- 保持循环状态
- 并使用其生命周期方法来控制循环。
回答加3
无论是 simple/classic 标签,容器只需要生成样板代码来调用它们的生命周期方法。下面是一个简单标记的示例:
红色的是生命周期方法调用。
容器只关心生命周期方法。如果有 body,container 会进一步解析 body 中的 classic 标签。对于简单的标签,doTag()
方法涵盖了一切。
(这个问题更多是关于容器如何包含标签。而不是关于标签应该如何实现。感谢 Ravi Thapliyal 指出。)
我是 JSP 的新手。我了解到 JSP 页面终于变成了 Servlet。
所以我比较了使用一些JSTL标签的JSP页面和容器生成的servletJava代码。
似乎每个标签都封装了一个常用的Java代码块,标签属性带有一些插槽filled/controlled。并且该块被插入到 _jspService()
方法中。
这是标记库对最终 servlet Java 代码的贡献的一般机制吗?
加 1
我挖掘生成的 servlet 代码用于包含 <c:forEach>
标签的 JSP。
JSP代码是这样的:
图片1:
生成的servlet代码是这样的:
图片二:
和
图3:
它应该是一个 2 步 过程来生成对客户端的最终响应:
JSP (picture 1) ==> Servlet Java code (picture 2, 3)
Servlet Java code ==> HTML
(容器执行_jspService()
方法)。
我的问题是:
图2和图3的代码哪里来的
谁在JSP生成的servletclass中布置图2和图3的代码?
添加 2
通过检查图 3 中的代码,对于 org.apache.taglibs.standard.tag.rt.core.ForEachTag
class,
我猜 ForEachTag
类型有点像 iterator
:
- 它被赋予了要迭代的项目集合。
- 它为外部世界提供了一些API来控制迭代过程。
并公开迭代数据:
- 它使用一个
scope
作为一个桥梁,将当前迭代的item传递给外界。
而外面的_jspx_meth_c_005fforEach_005f0
方法只是使用ForEachTag
类型进行迭代。直到 ForEachTag
让他停止。
所以我猜图 2 和图 3 中的代码只是 Web 容器的 JSP 解析逻辑的一部分,用于支持 JSTL 标签。
加 3
如果我分析Web Container和Tab库的不同职责,容器怎么知道如何生成类似于图2和图3的代码来支持一个新的标签库 ?
回答加3
无论是 simple/classic 标签,容器只需要生成样板代码来调用它们的生命周期方法。下面是一个简单标签的示例:
容器只关心生命周期方法。如果有正文,容器将进一步解析正文以获得 classic 标签。对于简单的标签,doTag()
方法涵盖所有内容。
加 4
学习了classic tag lifecycle
后,我明白了org.apache.taglibs.standard.tag.rt.core.ForEachTag
是一个classic标签处理器。图 3 中的代码是 Container 在评估标签体时调用 classic 生命周期方法。
ForEachTag
:
- 包含要循环的收集数据
- 保持循环状态
- 并使用其生命周期方法来控制循环。
是的,您的观察是正确的。标签库的行为类似于迷你模板引擎 运行 Java 代码(作为最终 servlet 的一部分),带有标签属性(可选)自定义 Java 实现。
如果您查看 JSP 文件头,它使用了任何 JSTL 标记,您会注意到它通过引用其 URI 导入标记库描述符并为其分配一个前缀,稍后在调用时使用库中的标签之一。
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
URI 被(由容器)映射到一个 .tld
标签库描述符文件,该文件包含 <tag>
个条目,将每个标签映射到它的实现 Java class 和描述标签支持的所有属性。如果您要实现生成屏幕键盘的自定义标签,您的条目可能看起来像
<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
目录下的任何位置。标签处理程序 class 需要实现一个特定的 接口 但容器还提供了一个 SimpleTagSupport
class 我们可以从中扩展。
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>
学习了经典的tag lifecycle,明白了org.apache.taglibs.standard.tag.rt.core.ForEachTag
是一个经典的tag handler。图3中的代码是Container在评估标签体时调用经典的生命周期方法。
ForEachTag:
- 包含要循环的收集数据
- 保持循环状态
- 并使用其生命周期方法来控制循环。
回答加3
无论是 simple/classic 标签,容器只需要生成样板代码来调用它们的生命周期方法。下面是一个简单标记的示例:
红色的是生命周期方法调用。
容器只关心生命周期方法。如果有 body,container 会进一步解析 body 中的 classic 标签。对于简单的标签,doTag()
方法涵盖了一切。