一. tag file 简介

  tag file从两个方面简化了自定义标签的开发。首 先,tag file无须提前编译,直到第一次被调用才会编 译。除此之外,仅仅使用JSP语法就可以完成标签的扩 展定义,这意味着不懂Java的人也能够进行标签自定义 了。

   其次,标签库描述文件也不再需要了。原先需要在 标签库描述文件里定义标签元素的名字,以及它所对应 的action。使用tag file的方式,tag file名和action相同, 因此不再需要标签库描述文件了。

  JSP容器提供多种方式将tag file编译成Java的标签 处理类。例如Tomcat将tagfile翻译成继承于 javax.servlet.jsp.tagext.SimpleTag接口的标签处理类。

  一个tag file和JSP页面一样,它拥有指令、脚本、 EL表达式、动作元素以及自定义的标签。一个tag file 以tag和tagx为后缀,它们可以包含其他资源文件。一个 被其他文件包含的tag file应该以tagf为后缀。

  tag文件必须放在应用路径的WEB-INF/tags目录下 才能生效。和标签处理类一样,tag 文件可以被打到jar 包里。

   tag file中也有一些隐藏对象,通过脚本或者EL表 达式可以访问这些隐藏对象。表7.1列出了这些隐藏对 象。这些隐藏对象和JSP隐藏对象类 似。

tag file中可用的隐藏对象
对象 类型
request javax.servlet.http.HttpServletRequest
response javax.servlet.http.HttpServletResponse
out javax.servlet.jsp.JspWriter
session javax.servlet.http.HttpSession
application javax.servlet.ServletContext
config javax.servlet.ServletConfig
jspContext javax.servlet.jsp.JspContext

二.第一个 tag file

1. 下面的这个例子包含一个tag文件和一个使用这个tag文 件的JSP页面。例子的目录结构如图所示。

 

  这个tag file的名称是firstTag.tag,代码如下所 示。

<%@ tag import="java.util.Date" import="java.text.DateFormat"%>
<%
DateFormat dateFormat =
DateFormat.getDateInstance(DateFormat.LONG);
Date now = new Date(System.currentTimeMillis());
out.println(dateFormat.format(now));
%>

  tag file和JSP页面是很相似 的。在firstTag.tag文件里包含了一个tag指令和一个脚本 片段,其中tag指令里又有两个import属性。接下来,只 需要将这个tag file放到WEB-INF/tags目录下就可以使用 了。注意tag file名和标签的名字是一样的,例如这个 firstTag.tag的tag file对应的标签名即为firstTag。

2. 下面是一个使用firstTag.tag文件的JSP实例: firstTagTest.jsp。

firstTagTest.jsp页面

<%@ taglib prefix="easy" tagdir="/WEB-INF/tags" %>
Today is <easy:firstTag/>

效 果:

三. tag file 指令

和JSP页面一样,tag file可以使用指令来指挥JSP容 器如何编译这个tag file。tag file的指令语法和JSP是一 样的:

<%@ directive (attribute="value")* %>

星号(*)表示括号内的可以重复0次或者多次,上 面的指令也可以写成下面这种更直白的样子:

<%@ directive attribute1="value1" attribute2="value2" ... %>

属性必须被单引号或者双引号包裹,<%@之后和 %>之前的空格加不加都不影响正确性,但是为了可读 性,建议加上空格。除了page指令,其他所有的JSP指 令都可以用于tag file。在tag file中,可以使用tag指令代 替page指令。另外,你还可以使用两个新指令: attribute 和variable。下表展示了所有可以在tag file中使 用的指令。

tag file指令
指令 描述
tag 作用与JSP页面中的page指令类似
include 用于将其他资源导入tag file中
taglib 用于将自定义标签库导入tag file中
attribute 用于将自定义标签库导入tag file中
variable 用于将自定义标签库导入tag file中

1. tag指令

tag指令和JSP页面中的page指令类似。以下是它的 使用语法:

<%@ tag (attribute="value")* %>

也可以使用下面这种更直白的表达式:

<%@ tag attribute1="value1" attribute2="value2" ... %>
tag指令的属性
属性 描述
display-name 在XML工具中显示的名称。默认值是不包含后缀的tagfile名
body-content 指定标签body的类型,body-content属性值有empty、tagdependent、scriptless,默认值是scriptless
dynamicattributes 指定tagfile动态属性的名称。当dynamicattributes值被设定时,会产生一个Map来存放这些动态属性的名称和对应的值
small-icon 指定一个图片路径,用于在XML工具上显示小图标。一般不会用到
large-icon 指定一个图片路径,用于在XML工具上显示大图标。一般也不会用到
description 标签的描述信息
example 标签使用实例的描述
language tagfile中使用的脚本语言类型。当前版本的JSP中,该值必须设为“java”
import 用于导入一个java类型,和JSP页面中的import相同
pageEncoding 指定tagfile使用的编码格式,可以使用“CHARSET”中的值。和JSP页面中的pageEncoding相同

   除了import属性,其他所有的属性在一个tag指令或 一个tag file中都只能出现一次。例如,以下的tag file就 是无效的,因为body-content属性在同一个tag file中出 现了多次:

<%@ tag display-name="first tag file" body-content="scriptless"
%>
<%@ tag body-content="empty" %>

2. include 指令

  ag file中的include指令和JSP页面中的include指令 是一样的。可以使用这个指令来将外部文件导入到tag file中。当你有一个公共资源文件有可能用在多个tag file中时,include指令将能够发挥它的作用。这个公共 资源文件可以是静态文件(例如HTML文件),也可以 是动态文件(例如其他tag file)。

注意: 被导入的tag file片段必须以tagf为后缀。

例如: includeDemoTag.tag文件就导入了 一个静态文件(included.html)和一个动态文件 (included.tagf)。

includeDemoTag.tag文件

<%@ tag language="java" pageEncoding="UTF-8"%>
This tag file shows the use of the include directive.
The first include directive demonstrates how you can include
a static resource called included.html.
<br/>
Here is the content of included.html:
<%@ include file="included.html" %>
<br/>
<br/>
The second include directive includes another dynamic resource:
included.tagf.
<br/>
<%@ include file="include.tagf" %>

included.html 和included.tagf文件它们都和tag file放在同一个目录下。注意: 被导入的tag file片段必须以tagf为后缀。

included.html 文件

<table>
<tr>
<td><b>Menu</b></td>
</tr>
<tr>
<td>CDs</td>
</tr>
<tr>
<td>DVDs</td>
</tr>
<tr>
<td>Others</td>
</tr>
</table>

included.tagf文件

<%
out.println("hello from included.tagf");
%>

includeDemoTagTest.jsp 页面

<%@ taglib prefix="easy" tagdir="/WEB-INF/tags" %>
<easy:includeDemoTag/>

3.taglib指令

  可以通过taglib指令在tag file中使用自定义标签。 taglib指令的语法如下:

<%@ taglib uri="tagLibraryURI" prefix="tagPrefix" %>

  其中uri属性用来指定与前缀相关联的标签库描述 文件的绝对路径或相对路径。

  prefix属性用来定义自定义标签的前缀。

   使用taglib指令,你可以像下面那样使用不包含 content body的自定义标签:

<prefix:tagName/>

  当然,也可以使用包含content body的自定义标 签:

<prefix:tagName>body</prefix:tagName>

taglibDemo.tag导入了firstTag.tag来显 示服务器日期,taglibDemoTest.jsp调用了 taglibDemo.tag。

taglibDemo.tag页面

<%@ taglib prefix="simple"  tagdir="/WEB-INF/tags"  %>
The server's date: <simple:firstTag />

jsp页面

<easy:IncludeDemoTag />

4. attribute 指令

  attribute用于设定tag file中标签的属性。它和标签 库描述文件中的attribute元素等效。下面是该指令的语 法:

<%@ attribute (attribute="value")* %>

  也可以用以下更直白的方式表达:

<%@ attribute attribute1="value1" attribute2="value2" ... %>

attribute指令的属性参见下表。其中只有name属性 是必须的。

attribute指令的属性
属性 描述
name 用于设定该属性的名称。在一个tag file中,每个属性的名称必须是唯一的
required 用于设定该属性是否是必须的。值可以取true或false,默认值为flase
fragment 用于设定该属性是否是fragment。默认值为false
rtexprvalue 用于设定该属性的值是否在运行时被动态计算。值可以取true或false,默认值为true
type 用于设定该属性的类型,默认值为java.lang.String
description 用于设定该属性的描述信息

   下面是一个例子,encode.tag文件可用 于对一个字符串进行HTML编码。这个encode标签定义 了一个input属性,该属性的类型是java.lang.String。

encode.tag文件

<%@ tag language="java"   pageEncoding="UTF-8"  %>
<%@ attribute name="input" required="true" %>
<%!
private String encodedHtmlTag(String tag){
if ( tag == null) return null;
int length = tag.length();
StringBuilder encodedTag = new StringBuilder( * length);
for( int i =; i < length; i++)
{
char c = tag.charAt(i);
if( c == '<')
encodedTag.append("&lt;");
else if ( c == '>')
encodedTag.append("&gt;");
else if ( c == '&')
encodedTag.append("&amp;");
else if ( c == '"')
encodedTag.append("&qout");
else if ( c == ' ')
encodedTag.append("&nbsp;");
else
encodedTag.append(c);
}
return encodedTag.toString();
}
%>
<%=encodedHtmlTag(input) %>

encodeTagTest.jsp文件

<%@ taglib prefix="easy" tagdir="/WEB-INF/tags" %>
<easy:encode input="<br/> means changing line"/>

5. variable 指令

   有时候我们需要将tag file中的一些值传递到JSP页 面。这时候通过variable来完成。tag file中的variable指 令和标签库描述文件中的variable元素类似,它用于定 义那些需要传递到JSP页面的变量。

   tag file支持多个variable指令,这意味着可以传递 多个值到JSP页面。相对而言,attribute 指令的作用与 variable相反,它用于将值从JSP页面传递到tag file。

variable指令的语法如下:

<%@ variable (attribute="value")* %>

也可以用下面这样更直白的表达方式:

<%@ variable attribute1="value1" attribute2="value2" ... %>
variable属性
属性 描述
name-given 变量名。在JSP页面的脚本和EL表达式中,可以使用该变量名。如果指定了name-from-attribute属性,那么name-given属性就不能出现了,反之亦然。name-given的值不能和同一个tag file中的属性名重复
name-from-attribute 和name-given属性类似,由标签属性的值来决定变量的名称。如果namefrom-attribute和name-gien属性同时出现或者都不出现的话会出现错误
alias 设定一个用来接收变量值的局部范围
variableclass 变量的类型。默认为java.lang.String
declare 设定该变量是否声明。默认值为false
scope 用于指定该变量的范围。可取的值为AT_BEGIN、AT_END、和NESTED。默认值为NESTED
description 用于描述该变量

  你或许会奇怪,既然JSP页面可以调用JspWriter来 接收变量值了,为什么还需要通过variable指令来传递 变量值呢。那是因为通过JspWriter只能简单地将一个 String传递到JSP页面,灵活性很差。举一个例子,清单 7.1中的firstTag.tag用于输出服务器当前日期的长格式。 但是如果你还需要输出服务器日期的短格式的话,就必 须再写一个tag file。写两个功能类似的tag file显然是冗 余工作。如果使用变量指令,就没有这样的问题了,只 需要在tag file中定义longDate和shortDate两个变量就可 以了。

例如,varDemo.tag提供了输出服务 器当前日期长格式和短格式的两个功能,它定义了两个 变量:longDate和shortDate。

<%@ tag language="java"   pageEncoding="UTF-8" %>
<%@ tag import="java.util.Date" import="java.text.DateFormat" %>
<%@ variable name-given="longDate" %>
<%@ variable name-given="shortDate" %>
<%
Date now = new Date();
DateFormat longFormat = DateFormat.getDateInstance(DateFormat.LONG);
DateFormat shortFormat = DateFormat.getDateInstance(DateFormat.SHORT);
jspContext.setAttribute("longDate", longFormat.format(now));
jspContext.setAttribute("shortDate",shortFormat.format(now));
%>
<jsp:doBody />

  注意,这里使用了jspContext.setAttribute方法来设 置变量。jspContext是一个隐藏对象。JSTL中的set标签 也能实现同样的功能,如果对JSTL熟悉,可以使用set 标签来代替setAttribute方法。JSTL在第5章“JSTL”中介 绍过。 同时需要注意的是,这里使用了doBody动作元素 来调用这个标签体。

varDemoTest.jsp页面

<%@ taglib prefix="tags" tagdir="/WEB-INF/tags" %>
Today's date:
<br/>
<tags:varDemo>
In long format: ${longDate}
<br/>
In short format: ${shortDate}
</tags:varDemo>

  在很多情况下都需要用到变量。比如说,你希望实 现一个这样的功能:根据产品标识从数据库中获取该产 品的详细信息。你可以通过一个属性来传递产品标识。 然后可以用多个变量来保存产品的详细信息,每个变量 对应为产品的每个属性。最终,你会用到例如name、 price、description、imageUrl等变量。

四. doBody

  doBody动作元素只能在tag file中使用,它用来调用 一个标签的本体内容。

  doBody动作元素也可以有属性。你可以通过这些 属性来指定某个变量来接收主体内容,如果不使用这些 指令,那么doBody动作元素会把主体内容写到JSP页面 的JspWriter上。

doBody的属性
属性 描述
var 用于保存标签主体内容的变量值,主体内容就会以java.lang.String的类型保存这个变量内。var和varReader属性只能出现一个
varReader 用于保存标签主体内容的变量值,主体内容就会以java.io.Reader的类型保存这个变量内。var和varReader属性只能出现一个
scope 变量保存到的作用域

   下面的这个例子说明了如何用doBody来调用标签 本体内容并将内容保存在一个叫作referer的变量中。假 设你有一个卖玩具的网站,并且在多个搜索引擎上做了 这个玩具网站的广告。现在你想要知道每个搜索引擎为 玩具网站带来的流量有多少转化成了购买行为。为了做 到这点,你可以记录每个网站首页访问的referer头部信 息,使用一个tag file来将referer头信息保存到session属 性中。如果某个用户在后续购买了产品,就可以从 session属性中获得referer头信息,并记录在数据库中。

   这个例子包含了一个HTML文件 (searchEngine.html)、两个JSP文件(main.jsp 和 view Referer.jsp)以及一个tag file (doBodyDemo.tag)。 main.jsp页面是玩具网站的首页,使用了doBodyDemo 标签来保存referer头信息。viewReferer.jsp页面用来查 看收集到的referer头信息。如果直接通过URL访问 main.jsp,那么referer头信息即为null。因此你必须通过 searchEngine.html来链接到main.jsp页面。

doBodyDemo.tag页面

<jsp:doBody var="referer" scope="session"/>

  没错,doBodyDemo.tag只有一行:一个doBody动 作元素。它指定了一个叫作referer的session属性来保存标签本体内容。

main.jsp页面

Your referer header: ${header.referer}
<br/>
<tags:doBodyDemo>
${header.referer} <!-- 这个值会传给doBodyDemo.tag 里的 referer1 变量-->
</tags:doBodyDemo>
<a href="viewReferer.jsp">View</a> the referer as a Session attribute.

main.jsp页面通过文本和EL表达式输出referer头信息,紧接着,输出一个指向ViewReferer页面的链接

viewReferer.jsp页面

The referer header of the previous page is ${sessionScope.referer1}<!-- 打印refere1的值 -->

浏览器结果

五. invoke

  invoke动作元素和doBody类似,在tag file中,可以 使用它来调用一个fragment。还记得在定义属性的 attribute指令中有一个fragment属性,它的值可以是true 或者false。如果fragment值为true,那么这个属性就是 一个fragment,这意味着可以从tag file中多次调用。 invoke动作元素也有多个属性,表7.7展示了invoke动作 元素中的全部属性,其中fragment属性是必须的。

invoke动作元素的属性
属性 描述
fragment 要调用的fragment的名称
var 用于保存片段主体内容的变量值,主体内容就会以java.lang.String的类型保存这个变量内。var和varReader属性只能出现一个
varReader 用于保存标签主体内容的变量值,主体内容就会以java.io.Reader的类型保存这个变量内。var和varReader属性只能出现一个
scope 变量保存到的作用域

  invokeDemo.tag是一个invoke动作元 素的例子。

invokeDemo.tag 文件

<%@ tag language="java" pageEncoding="UTF-8"%>
<%@ attribute name="productDetails" fragment="true" %>
<!-- 因为invoke 是用来调用fragment 的,如果fragment="false" 的话 连续按F5刷新页面会报错 -->
<%@ variable name-given="productName" %>
<%@ variable name-given="description" %>
<%@ variable name-given="price" %>
<%
jspContext.setAttribute("productName", "Pelesonic DVD Player");
jspContext.setAttribute("description","Dolby Digital output through coaxial digital-audio jack,"
+" 500 lines horizontal resolution-image digest viewing");
jspContext.setAttribute("price",);
%>
<jsp:invoke fragment="productDetails" />

  invokeDemo.tag中使用了attribute指令,并且将 fragment属性值设为true。另外还定义了三个变量。最 后调用了productDetails的fragment。由于在invoke动作 元素中,var和varReader都没有设置,因此fragment的内 容将直接传递到JSP页面的JspWriter中。

invokeTest.jsp页面

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="easy" tagdir="/WEB-INF/tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Product Details</title>
</head>
<body>
<easy:invokeDemo>
<jsp:attribute name="productDetails">
<table width="" border="" cellspacing="">
<tr>
<td><b>Product Name</b></td>
<td>${productName}</td>
</tr>
<tr>
<td><b>Description</b></td>
<td>${description}</td>
</tr>
<tr>
<td><b>Price</b></td>
<td>${price}</td>
</tr>
</table>
</jsp:attribute>
</easy:invokeDemo>
</body>
</html>

浏览器结果

jsp 标签文件的更多相关文章

  1. jsp2.0+中的标签文件,JSP Fragment技术

    刚进新公司不久,今天在看到项目中用到了.tag文件.刚开始我还以为这个是第三方类似freemarker的模板技术.问了下项目组的其他人员,原来这是jsp2.0以来就有的JSP Fragment技术.以 ...

  2. Servlet和JSP之标签文件学习

    在上一篇文章中介绍了自定义标签的用法,接下来介绍标签文件的用法啦. tag file指令 tag file简介 用tag file的方式,无需编写标签处理类和标签库描述文件,也可以自定义标签.tag ...

  3. java web学习总结(二十七) -------------------JSP标签介绍

    一.JSP标签介绍 JSP标签也称之为Jsp Action(JSP动作)元素,它用于在Jsp页面中提供业务逻辑功能,避免在JSP页面中直接编写java代码,造成jsp页面难以维护. 二.JSP常用标签 ...

  4. 自定义JSP标签库及Properties使用

    自定义JSP标签库及Properties使用 自定义JSP标签 自定义JSP标签技术是在JSP 1.1版本中才出现的,它支持用户在JSP文件中自定义标签,这样可以使JSP代码更加简洁. 这些可重用的标 ...

  5. JavaWeb---总结(十)JSP标签

    一.JSP标签介绍 JSP标签也称之为Jsp Action(JSP动作)元素,它用于在Jsp页面中提供业务逻辑功能,避免在JSP页面中直接编写java代码,造成jsp页面难以维护. 二.JSP常用标签 ...

  6. javaweb学习总结(十九)——JSP标签

    一.JSP标签介绍 JSP标签也称之为Jsp Action(JSP动作)元素,它用于在Jsp页面中提供业务逻辑功能,避免在JSP页面中直接编写java代码,造成jsp页面难以维护. 二.JSP常用标签 ...

  7. eclipse加速之禁用JS、jsp等文件的语法验证,eclipsejs

    eclipse加速之禁用JS.jsp等文件的语法验证 去除eclipse的JS验证:将windows->preference->Java Script->Validator-> ...

  8. javaWeb 使用jsp标签进行防盗链

    /** * 1.新建类继承SimpleTagSupport * 新建2个属性, 添加对应的set方法 * 覆盖doTag()方法 */ import java.io.IOException; impo ...

  9. 11、Jsp加强/EL表达式/jsp标签

    1 Jsp基础回顾 Jsp基础 1)Jsp的执行过程 tomcat服务器完成:jsp文件->翻译成java文件->编译成class字节码文件-> 构造类对象-> 调用方法 to ...

随机推荐

  1. Linq中的left join

    left join var custs = from c in db.T_Customer join u in db.Sys_User on c.OwnerId equals u.Id into te ...

  2. springfox-swagger2

    简介 springfox是通过注解的形式自动生成API文档,利用它,可以很方便的书写restful API: swagger主要用于展示springfox生成的API文档: 依赖 <depend ...

  3. P1903 [国家集训队]数颜色 / 维护队列(莫队区间询问+单点修改)

    题目链接:https://www.luogu.org/problemnew/show/P1903 题目大意:中文题目 具体思路:莫队单点修改+区间询问模板题,在原来的区间询问的基础上,我们要记录当前这 ...

  4. SQL Server - 约束 CONSTRAINT

    总结 约束放置在表中,以下五种约束: NOT NULL 非空约束C 指定的列不允许为空值 UNIQUE 唯一约束U 指定的列中没有重复值,或该表中每一个值或者每一组值都将是唯一的 PRIMARY KE ...

  5. 【转】python模块导入细节

    [转]python模块导入细节 python模块导入细节 官方手册:https://docs.python.org/3/tutorial/modules.html 可执行文件和模块 python源代码 ...

  6. k64 datasheet学习笔记31---External Bus Interface (FlexBus)

    1.前言 FlexBus多功能外部总线接口控制器是一个硬件模块: (1)通过并行总线提供存储器扩展或与外设连接: (2)如下的同步或异步的slave-only设备可以直连到FlexBus总线或者只需增 ...

  7. Git常用命令总结(超实用)【转】

    转自:https://www.linuxprobe.com/git-common-commands.html 本文由LinuxProbe.Com团队成员逄增宝整理发布,原文来自:Linux就这么学. ...

  8. 求逆序对 ----归并排 & 树状数组

    网上看了一些归并排求逆序对的文章,又看了一些树状数组的,觉得自己也写一篇试试看吧,然后本文大体也就讲个思路(没有例题),但是还是会有个程序框架的 好了下面是正文 归并排求逆序对 树状数组求逆序对 一. ...

  9. gPRC学习笔记

    gPRC学习笔记 gPRC基础教程. gPRC官方文档. protobuf 3.0的简易教程. 什么是RPC RPC(remote procedure call) -- 远程过程调用(相对于本地调用的 ...

  10. web@h,c小总结

    问题0:元素内联元素,行内元素,行内块元素.        内联: 宽高M,P都有效        行内元素:无宽高,内容撑开,M,P左右有效        行内块元素:可设宽高,内容撑开,M,P都有 ...