学习编写标记文件(tag):
自定义标记的用途就是给程序员可以自定一些特定功能的标记, 以及封装代码, 达到分工, 重用性等
多种好处.
JSP规范2.0中新增了标记文件(tag file)的使用, 免除以前自定义标记必须为一个Java类, 以及必须
加上一个标记描述文件(tld)的编码难度.
以下我们来看标签文件的使用.
1. 存放:
一个标记文件以tag为後缀名, 以同一类型的检签放到同一个文件夹中组成一个标记库, 再放到
"/WEB-INF/tags/"中保存.
例如接下来我打算建立一组有关数学的标记库, 我在"/WEB-INF/tags/"下建立一个"maths"文件夹, 然
後就可以在"/WEB-INF/tags/maths/"下建立後缀名为tag的标记文件了.
现在我想先做一个数字相加的标记, 起名为"add.tag", 放到maths标记库下.
2. 语法:
标记文件其实就是一个jsp文件, 所以语法基本上跟jsp是一样的, 在第一行加上以下这个元素来告诉
服务器 它是一个标记文件:
<%@ tag %>
我们还要加上一些属性来告诉 服务器 这个标记文件的设定:
1) body-content - 设定这个标记的主体内容类型:
A. empty
这个是一个空标记.
B. scriptless
主体可以有内容, 而jsp容器会去处理里面的jsp元素, 换句话就是可以是
文本, EL表达式, 标准动作甚至另一个自定义标记.
C. tagdependent
主体可以有内容, 而jsp容器会把它们当作纯文件处理 .
2) pageEncoding - 设定这个标记的编码
我们的add标记是个空标记, 而编码是"UTF-8", 所以加上这样的一句:
<%@ tag body-content="empty" pageEncoding="UTF-8" %>
标记中使用以下这个元素来声明属性:
<%@ attribute %>
attribute元素也有几个属性:
1) name - 这个attribute的名称.
2) required - true/false, 是否必须的.
3) rtexprvalue - true/false, 这个attribute可否使用EL表达式, 否则为纯文本.
4) type - 设定这个attribute的类型, jsp容器会把结果自动转换成这个类.
我们的add.tag有两个属性, 分别代表两个要相加的数字, x跟y, 它们都是必须的, 可以用EL表达式:
<%@ attribute name="x" required="true" rtexprvalue="true" %>
<%@ attribute name="y" required="true" rtexprvalue="true" %>
那这个标记都设定好了, 那我们应该怎样读取这些传入的属性呢? 其实很简单, 标记文件就是一个
jsp文件, 这些输入的属性值都存放在作用域中, 所以利用EL表达式就可以了:
${x + y}
这个标记文件就完成了, 以下为完整代码, 你也可以直接打开"/WEB-INF/tags/maths/add.tag":
<%--
maths标记库add标记
功能: 把传入参数相加
参数:
x, 数字1, 必须
y, 数字2, 必须
--%>
<%@ tag body-content="empty" pageEncoding="UTF-8" %>
<%-- 声明属性 --%>
<%@ attribute name="x" required="true" rtexprvalue="true" %>
<%@ attribute name="y" required="true" rtexprvalue="true" %>
<%-- 内容 --%>
${x + y}
标记文件完成了, 那我们要怎样在jsp文件中调用它呢? 首先我们导入maths标记库, 跟调用标准动作
一样使用taglib指令, 但是把url属性换成tagdir, 指定我们自定义标记库的位置, 并给它一个前缀
名, 以下我们用"maths":
<%@ taglib tagdir="/WEB-INF/tags/maths/" divfix="maths" %>
然後我们就可以调用标准动作一样去使用它啦, 当然必须的属性一定要有, 不然会报错:
<maths:add x="10" y="10"/>
以下为调用add标记的jsp页的完整代码, 同样的你可以直接打开"/add.jsp":
<%-- maths标记库add标记的演试 --%>
<%@ page contentType="text/html; charset=UTF-8" language="java" %>
<%-- 调用自定义标记库maths --%>
<%@ taglib tagdir="/WEB-INF/tags/maths" divfix="maths" %>
<html>
<head>
<title>Maths标记库add标记演试</title>
</head>
<body>
结果:<br/>
<%-- 使用add标记 --%>
<maths:add x="10" y="10"/>
</body>
</html>
相信大家都了解基本工作原理了吧? 你可以把标记文件看作一个jsp页面, 你可以对它传入一些参数,
调用它的面页就像包含它一样, 所以你可以标记文件打上一句"HelloWorld", 一段html代码, 甚至包
含其他的动作, 调用它的面页就会显示, 大家可以打开"/helloworld.jsp"看一下, 它调用了别一个
标记库others里面的helloworld标记.
add标记是一个空标记, 我们学过body-content="scriptless", 那我们应该怎样去处理标记主体的数
据呢? 我们来新增一个新的标记库, 叫string, 再增加一个标记文件"show.tag", 同样的加上tab指
令告诉服务器 这个是一个标记文件, 这一次body-content属性改为scriptless:
<%@ tag body-content="scriptless" pageEncoding="UTF-8" %>
然後我们加入一个标准动作:
<jsp:doBody>
它的用途是读入标记的主体内容, 当没有指定要保存到的变量时, 它把内容直接输出到调用的页面上.
我们写一个"/show.jsp"来简单调用这个show标记:
?<%-- string标记库show标记的演试 --%>
<%@ page contentType="text/html; charset=UTF-8" language="java" %>
<%-- 调用自定义标记库string --%>
<%@ taglib tagdir="/WEB-INF/tags/string" divfix="string" %>
<html>
<head>
<title>string标记库trim标记演试</title>
</head>
<body>
<%-- 使用show标记 --%>
<string:show>
这个是标记的主体内容
</string:show>
</body>
</html>
<jsp:doBody>有三个属性:
1) var - 当指定这个变量, 读取的主体内容就会以String保存这个变量内, 不会直接输出页
面.
2) varReader - 用途跟var一样, 但是保存的不是一个String, 而是一个java.io.Reader.
3) scope - 变量保存到的作用域, 包括: page, request, session, application, 默认为
page.
接下来我们扩充string标记库, 加入一个新的标记"trim.tag", 同样的加入tag指令, 设定
body-content为scriptless代表它可以有主体内容, 因为我们会使用到核心标记库, 所以加上taglib
指令导入核心标记库, 并加入jsp:doBody指令读取主体内容并保存到变量body中:
<%@ tag body-content="scriptless" pageEncoding="UTF-8" %>
<%-- 导入核心标记库 --%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" divfix="c" %>
<%-- 把主体内容保存到body变量中, 没有指定作用域下, 保存在page --%>
<jsp:doBody var="body"/>
我们获得一个主体内容的字符串了, 那可以编写一段代码来把字符串中的空白去掉, 我们可以利用核
心标记库的一个标记forTokens来把字符串跟据空白来分割, 再输出就可以达到这个效果了, 以下给出
这个标记的完整代码, 大家也可以直接打开"/WEB-INF/tags/string/trim.tag":
<%--
string标记库trim标记
功能: 把标记主体的内文中的空白去掉
--%>
<%@ tag body-content="scriptless" pageEncoding="UTF-8" %>
<%-- 导入核心标记库 --%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" divfix="c" %>
<%-- 把主体内容保存到body变量中, 没有指定作用域下, 保存在page --%>
<jsp:doBody var="body"/>
<%-- 实现把主体字符串的空白去掉 --%>
<c:forTokens var="char" items="${body}" delims=" ">${char}</c:forTokens>
这里有一个要注意的, 最後一行必须要这样写, 什么意思? 很多人(包括我)可能会这样写:
<c:forTokens var="char" items="${body}" delims=" ">
${char}
</c:forTokens>
这个是好习惯, 代码看上去整齐多了, 但是jsp容器会把换行换成一个空白...哈哈, 不懂的自己试一
下吧^^
这个演试可以看到标记文件不单没有以前标记处理类加上一个tld来得那么麻烦, 而且在一个标记文
件中, 我们可以再导入另一个标记库来扩充功能, 实在是非常方便.
相信大家都对标记文件的基本应用都有一定的了解了, 下面我们来看标记文件的其他功能.
如果我们想建立一些标记文件供网页人员使用, 而且这个标记文件支持所有html元素的属性, 那你可
能立刻就想到, 我们必须为每一个可能出现的html标记属性建立一个属性标记, 那是多费时的工作,
所以我们可以在tab指令中加上dynamic-attributes这个属性, 表示这个标记可以容许任何的属性值
出现, jsp容器会自动把所有未声明的属性保存到一个以你给出的值为命名的Map集合中, 而这个集合
保存在page作用域中. 我们来新建一个标记文件到others标记库中, 并加上以下代码行:
<%@ tag body-content="empty" pageEncoding="UTF-8"
dynamic-attributes="attributesList" %>?
当调用这个标记时, 所有未被声明的属性都会保存到"attributesList"这个Map集合中, 我们可以用
核心标记库的forEach把它们列出, 以下为完整代码, 你也可以直接打开"/WEB-INF/tags/others/
showAttributes.tag":
? <%--
others标记库showAttributes标记
功能: 读取dynamic-attributes所保存的属性集合, 输出到调用的页面上.
--%>
<%@ tag body-content="empty" pageEncoding="UTF-8"
dynamic-attributes="attributesList" %>?
<%-- 导入核心标记库 --%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" divfix="c" %>
<%-- 输出所有属性 --%>
<p>本标记包含了以下的动态属性</p>
<%-- 使用forEach遍历"attributesList"集合并输出到调用页面 --%>
<c:forEach var="item" items="${attributesList}" varStatus="i">
<p>${i.index + 1}. ${item.key}: ${item.value}</p>
</c:forEach>
另外编写一个jsp页面调用showAttributes标记, 以下为完整代码, 你也可以直接打开
"/showAttributes.jsp":
? <%-- others标记库showAttributes标记的演试 --%>
<%@ page contentType="text/html; charset=UTF-8" language="java" %>
<%-- 调用自定义标记库others --%>
<%@ taglib tagdir="/WEB-INF/tags/others/" divfix="others" %>
<html>
<head>
<title>others标记库showAttributes标记演试</title>
</head>
<body>
<others:showAttributes param1="hello" param2="on9" color="red"/>
</body>
</html>
下来我们看一个属性的扩展功能 - 属性片段(attribute fragment), 先解译什么是片段, 大家可以
把片段看作一段jsp代码, JSP规范中所谓的jsp fragment, 例如我们之前使用了jsp:doBody读取的主
体内容就是一个片段. 我们可以将一段巳命名的片段(named fragment)作为一个标记的属性使用, 并
而在标记中多次或一次调用这个传入的片段. 要调用这个片段, 我们使用另一个标淮动作:
<jsp:invoke/>
它是一个空标记, 有以下的属性:
1) fragment - 要调用的片段名.
2) var - 给出变量名, 把片段经过jsp容器计算过之後的结果作为字符串保存.
3) varReader - 同上, 不过将结果作为一个java.io.Reader保存.
4) scope - 作用域= =, 有var就有它, 不多说了, 默认page.
当然, 叫做属性片段, 我们必须告诉jsp容器标记中那些标记属性的内容会是片段而不是静态文本. 我
们可以在属性元素上加上fragment="true"这个属性:
<%@ attribute name="name" fragment="true" %>
接下来我们再编写一个标记来演试一下属性片段的应用, 我们在others标记库中新增一个"invoke"
标记, 加上tag指令, 建立两个属性fragment1跟fragment2, 用来接收两个属性片段, 以下给出完整
代码, 大家也可以直接打开"/WEB-INF/tags/others/invoke.tag":
<%--
others标记库invoke标记
功能: 演试属性片段
--%>?
<%@ tag body-content="scriptless" pageEncoding="UTF-8" %>
<%@ attribute name="fragment1" fragment="true" %>
<%@ attribute name="fragment2" fragment="true" %>
<%-- 调用标准动作jsp:invoke显示读取的属性片段 --%>
<p style="font-size:24px; font-weight:bold">这里输出属性片段一的计算结果:</p>
<jsp:invoke fragment="fragment1"/>
<p style="font-size:24px; font-weight:bold">这里输出属性片段二的计算结果:</p>
<jsp:invoke fragment="fragment2"/>
<%-- 调用标准动作jsp:doBody显示读取的主体内容 --%>
<p style="font-size:24px; font-weight:bold">这里输出主体内容:</p>
<jsp:doBody/>
上面可以看到我们调用了两次<jsp:invoke fragment="xxx"/>, 大家可以把它看作一个占位符, 它的
位置就是读取的属性片段的计算结果. 最後我们再一次调用<jsp:doBody/>来读取主体内容.
不懂? 没关系, 下面我们先把调用页面"invoke.jsp"建立好, 细心观察浏览器出来的效果, 大家就可
以了解为什么我会说把<jsp:invoke/>看作一个占位符, 其实<jsp:doBody/>也是同一个工作原理, 下
面给出"invoke.jsp"的完整代码, 同样大家可以直接打开"/invoke.jsp":
<%-- others标记库invoke标记的演试 --%>
<%@ page contentType="text/html; charset=UTF-8" language="java" %>
<%-- 调用自定义标记库others --%>
<%@ taglib tagdir="/WEB-INF/tags/others" divfix="others" %>
<%-- 调用自定义标记库string --%>
<%@ taglib tagdir="/WEB-INF/tags/string" divfix="string" %>
<html>
<head>
<title>others标记库invoke标记演试</title>
</head>
<body>
<%-- 使用invoke标记 --%>
<others:invoke>
<jsp:attribute name="fragment1"> <%-- 第一个片段我们引用helloworld标记 --%>
<others:helloworld/>
</jsp:attribute>
<jsp:attribute name="fragment2"> <%-- 第二个片段我们引用trim标记 --%>
<string:trim>
I am a boy!
</string:trim>
</jsp:attribute>
<jsp:body> <%-- 这里就是主体内容 --%>
这里就是<font color="red" size="25">主体内容</font>啦
</jsp:body>
</others:invoke>
</body>
</html>?
(上面代码的排版有点乱, 注释本来是自己开新行的, 但是属性之间如果插入注释, 服务器 会报错= =)
这个jsp页面包含我们今天所建立的另外两个标记"helloworld"跟"trim", 它们分别就是两个属性片段
的内容, 另外大家会看到<jsp:body>...</jsp:body>这个没介绍过的标准动作, 因为一个标记的主体
如果巳经包含了<jsp:attribute/>元素的话, 主体的内容就必须放到<jsp:body/>之内, jsp容器才可
正常的分别到哪些是属性, 哪个是主体, 所以以下的语法是不容许的:
<others:invoke>
<jsp:attribute name="fragment1">
属性一的内容
</jsp:attribute>
<jsp:attribute name="fragment2">
属性二的内容
</jsp:attribute>
<p>这里是主体内容...</p>
</others:invoke>
下来留一个小测试给大家, 打开"/invoke.jsp", 在<jsp:body/>标记内加上这一段代码:
${"a" == "a"}
重载"/invoke.jsp", 大家会发现在网页的末尾, 出现了"true"一字, 然後我们来开"/WEB/INF/
tags/others/invoke.tag", 把tag指令中的body-content属性改为"tagdependent", 重载
"/invoke.jsp"看有什么不一样?
接下来这个会是个难点, 这个部份希望大家可以返覆多看几遍, 试著修改一下例题来了解一下参数不
同会产生什么不一样的结果.
我们一直的工作流程都是, 一个jsp页面调用一个自定义的标记, 给它一些属性, 我们在标记里读取它
们, 然後处理代码, 返回给jsp容器, jsp容器计算结果後给jsp页面输出静态的文本, 那我们可不可以
在处理代码後, 把结果以变量的形式返回呢? 就好像我们写一个有返回值的函数一样? 可能大家会想
想我们有<c:set/>这个声明/赋值的标准动作, 但是想一下, 标记文件跟jsp页面是两个不同的page作
用域, 我们如果要传递变量的话就只有把变量放在session/application中了, 那不是很麻烦? 万一我
在jsp接收变量後没有把这个变量的内存空间释放掉, 那服务器 有10GB内存也不够用了, 所以JSP规范
中提供了一个指令:
<%@ variable %>
它可以让我们在标记文件中的声明一个输出变量, 让jsp页面读取, 它有以下的属性:
1) name-given - 给这个变量取名.
2) name-from-attribute - 这个变量名由一个属性来决定(跟name-given只可选一).
3) alias - 给输出变量取别名(配合name-from-attribute使用).
4) variable-class - 给出输出变量类型, jsp容器会自动转换, 如果没指定为String.
5) scope - 输出变量在jsp页面上的更新模式, 可取值为: AT_BEGIN/AT_END/NESTED, 默认
为"NESTED".
相信第1,4属性大家都看懂, 第2,3属性我们在下一个例子中再说明, 我们来说明一下scope属性.
scope的3个可取值代表什么意思呢?
1) AT_BEGIN - 输出变量在标记文件的<jsp:doBody/>/<jsp:invoke/>之前及标记文件执行结
束後更新输出变量的值.
2) AT_END - 输出变量只有在标记文件执行结束後更新输出变量的值.
3) NESTED - 输出变量在标记文件的<jsp:doBody/>/<jsp:invoke/>之前更新输出变量的值,
在标记文件结束後, 将会把输出变量还原到在调用标记前的值
不懂? 我也搞了4个小时, 返覆的试验才清楚这三个取值有什么不一样. 现在不了解没有关系, 它们关
系到在标记文件中使用到<jsp:doBody/>/<jsp:invoke/>时, 其他的代码在这些动作之前之後的不同,
我们现在只需要记得一个不同就好了. 如果你需要把输出变量输出到jsp页面上(= =不然呢?), 就用
"AT_BEGIN", 如果你只需要在标记执行中在jsp页面读取到输出变量, 那就用"NESTED".
可能大家还是会搞混了, 我不就是为了输出一个变量到jsp页面吗? 你给我一个"NESTED"干吗? 其实输
出变量还有一个用途, 就是让标记文件可以把变量传到另一个标记文件上. 如果我的标记文体主体内
容是另一个标记, 我想把值传给它而巳, 并没有需要传到jsp页面的作用域上时, "NESTED"就有用了,
因为还原的意思是, 如果调用的jsp页面本来就没有声明这个输出变量, 那就代表输出变量只有在标记
主体执行时出现过, 结束後它就卸载了.
下面我们就来看一个例子吧(还是不懂? 就只用"AT_BEGIN"吧, 管它还不还原), 以下建立了一个新的
标记文件"variable.tag"在others标记库中, 同样的加入tag指令, 导入核心标记库(?), 以下给出完
整代码, 大家也可以直接打开"/WEB-INF/tags/others/variable.tag":
<%--
others标记库variable标记
功能: 演试variable指令输出变量的功能
--%>
<%@ tag body-content="empty" pageEncoding="UTF-8" %>
<%-- 导入核心标记库 --%>
<%@ taglib divfix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%-- 声明一个输出变量, 取名为"v" --%>
<%@ variable name-given="v" scope="AT_BEGIN" %>
<%-- 对输出变量赋值 --%>
<c:set var="v" value="这个就是标记文件的输出的内容"/>
为什么要使用要<c:set/>动作呢? 因为variable指令只是声明了一个变量, 我们还需要给它赋值, 下
面同样我们再建立一个"/variable.jsp", 看看jsp页面是如何读取到这个变量, 以下给出完整代码,
大家也可以直接打开"/variable.jsp":
<%-- others标记库variable标记的演试 --%>
<%@ page contentType="text/html; charset=UTF-8" language="java" %>
<%-- 导入others标记库 --%>
<%@ taglib tagdir="/WEB-INF/tags/others" divfix="others" %>
<html>
<head>
<title>others标记库variable标记演试</title>
</head>
<body>
<%-- 调用variable标记并显示 --%>
<others:variable/>
输出变量v: ${v}
</body>
</html>?
有了variable指令, 我们就可以把一个标记文件处理後的结果, 放到输出变量中, 再给它指定一个类
型, 作为另一个标记文件的属性传递, 是不是很方便呢?
但是问题来了, 这个输出变量的取名是标记文件定义的, 如果调用它的页面也有这个变量那怎办? 所
以我们下面来了解一下variable指令上"name-from-attribute"跟"alias"这两个属性, 怎样可以达成
"取别名"的效果.
我们来新建一个标记文件"alias"在"others"标记库中, 同样加入tag指令, 导入核心标记库, 然後我
声明一个属性, 它的作用就是用来存放输出变量的取名, 让调用页面可以传入一个字符值来决定输出
变量的取名, 然後我们使用variable指令:
<%@ variable name-from-attribute="output" alias="v" scope="AT_END" %>
"name-from-attribute"属性告诉jsp容器这个输出变量的取名为那个属性的值, 而"alias"属性就为
这个输出变量取一个别名, 以便在标记里使用这个变量, 以下给出完整代码, 大家也可以直接打开
"/WEB-INF/tags/others/alias.tag":
<%--
others标记库alias标记
功能: 演试variable指令的取别名功能
--%>
<%@ tag body-content="empty" pageEncoding="UTF-8" %>
<%-- 导入核心标记库 --%>
<%@ taglib divfix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%-- 存放输出变量的名称, 记得这个属性必须为静态文本及必须的 --%>
<%@ attribute name="output" required="true" rtexprvalue="false" %>
<%-- 声明输出变量, 在标记文件中使用别名为"v", 而在调用页面上的名称则
由属性output决定 --%>
<%@ variable name-from-attribute="output" alias="v" scope="AT_END" %>
<%-- 为输出变量赋值 --%>
<c:set var="v" value="<p>这个就是标记文件的输出的内容</p>"/>
同样的, 我们建立一个"/alias.jsp"来演试一下, 以下给出完整代码, 大家也可以直接打开
"/variable.jsp":
<%-- others标记库alias标记的演试 --%>
<%@ page contentType="text/html; charset=UTF-8" language="java" %>
<%-- 导入others标记库 --%>
<%@ taglib tagdir="/WEB-INF/tags/others" divfix="others" %>
<html>
<head>
<title>others标记库alias标记的演试</title>
</head>
<body>
<%-- 调用alias标记, 对output属性赋值就可以自定义输出变量名 --%>
<others:alias output="super"/>
${super}
<%-- 试一下用别的名称 --%>
<others:alias output="haha"/>
${haha}
</body>
</html>?
使用了"name-from-attribute"就可以避免命名冲突了, 记得存放输出变量取名的属性必须把
"rtexprvalue"设为假, 不然服务器 也会报错的.
以上就是JSP规范2.0中新增的标记文件的语法介绍了^^
3. 打包
今天计一下我们都创建了8个自定义动作, 如果我们想要跟人家分享我的作品, 或者要去第三方部署的
话, 那就麻烦了, 所以以下我们学习怎样去把我们的标记库打包.
第一步, 我们先改变一下文件结构, 在网站根目录下, 创建一个"META-INF"文件夹, 然後把"WEB-INF"
里面的"tags"文件夹复制过去, 形成以下文件结构:
网站根目录/
META-INF/
tags/
maths/
...tag文件...
others/
...tag文件...
string/
...tag文件...
WEB-INF/
...tag文件夹...
...jsp文件...
我们先打包string标记库, 所以把"maths"跟"others"文件夹删除, 然後我们需要创建一个tld标签描
述文件(对, 又是它, XML又来了)在"META-INF"下, 复制下面的内容到文件开始:
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLScheme-instance"
xsi:schemeLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/sml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
<!-- 标记库版本 -->
<tlib-version>1.0</tlib-version>
<!-- 命名空间前缀 -->
<short-name>string</short-name>
<!-- 文件夹名 -->
<uri>string</uri>
<!-- 包含的标记 -->
<tag-file>
<!-- 标记名 -->
<name>show</name>
<!-- 路径 -->
<path>/META-INF/tags/string/show.tag</path>
</tag-file>
<tag-file>
<name>trim</name>
<path>/META-INF/tags/string/trim.tag</path>
</tag-file>
</taglib>
taglib元素的一大串属性不用管它, 这个不是我们的讨论范围, 以後要写tld文件就复制过去就对了,
版本跟命名空间前缀也可以不管, 那个是给设计工具使用的, 没什么影响, uri元素必须为标记库的
文件夹名, 之後的tag-file元素声明了这个标签库里面有什么标记, 语法为:
...
<tag-file>
<name>标记名</name>
<path>相对路径</path>
</tag-file>
...
完成後打开"命令提示符", 转到网站的根目录, 输入下面的命令:
jar cvf string.jar META-INF
完成後大家就会看到根目录下新增了一个jar文件"string.jar", 把它放到"/WEB-INF/lib"之下就OK
了. 那我们再新建一个jsp页面来调用这个巳经打包好的标记库吧, 以下为"jar.jsp"的完整代码,
同样大家可以直接打开"/jar.jsp":
<%-- 使用jar文件导入标记库的演试 --%>
<%@ page contentType="text/html; charset=UTF-8" language="java" %>
<%-- 导入string标记库包 --%>
<%@ taglib uri="string" divfix="string" %>
<html>
<head>
<title>使用jar文件导入标记库的演试</title>
</head>
<body>
<%-- 调用trim标记 --%>
<string:trim>
Please trim me!
</string:trim>
</body>
</html>?