目录
3.1 Tag文件的结构
Tag文件是一种特殊的文件,它可以被JSP页面动态加载和调用,实现代码的复用和分离。Tag文件的扩展名为.tag,其结构和JSP文件类似,可以使用HTML标签,Java脚本,JSP动作和指令,以及一些特殊的指令。
## 3.1.1 Tag文件的结构
Tag文件的结构如下:
```jsp
<%@ tag pageEncoding="编码方式" %>
<%@ attribute name="属性名" required="true|false" type="属性类型" %>
<%@ variable name-given="变量名" alias="别名" scope="作用域" %>
<%@ taglib prefix="前缀" tagdir="标记库位置" %>
<%@ include file="包含文件" %>
<!-- 标记体 -->
<jsp:doBody/>
```
其中:
- `<%@ tag %>`指令是定义Tag文件的基本信息,如编码方式,标记体类型等。
- `<%@ attribute %>`指令是定义Tag文件的属性,用于接收JSP页面传递的参数。
- `<%@ variable %>`指令是定义Tag文件的变量,用于在JSP页面中使用。
- `<%@ taglib %>`指令是引入其他标记库,用于在Tag文件中使用其他自定义标记。
- `<%@ include %>`指令是包含其他文件,用于在Tag文件中重用代码。
- `<jsp:doBody/>`动作是调用标记体,用于在Tag文件中执行JSP页面传递的内容。
## 3.1.2 Tag文件的保存
Tag文件必须保存在`/WEB-INF/tags`目录下,或者该目录下的子目录中。这样可以保证Tag文件不会被用户直接访问,也便于管理和维护。每个目录下的Tag文件可以形成一个标记库,通过前缀来区分不同标记库中相同名字的标记文件。
# 3.2 Tag标记
Tag标记是对应Tag文件的标识符,可以在JSP页面中使用。Tag标记的格式有两种:
- `<tag 文件名/>`:没有标记体的Tag标记,用于调用不需要传递参数的Tag文件。
- `<tag 文件名> 标记体 </tag 文件名>`:有标记体的Tag标记,用于调用需要传递参数或内容的Tag文件。
在使用Tag标记之前,需要在JSP页面中引入相应的标记库,使用`<%@ taglib %>`指令。例如:
```jsp
<%@ taglib prefix="math" tagdir="/WEB-INF/tags/math/" %>
```
这样就可以在JSP页面中使用`math`前缀来调用`/WEB-INF/tags/math/`目录下的Tag文件了。例如:
```jsp
<math:random/>
<math:sum>1,2,3</math:sum>
```
## 3.2.1 Tag标记和Tag文件
一个Tag标记对应一个Tag文件,一个Tag文件对应一个Tag类。当JSP页面调用一个Tag标记时,会创建一个对应的Tag类的实例,并执行其方法。这些方法包括:
- `setJspContext(JspContext pc)`:设置JSP上下文对象。
- `setParent(JspTag parent)`:设置父标签对象。
- `getParent()`:获取父标签对象。
- `setJspBody(JspFragment jspBody)`:设置标记体对象。
- `doStartTag()`:开始执行标签。
- `doEndTag()`:结束执行标签。
- `doInitBody()`:初始化标签体。
- `doAfterBody()`:处理循环体。
## 3.2.2 Tag标记的使用
要使用一个Tag标记,需要遵循以下步骤:
- 编写一个Tag文件,并保存在`/WEB-INF/tags`目录下或其子目录中。
- 在JSP页面中引入相应的标记库,并给定一个前缀。
- 在JSP页面中使用前缀和Tag文件名来调用相应的Tag标记,并根据需要传递参数或内容。
- 在浏览器中访问JSP页面,查看效果。
例如,要使用一个计算三角形面积的Tag标记,可以按照以下步骤:
- 编写一个名为Area.tag的Tag文件,并保存在`/WEB-INF/tags/math/`目录下。该Tag文件有三个属性:a, b, c,分别表示三角形的三条边长。该Tag文件计算并输出三角形面积。
```jsp
<%@ tag pageEncoding="UTF-8" %>
<%@ attribute name="a" required="true" type="java.lang.Double" %>
<%@ attribute name="b" required="true" type="java.lang.Double" %>
<%@ attribute name="c" required="true" type="java.lang.Double" %>
<%
// 计算三角形面积
double p = (a + b + c) / 2; // 半周长
double s = Math.sqrt(p * (p - a) * (p - b) * (p - c)); // 面积
out.println("三角形面积为:" + s); // 输出结果
%>
```
- 在JSP页面中引入`/WEB-INF/tags/math/`目录下的标记库,并给定前缀为`math`。
```jsp
<%@ taglib prefix="math" tagdir="/WEB-INF/tags/math/" %>
```
- 在JSP页面中使用`math:Area`来调用Area.tag,并传递三个参数:a=3, b=4, c=5。
```jsp
<math:Area a="3" b="4" c="5"/>
```
## 3.2.3 Tag标记的运行原理
当JSP容器遇到一个自定义标签时,会根据其前缀找到对应的TLD(tag library descriptor)文件或tagdir属性指定的目录。然后根据其名称找到对应的tag-file元素或tag-class元素。如果是tag-file元素,则会将其指定的.tag文件转换为一个实现了SimpleTag接口或BodyTag接口或IterationTag接口或ClassicTag接口之一的Java类,并编译为.class字节码。如果是tag-class元素,则会直接加载其指定的Java类。然后创建该类的实例,并调用其相应方法来执行自定义标签。
# 3.3 Tag文件中常用指令
除了上述介绍过的tag指令和attribute指令外,还有一些常用指令可以在tag文件中使用。这些指令包括:
- variable指令:定义变量,在JSP页面中可以访问该变量。
- taglib指令:引入其他自定义标签库,在tag文件中可以使用其他自定义标签。
- include指令:包含其他静态资源,在tag文件中可以重用代码。
## variable指令
variable指令可以定义变量,在JSP页面中可以访问该变量。variable指令有以下属性:
- name-given:给定变量名。
- alias:给定别名。
- scope:给定作用域(AT_BEGIN 或 AT_END)。
- declare:是否声明变量(true 或 false)。
- description:给定描述信息。
例如:
```jsp
<%@ variable name-given="result" alias="res" scope="AT_BEGIN"
declare="true" description="计算结果"%>
```
这样就定义了一个名为result(别名为res)的变量,在JSP页面开始时声明,在JSP页面结束时销毁,在tag文件和JSP页面都可以访问。
## taglib指令
## taglib指令
taglib指令可以引入一个自定义标签库的定义,包括库路径、自定义标签。taglib指令的语法如下:
```jsp
<%@ taglib uri="uri" prefix="prefixOfTag" %>
```
其中,uri属性确定标签库的位置,prefix属性指定标签库的前缀。等价的XML语法如下:
```xml
<jsp:directive.taglib uri="uri" prefix="prefixOfTag" />
```
使用taglib指令后,就可以在tag文件中使用自定义标签了。自定义标签的格式为:
```jsp
<prefixOfTag:tagName attribute="value"/>
```
或者
```jsp
<prefixOfTag:tagName attribute="value"> 标记体 </prefixOfTag:tagName>
```
其中,prefixOfTag是taglib指令中定义的前缀,tagName是自定义标签的名称,attribute是自定义标签的属性,标记体是自定义标签的内容。
例如,假设有一个名为mytags.tld的标签库描述文件,其内容如下:
```xml
<taglib>
<tlib-version>1.0</tlib-version>
<jsp-version>2.0</jsp-version>
<short-name>mytags</short-name>
<uri>http://www.example.com/mytags</uri>
<tag>
<name>hello</name>
<tag-class>com.example.HelloTag</tag-class>
<body-content>empty</body-content>
</tag>
</taglib>
```
该文件定义了一个名为hello的自定义标签,其对应的类是com.example.HelloTag,其标记体类型是empty。
在一个名为test.tag的tag文件中,使用taglib指令来引入该标签库,并使用hello标签:
```jsp
<%@ tag pageEncoding="UTF-8" %>
<%@ taglib uri="http://www.example.com/mytags" prefix="my" %>
<my:hello/>
```
这样就可以在test.tag中调用hello标签了。假设com.example.HelloTag类的作用是输出一句问候语,那么在浏览器中访问test.tag时,就会看到类似下面的输出:
```html
Hello, this is a custom tag!
```
## include指令
include指令可以包含其他静态资源,在tag文件中可以重用代码。include指令的语法如下:
```jsp
<%@ include file="包含文件" %>
```
其中,file属性指定要包含的文件的相对路径或绝对路径。被包含的文件可以是任何文本文件,如HTML文件,JSP文件,tag文件等。被包含的文件中的内容会原样插入到include指令所在的位置,如果有JSP语句,则会被解析执行。
include指令的作用和include动作(`<jsp:include>`)类似,但有以下区别:
- include指令是在编译时执行,而include动作是在运行时执行。
- include指令是静态包含,只能包含静态资源,而include动作是动态包含,可以包含动态资源。
- include指令会导致被包含文件和当前文件合并为一个源文件,而include动作不会。
- include指令不能传递参数,而include动作可以。
例如,假设有一个名为header.tag的tag文件,其内容如下:
```jsp
<%@ tag pageEncoding="UTF-8" %>
<h1>这是一个标签头部</h1>
```
在另一个名为hello.tag的tag文件中,使用include指令来包含header.tag:
```jsp
<%@ tag pageEncoding="UTF-8" %>
<%@ include file="header.tag" %>
<p>你好,这是一个标签内容</p>
```
在JSP页面中引入并调用hello.tag:
```jsp
<%@ taglib prefix="my" tagdir="/WEB-INF/tags/" %>
<my:hello/>
``
# 总结
本文介绍了Tag文件和Tag标记的概念、用法和原理,以及Tag文件中常用的指令。Tag文件和Tag标记是实现代码复用和分离的一种有效方式,在Web开发中有广泛的应用。通过学习本文,读者可以掌握如何编写和使用Tag文件和Tag标记,以及如何利用不同的指令来增强Tag文件的功能。