JSP自定义标签——简单标签(1)
前面一篇博客介绍了自定义标签的传统标签使用方式,但是我们会发现,使用传统标签非常的麻烦,而且接口还多,现在传统标签基本都没用了,除了一些比较久的框架。Sun公司之后推出了一个新的标签使用方式,称之为简单标签。简单标签也作为JSP2.0以后的标准标签使用方式,下面是一张传统标签和简单标签的对比,可以看到简单标签真的简化了不少:

与传统标签的使用步骤是类似的,需要满足以下两个步骤:
① 编写一个实现SimpleTag接口(实际上我们更常的是继承SimpleTagSupport接口的实现类从而免于覆写所有的方法)的Java类,这个Java类也称为标签处理器类。
② 编写标签的TLD文件,用于指定标签的URI和对标签的声明描述,这一点和EL函数时一样的,TLD文件必须放置在web应用下的【WEB-INF】文件中,可以是除【classes】和【lib】目录以外的任何子目录中。TLD文件的模板可以从【Tomcat】--->【webapps】--->【examples】--->【WEB-INF】--->【jsp2】中有一个“jsp2-example-taglib.tld”文件复制首尾和其中的<Tag>标签。
注:在TLD文件中我们使用<tag>标签来对每一个自定义标签的Java类进行描述,其中每个<tag>标签下还需要指定<body-content>的值,这个是描述标签体的类型:对于简单标签使用:“empty”(无标签体内容时) 或“scriptless” (有标签体内容时)。
注意:简单标签在JSP页面中,标签体内容中是不允许使用JSP脚本的。
与传统标签需要使用doStartTag()方法和doEndTag()方法不同,简单标签只需要doTag()方法来处理标签,所有的标签体内容逻辑,迭代,是否执行标签体内容等等都只需要调用doTag()方法即可。因此简单标签能和传统标签的bodyTagSupport能有一样的功能,但是生命周期方式更简单并且只有一个接口。
下图是简单标签SimpleTag接口的所有方法:

其中除了getParent方法以外,其他都是生命周期方法,这一点和传统标签类似。简单自定义标签的生命周期顺序为:① 创建自定义标签的实例对象 ---> ② setJspContext方法 ---> ③ setJspBody方法(如果有标签体才调用) ---> ④ setParent方法(如果有父类自定义标签才调用)---> ⑤ doTag方法 ---> ⑥ 该自定义标签的实例对象将被垃圾回收器回收(与传统自定义标签不同,简单标签的标签处理器类对象不会缓存)。
下面简单地介绍下这几个生命周期方法:
setJspContext(JspContext pc)方法,JSP容器对简单标签进行实例化对象后,通过调用这个方法,将pageContext对象(pageContext是JspContext的子类)传入标签处理器类从而使得在标签处理器类处理标签和标签体时(doTag)能通过这个对象获取其他八大web对象。
setJspBody(JspFragment jspBody)方法,是将标签体内容封装为一个JspFragment对象传入给标签处理器类,也就是说JspFragment对象就代表标签体的内容。如果想要执行标签体,只需要调用JspFragment对象的invoke(Writer out)方法传入一个输出流对象即可,或者如果往invoke方法中传入的参数为null的话,默认参数为JspWriter对象,等效于invoke(this.getJspContext.getOut)。如果不调用invoke方法,那么就不会执行标签体内容,另外可以随意调用多次invoke方法。另外如果简单标签没有标签体内容,那么setJspBody不会被调用。
setParent方法,只有在该自定义标签嵌入在另一个自定义标签中才会调用,记住父标签必须也是自定义标签才可以,如果父标签只是简单的HTML标签那么该setParent方法不会被调用。
doTag()方法,由JSP容器来调用,通常是由我们开发人员来覆写这个方法的实现,我们要使用标签来完成任何功能的实现都在这个方法中。如果我们不想执行这个标签后面余下的JSP页面,那么只需要在这个方法内抛出一个“SkipPageException”异常即可。
如果要想直接实现SimpleTag接口,那么在这个实现类中一定要有一个无参的构造函数。通常我们选择继承SimpleTag接口的实现类,也就是SimpleTagSupport类。继承SimpleTagSupport类的话,继承的子类中还可以使用SimpleTagSupport类给子类提供的方法获取pageContext对象或者JspFragment对象:

例1:使用简单标签来控制是否执行标签体内容
编写标签处理器类:
package com.fjdingsd.simpletag;
public class ShowTagBodyOrNot extends SimpleTagSupport {
@Override
public void doTag() throws JspException, IOException { JspFragment fragment = this.getJspBody();
fragment.invoke(this.getJspContext().getOut());
//上面的代码等效于fragment.invoke(null);
}
}
在TLD文件中声明描述标签:
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
<description>A tag library exercising SimpleTag handlers.</description>
<tlib-version>1.0</tlib-version>
<short-name>SimpleTagLibrary</short-name>
<uri>simpletag</uri> <tag>
<name>showbody</name>
<tag-class>com.fjdingsd.simpletag.ShowTagBodyOrNot</tag-class>
<body-content>scriptless</body-content>
</tag> </taglib>
在JSP页面中导入taglib指令:
<%@ taglib uri="simpletag" prefix="simple" %>
最后就可以在JSP页面的主体中使用刚才定义的简单标签了:
<simple:showbody>
银魂
</simple:showbody>
在浏览器中观察:

分析:能显示的原因,是因为在这个标签中,将标签体封装成JspFragment对象,并且通过这个对象调用了invoke()方法,即执行标签体内容,如果我们想控制标签体内容不输出显示的话,只要不调用invoke()方法即可,修改例1的标签处理器类:
public class ShowTagBodyOrNot extends SimpleTagSupport {
@Override
public void doTag() throws JspException, IOException {
JspFragment fragment = this.getJspBody(); //这句代码,或者甚至这个方法没有都可以,都能控制标签体内容不执行,要想执行必须要有JspFragment.invoke方法
}
}
其他TLD文件等等内容都不变,则浏览器中不会对这个标签显示任何内容。
例2:使用简单标签来控制标签体内容执行次数
编写标签处理器类:
package com.fjdingsd.simpletag;
public class LoopTagBody extends SimpleTagSupport {
@Override
public void doTag() throws JspException, IOException {
JspFragment fragment = this.getJspBody();
for(int i=0;i<3;i++) {
fragment.invoke(null); //标签体执行3次
}
}
}
在TLD文件中描述(这里省略首尾,详细内容请看例1):
<tag>
<name>loopbody</name>
<tag-class>com.fjdingsd.simpletag.LoopTagBody</tag-class>
<body-content>scriptless</body-content>
</tag>
在JSP页面中导入taglib指令(此处略)后,在JSP页面的主体中使用刚才定义的简单标签:
<simple:loopbody>
神乐 <br>
</simple:loopbody>
在浏览器中观察:

例3:使用简单标签来修改标签体内容再输出(这里将标签体内容中所有字母变为大写)
分析:要想使用简单标签来修改标签体内容再输出,需要先获取标签体对象(JspFragment),我们知道要想执行标签体必须调用invoke(Writer out)方法,但是如果我们使用非缓冲的Writer输出流,那么就直接输出给浏览器了,无法达到修改目的,因此我们应该使用带有缓冲流的字符流对象,将标签体内容通过invoke方法先存入字符流,再从字符流中取出修改最后再输出给浏览器。
编写标签处理器类:
package com.fjdingsd.simpletag;
public class ModifyTagBody extends SimpleTagSupport {
@Override
public void doTag() throws JspException, IOException {
JspFragment fragment = this.getJspBody();
StringWriter writer = new StringWriter();
fragment.invoke(writer); String tagContent = writer.toString().toUpperCase();
this.getJspContext().getOut().write(tagContent);
}
}
另:使用StringWriter缓冲流是因为StringWriter能够获得缓冲区中的值:

在TLD文件中描述(这里省略首尾,详细内容请看例1):
<tag>
<name>modifybody</name>
<tag-class>com.fjdingsd.simpletag.ModifyTagBody</tag-class>
<body-content>scriptless</body-content>
</tag>
在JSP页面中导入taglib指令(此处略)后,在JSP页面的主体中使用刚才定义的简单标签:
<simple:modifybody>
long live sd
</simple:modifybody>
在浏览器中观察:

例4:使用简单标签来控制便签后余下的JSP页面是否显示
若想使用简单标签来控制便签后余下的JSP页面不显示,只需要在标签处理器类的doTag方法中抛出“SkipPageException”异常即可。
编写标签处理器类:
package com.fjdingsd.simpletag;
public class HideRemainJSP extends SimpleTagSupport {
@Override
public void doTag() throws JspException, IOException { throw new SkipPageException();
}
}
在TLD文件中描述(这里省略首尾,详细内容请看例1):
<tag>
<name>hidepage</name>
<tag-class>com.fjdingsd.simpletag.HideRemainJSP</tag-class>
<body-content>empty</body-content>
</tag>
在JSP页面中导入taglib指令(此处略)后,在JSP页面的主体中使用刚才定义的简单标签:
<simple:hidepage/> <!DOCTYPE HTML>
<html>
<head>
<title>My JSP 'simpletagdemo.jsp' starting page</title>
</head> <body>
。。。
</body>
</html>
结果:我在JSP页面最开始的地方使用了刚才自定义的简单标签,控制该标签后的页面不再执行,因此浏览器访问该页面中将只会看到空白页面,包括页面源码也是为空。
JSP自定义标签——简单标签(1)的更多相关文章
- JSP自定义标签——简单标签(2)
在前一篇博客中,我们已经学习了自定义的简单标签的基本使用方法,这一篇我们来学习如何在简单标签中添加标签属性.对自定义标签添加一些属性,可以使我们的标签功能更加灵活和复用.例如前一篇博客使用简单标签来对 ...
- JSP自定义tld方法标签
卧槽 我们可以通过tld文件,自定义一个方法标签,以便在页面中使用,目录通常放在WEB-INF下面的tlds文件夹: 引入方式示例,直接在jsp上引入tld标签文件: <%@ taglib pr ...
- JSP自定义标签之简单标签入门
在sun官方文档上有下面这样一段话. 官方文档声明 public interface SimpleTag extends JspTag Interface for defining Simple Ta ...
- JSP自定义标签(标签处理器 tld文件)
标签的形式如下,标签处理器就是处理JSP页面中的标签的属性和内容,定义好之后就跟使用JSTL一样 <标签名 属性名="属性值" 属性名="属性值"> ...
- Rhythmk 一步一步学 JAVA(7): jsp 自定义标签
1.实现Tag接口: TagSupport类实现了Tag接口,为我们提供了4个重要的方法(见表6-5). 1.1. TagSupport类中的常用方法 int doStartTag ...
- javaEE(7)_自定义标签&JSTL标签(JSP Standard Tag Library)
一.自定义标签简介 1.自定义标签主要用于移除Jsp页面中的java代码,jsp禁止出现一行java脚本. 2.使用自定义标签移除jsp页面中的java代码,只需要完成以下两个步骤: •编写一个实现T ...
- [转]JSP自定义标签
原文链接 当jsp的内置标签和jstl标签库内的标签都满足不了需求,这时候就需要开发者自定义标签. 自定义标签 下面我们先来开发一个自定义标签,然后再说它的原理吧! 自定义标签的开发步骤 步骤一 编写 ...
- python的Web框架,Django自定义过滤器及标签
代码布局 有的时候框架给的过滤器不够用,需要自定义一些过滤器,所以就需要我们自己来定义一些过滤器等 自定义代码放置的路径 某个app特用(独有)的 - app 目录下的 templatetags文件夹 ...
- Django——5 自定义过滤器及标签
Django 自定义过滤器 自定义标签 简单标签 包含标签 自定义过滤器 自定义过滤器就是一个带有一个或两个参数的Python 函数: - (输入的)变量的值 —— 不一定是字符串形式. - 参数的值 ...
随机推荐
- Easyui datagrid 批量编辑和提交
<script type="text/javascript"> $(function() { var $dg = $("#dg"); $dg.dat ...
- HDU 5119 Happy Matt Friends(2014北京区域赛现场赛H题 裸背包DP)
虽然是一道还是算简单的DP,甚至不用滚动数组也能AC,数据量不算很大. 对于N个数,每个数只存在两个状态,取 和 不取. 容易得出状态转移方程: dp[i][j] = dp[i - 1][j ^ a[ ...
- Python函数式编程:内置filter函数使用说明
filter操作是函数式编程中对集合的重要操作之一,其作用是从原集合中筛选符合条件的条目,组成一个新的集合. 这在我们日常编程中是非常常见的操作.我们通常的做法是通过循环语句来处理. 而使用filte ...
- Spring Boot 探索系列 - 自动化配置篇
26. Logging Prev Part IV. Spring Boot features Next 26. Logging Spring Boot uses Commons Logging f ...
- lucene 索引查看工具
luke 是 lucene 索引查看工具,基于 swing 开发的,是 lucene.solr.nutch 开发过程中不可或缺的工具.在测试搜索过程,进程出现搜不到东西或者搜到的东西不是想要的结果时, ...
- C++标准库类型vector及迭代器iterator简介
Vector是C++标准库类型,称为容器,一个容器中的所有对象必须是同一种类型的.与数组相比,其最大的优点就是动态增长.Vector是一个类模板,并不是数据类型,而vector<int>和 ...
- 配置免安装版JAVA1.7的环境变量
我用的是免安装版JAVA1.7,假设想获取JDK能够联系问我要. 1.開始配置环境变量,右击[我的电脑]---[属性]-----[高级]---[环境变量],如图: 2.选择[新建系统变量]--弹出&q ...
- 三种LVS负载均衡技术的优缺点----负载均衡调度算法
三种LVS负载均衡技术的优缺点归纳以下表: VS/NATVS/TUNVS/DR 服务器操作系统任意支持隧道多数(支持Non-arp) 服务器网络私有网络局域网/广域网局域网 服务器数目(100M网络) ...
- vc根据域名获取IP地址 gethostbyname()函数
以下是VC Socket初始化时用到的两个函数 一.WSAStartup函数 int WSAStartup ( ...
- C++静态库中使用_declspec(dllexport) 不能导出函数的问题
在某项目中,有一些静态库,这些静态库中有类型命名的函数GET_XXX.在一次项目结构调整的时候,我想将调用这静态库的代码编译成DLL,并且将这些Get函数导出,我就直接就这些函数前面添加了_decls ...