似乎有两种使用 JSP 进行模板化的方法。包含具有这些语句之一的文件
<%@ include file="foo.html" %>
<jsp:include page="foo.html" />
或使用 JSP 标记文件
// Save this as mytag.tag
<%@ tag description="Description" pageEncoding="UTF-8"%>
<html>
<head>
</head>
<body>
<jsp:doBody/>
</body>
</html>
在另一个 JSP 页面中调用它
<%@ taglib prefix="t" tagdir="/WEB-INF/tags" %>
<t:mytag>
<h1>Hello World</h1>
</t:mytag>
那么我应该使用哪种方法呢?现在是否被认为已弃用,或者它们既有效又涵盖不同的用例?
编辑
使用此标记文件与使用包含不一样吗?
// Save this as product.tag
<%@ tag description="Product templage" pageEncoding="UTF-8"%>
<%@ tag import="com.myapp.Product" %>
<%@ attribute name="product" required="true" type="com.myapp.Product"%>
Product name: ${product.name} <br/>
Quantity: ${product.quantity} <br/>
并在另一个 JSP 上调用它
<%@ taglib prefix="t" tagdir="/WEB-INF/tags" %>
<t:product>
<c:forEach items="${cart.products}" var="product">
<t:product product="${product}"/>
</c:forEach>
</t:product>
在我看来,这与使用包含并向其传递参数非常相似。那么标记文件与包含相同吗?
JSP 语法元素概述
首先,为了让事情更清楚,下面是对 JSP syntax elements 的简短概述:
指令:它们传达有关整个 JSP 页面的信息。
脚本元素:这些是 Java 编码元素,例如声明、表达式、scriptlet 和注释。
对象和范围:JSP 对象可以显式或隐式创建,并且可以在给定范围内访问,例如从 JSP 页面或会话中的任何位置访问。
操作:这些操作创建对象或影响 JSP 响应中的输出流(或两者兼而有之)。
内容如何包含在 JSP 中
有几种机制可以重用 JSP 文件中的内容。
以下在 JSP 中包含内容的 4 种机制可以归类为直接重用:
(前 3 种机制引用自 "Head First Servlets and JSP")
1) include 指令: <%@ include file="header.html" %> 静态:在翻译时将文件属性值的内容添加到当前页面。该指令最初用于静态布局模板,例如 HTML 标头。
2)
Tag File是一种间接的内容重用方法,即封装可重用内容的方式。标记文件是一个源文件,其中包含可作为自定义标记重用的 JSP 代码片段。
包含文件和标记文件的目的是不同的。
Tag file(JSP 2.0 引入的一个概念)是用于创建自定义标记的选项之一。这是构建自定义标签的一种更快、更简单的方法。 Custom tags,也称为标记扩展,是 JSP 元素,允许将其他 Java 组件提供的自定义逻辑和输出插入到 JSP 页面中。通过自定义标记提供的逻辑由称为 标记处理程序 的 Java 对象实现。
可以由自定义标签执行的一些任务示例包括对隐式对象进行操作、处理表单、访问数据库和其他企业服务(如电子邮件和目录)以及实现流控制。
关于你的编辑
也许在您的示例中(在您的“编辑”段落中),使用直接包含和标记文件之间没有区别。但是自定义标签具有丰富的功能。他们能
通过调用页面传递的属性进行定制。
将变量传递回调用页面。
访问所有可用于 JSP 页面的对象。
互相交流。您可以创建和初始化 JavaBeans 组件,创建一个公共 EL 变量来引用一个标记中的该 bean,然后在另一个标记中使用该 bean。
相互嵌套并通过私有变量进行通信。
另请阅读“Pro JSP 2”:Understanding JSP Custom Tags。
有用的阅读。
JSP中include指令和include动作的区别
使模板更容易的 JSP 技巧
来自 coreservlet.com 的内容丰富且易于理解的教程,其中包含
来自 coreservlets.com 的另一个与标记库和标记文件相关的不错的教程:创建自定义 JSP 标记库:基础知识
带有示例的官方 Java EE 5 教程:使用标记文件封装可重用内容。
来自官方 Java EE 5 教程的这个页面应该会让您更加理解:Reusing Content in JSP Pages。
“Pro JSP 2”一书的这段摘录还讨论了为什么需要标签文件而不是使用静态包含:Reusing Content with Tag Files
Oracle 文档中非常有用的指南:静态包含与动态包含
结论
为每项任务使用正确的工具。
使用标签文件作为创建自定义标签的一种快速简便的方法,可以帮助您封装可重用的内容。
至于 JSP 中包含的内容(引自here):
如果文件很少更改,请使用 include 指令。这是最快的机制。如果您的容器没有自动检测更改,您可以通过删除主页类文件来强制更改生效。仅对经常更改的内容使用包含操作,并且在请求主页之前无法决定要包含哪个页面。
<@include>
- 指令标记指示 JSP 编译器在创建生成的 servlet 代码之前将包含文件的内容合并到 JSP 中。这相当于将包含页面中的文本剪切并粘贴到 JSP 中。
在运行时只执行一个 servlet。
在父页面中声明的 Scriptlet 变量可以在包含页面中访问(记住,它们是同一个页面)。
包含的页面不需要能够编译为独立的 JSP。它可以是代码片段或纯文本。包含的页面永远不会被编译为独立的。包含的页面也可以有任何扩展名,尽管 .jspf 已成为常规使用的扩展名。
旧容器的一个缺点是,在父页面更新之前,对包含页面的更改可能不会生效。最新版本的 Tomcat 将检查包含页面是否有更新,如果更新,则强制重新编译父页面。
另一个缺点是,由于代码直接内联到生成的 servlet 的服务方法中,因此该方法可能会变得非常大。如果超过 64 KB,您的 JSP 编译可能会失败。
<jsp:include>
- 另一方面,JSP Action 标记指示容器暂停该页面的执行,继续运行包含的页面,并将该页面的输出合并到该页面的输出中。
每个包含的页面在运行时作为单独的 servlet 执行。
在运行时可以有条件地包含页面。这对于使用包含构建页面的模板框架通常很有用。父页面可以根据一些运行时条件确定要包括哪个页面(如果有)。
scriptlet 变量的值需要显式传递给包含页面。
包含的页面必须能够独立运行。
由于在生成的 servlet 类中超出了最大方法大小,您不太可能遇到编译错误。
根据您的需要,您可以使用 <@include> 或
<t:mytag><h1>Hello World</h1></t:mytag>
?这不是包含,而是标签的正常使用(如 <jsp:useBean>
或 <c:if>
)。
<jsp:include />
优于 <%@ include >
的主要优点是:
<jsp:include />
允许传递参数
<jsp:include page="inclusion.jsp">
<jsp:param name="menu" value="objectValue"/>
</jsp:include>
这在 <%@include file="somefile.jsp" %>
中是不可能的
<%@include file="somefile.jsp?menu=value" %>
怎么样?也有限制吗?
所有三个模板选项 - <%@include>
、<jsp:include>
和 <%@tag>
都是有效的,并且所有三个都涵盖不同的用例。
使用 <@include>
,JSP 解析器在编译之前将包含文件的内容内联到 JSP 中(类似于 C 的 #include
)。您可以将此选项用于简单的静态内容:例如,如果您想在 Web 应用程序的每个页面中包含页眉、页脚或导航元素。包含的内容成为编译后的 JSP 的一部分,并且在运行时没有额外的成本。
<jsp:include>
(和 JSTL 的 <c:import>
,类似且功能更强大)最适合动态内容。当您需要包含来自另一个 URL(本地或远程)的内容时,请使用这些;当您包含的资源本身是动态的时;或者当包含的内容使用与包含页面冲突的变量或 bean 定义时。 <c:import>
还允许您将包含的文本存储在变量中,您可以进一步操作或重复使用该变量。这两者都会为调度带来额外的运行时成本:这是最小的,但您需要注意动态包含不是“免费的”。
当您想要创建可重用的用户界面组件时,请使用标记文件。例如,如果您有一个小部件列表,并且想要遍历小部件并显示每个小部件的属性(在表格中或在表单中),您将创建一个标签。标签可以接受参数,使用 <%@tag attribute>
并且这些参数可以是强制性的或可选的 - 有点像方法参数。
标记文件是一种更简单的、基于 JSP 的标记库编写机制,您必须使用 Java 代码编写(在 JSP 2.0 之前)。当标签中有大量渲染工作时,编写 JSP 标记文件要简洁得多:您不需要像用 Java 编写标签那样混合 Java 和 HTML 代码。
<jsp:include>
10 次某个 other 文件,则该 other 文件将被翻译 10 次(加上发送它的响应)。在使用 <@include>
10 次时,它只会翻译该 other 文件一次(在翻译时)。我做对了吗?
<jsp:include>
,另一个文件将被翻译成 Java 代码,然后编译一次,然后编译的类(方法)将被调用(调用)10 次。 @include
另一个文件的 10 个副本将被“粘贴”到调用文件中,然后整个文件将被翻译和编译一次。如果包含的文件包含变量声明,您会收到错误,因为 var 将使用 @include
重新声明 9 次
include 指令包含的资源在 jsp 翻译期间加载,而 include 操作包含的资源在请求期间加载。在包含指令的情况下,在 jsp 文件再次编译之前,对包含资源的任何更改都将不可见。在包含操作的情况下,包含资源的任何更改都将在下一个请求中可见。 include 指令是静态导入,而 include 动作是动态导入。 Include 指令使用 file 属性来指定要包含的资源,而 include 操作使用 page 属性来达到同样的目的。
不定期副业成功案例分享
<jsp:include>
时生成的代码示例,请参阅 this answer。这也是对 "JSP Execution" 过程的非常有用的描述。