JSP自定义标签——传统标签
同JSP标签一样,自定义标签主要用于移除JSP页面中的Java代码,可以看到我们在JSP中其实是禁止使用Java脚本的,任何要想通过Java代码实现的功能都必须以标签形式来处理,可以使用JSP标签,JSTL标签,EL函数,或者自定义标签。
自定义标签分为传统标签和简单标签,简单标签是Sun公司为减低自定义标签技术的学习难度而定义的,对于简单标签请看下一篇博客。本文先来学习传统自定义标签。
使用传统自定义标签需要满足以下两个步骤:
① 编写一个实现Tag接口(实际上我们更常的是继承Tag接口的实现类从而免于覆写所有的方法)的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”(代表标签没有标签体)或“JSP”(代表标签有标签体)。
以上的步骤整体类似于我们自定义EL函数,而不同的是这里的Java类需要继承特定的JSP的API中提供的类并覆盖其中特定的方法。
我们先看一看Tag类的API,注意,这是JSP技术,请看JSP的API:
从上面可以看到Tag是一个接口,如果我们直接继承Tag接口的话,那就得覆写这六个方法,那就显得十分麻烦了,况且有些方法是属于标签的生命周期方法,是由JSP引擎调用的,因此我们只需要继承Tag接口的实现子类即可,通常我们使用“TagSupport”类或者“BodyTagSupport”类,能有更多的功能。
在Tag接口中,除了getParent方法以外,其他都是生命周期方法。在浏览器在解析一个JSP页面时,遇到某个自定义标签后就会开始执行该标签的生命周期方法。自定义标签的生命周期顺序为:① 创建自定义标签的实例对象 ---> ② setPageContext方法 ---> ③ setParent方法---> ④ doStart方法 ---> ⑤ doEnd方法 ---> ⑥ release方法(通常在服务器关闭时才调用)。
下面简单的介绍下这几个生命周期方法:
setPageContext方法(重要),JSP引擎对标签进行实例化对象后,会先调用setPageContext方法,将JSP页面的pageContext对象传入这个标签处理器类,我们在JSP的pageContext隐式对象一文中说过,只要拥有了pageContext对象,那么就可以获取其他八大隐式对象从而操作web中的需求了。
setParent方法,在setPageContext方法执行完之后,将调用setParent方法,这个方法将会把这个自定义标签的父类标签(如果有)传递给该标签处理器类,如果没有父类标签,那么setParent方法的参数即为null。注意,这里说的标签的父标签也是指自定义标签,如果该自定义标签的只是嵌入在普通的HTML标签的话那么就是无父类标签,执行的只是setParent(null)方法。
doStartTag方法,当JSP引擎接连调用setPageContext方法和setParent方法完成标签的配置之后,当浏览器解析标签的开始标签时,就会调用doStartTag方法。通常我们在使用标签处理某个功能时,就将该功能在doStartTag方法中覆写。另外,依据doStartTag方法的返回值是“EVAL_BODY_INCLUDE”(执行)还是“SKIP_BODY”(不执行)决定是否执行标签体中的内容。可以说这是我们要使用标签来封装Java代码最重要的一个方法。
doEndTag方法,当浏览器在JSP页面中解析到该标签的结束标签时,就会调用doEndTag方法。另外,依据doEndTag方法的返回值是“EVAL_PAGE”(执行)还是“SKIP_PAGE” (不执行)决定是否执行结束标签之后余下的JSP页面内容。
release方法,通常JSP调用完doEndTag方法后,并不会立即执行release方法,因为为了服务器的性能,通常就会将标签处理器类的对象驻留于内存中,以便下次能更快速地调用,这一点和Servlet是一样的。一般在停止该web应用或服务器停止时才会调用标签处理器的release方法,释放标签中的资源。
通常我们使用的是一个Java类继承TagSupport类或者BodyTagSupport类,对于处理标签,依然也是覆写doStartTag方法。同时注意到TagSupport类中,一个属性即为pageContext,注意这是字段,同时能给子类调用(protected修饰),而我们基本在覆写doStartTag方法中要随处用到这个字段:
例1:使用自定义标签来显示来访者IP
创建一个Java类继承TagSupport类,覆写doStartTag方法,这里因为标签没有标签体,可以暂时不用管doStartTag方法的返回值:
package com.fjdingsd.tag;
public class GuestIpTag extends TagSupport {
@Override
public int doStartTag() throws JspException { HttpServletRequest request = (HttpServletRequest) this.pageContext.getRequest();
String ip = request.getRemoteAddr();
JspWriter out = this.pageContext.getOut();
try {
out.write(ip);
} catch (IOException e) {
throw new RuntimeException(e);
}
return super.doStartTag();
}
}
接着在web应用的【WEB-INF】中创建TLD文件,设置好uri和标签的名称、类、以及标签体类型:
<?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>selftag</uri> <tag>
<name>guestip</name>
<tag-class>com.fjdingsd.tag.GuestIpTag</tag-class>
<body-content>empty</body-content>
</tag>
</taglib>
最后就可以在JSP页面中使用自定义标签了,当然别忘了使用taglib指令先导入我们的标签所在的uri:
<%@ taglib uri="selftag" prefix="selftag" %>
在JSP页面的主体中使用我们设计好的自定义标签:
您的ip地址为:<selftag:guestip/>
浏览器中观察:
例2:控制标签的标签体内容是否输出显示
如果要想控制标签体的内容是否输出显示,只需要修改doStartTag方法的返回值即可:
package com.fjdingsd.tag;
public class ShowTagBodyOrNot extends TagSupport {
@Override
public int doStartTag() throws JspException {
HttpSession session = this.pageContext.getSession();
User user = (User) session.getAttribute("user");
if(user==null) {
return TagSupport.SKIP_BODY; //隐藏标签体内容
}else{
return TagSupport.EVAL_BODY_INCLUDE; //显示标签体内容
}
}
}
在TLD文件中定义(这里忽略文件首尾其他定义):
<tag>
<name>showbody</name>
<tag-class>com.fjdingsd.tag.ShowTagBodyOrNot</tag-class>
<body-content>JSP</body-content>
</tag>
在JSP页面中导入taglib指令后并在JSP页面主体部分使用自定义标签:
<selftag:showbody>
只有登录用户才能显示……
</selftag:showbody>
当然这个例子当我没有在session域中存入User对象时,是不会在页面上显示这个标签的标签体内容的,这里只是用来强调在doStartTag方法的返回值“EVAL_BODY_INCLUDE”与“SKIP_BODY”的区别。
例3:控制标签之后余下的JSP页面是否输出显示
如果要想标签之后余下的JSP页面是否输出显示,只需要修改doEndTag方法的返回值即可:
package com.fjdingsd.tag;
public class ShowJSPOrNot extends TagSupport {
//注意,TagSupport的doStartTag方法默认返回值为SKIP_BODY,也就是不执行标签体内容
@Override
public int doEndTag() throws JspException {
HttpSession session = this.pageContext.getSession();
User user = (User) session.getAttribute("user");
if(user==null) {
return TagSupport.SKIP_PAGE; 隐藏结束标签后余下JSP页面 }else{
return TagSupport.EVAL_PAGE; //显示结束标签后余下JSP页面
}
}
}
在TLD文件中定义(这里忽略文件首尾其他定义):
<tag>
<name>showpage</name>
<tag-class>com.fjdingsd.tag.ShowJSPOrNot</tag-class>
<body-content>empty</body-content>
</tag>
在JSP页面中导入taglib指令后并在JSP页面主体部分使用自定义标签:
<selftag:showpage/> <!DOCTYPE HTML>
<html>
<head>
<title>My JSP 'demo1.jsp' starting page</title>
</head> <body>
。。。
<body>
</html>
这里我把自定义标签置于JSP页面最开始的地方,可以看到如果没有在session域中存入User对象的话,那么这个JSP在被访问后是不会看到任何东西的,查看网页源码也是没有任何代码。当然这个例子只是用来强调在doEndTag方法的返回值 “EVAL_PAGE”和 “SKIP_PAGE”的区别。
使用传统的自定义标签还可以扩展一些其他的功能,比如控制标签体的内容重复执行,修改标签体内容再输出等等,这两个功能涉及到使用Tag不同实现类的使用,将在下一篇博客中进行讲解。
JSP自定义标签——传统标签的更多相关文章
- JSP自定义tld方法标签
卧槽 我们可以通过tld文件,自定义一个方法标签,以便在页面中使用,目录通常放在WEB-INF下面的tlds文件夹: 引入方式示例,直接在jsp上引入tld标签文件: <%@ taglib pr ...
- 传智播客JavaWeb day07、day08-自定义标签(传统标签和简单标签)、mvc设计模式、用户注册登录注销
第七天的课程主要是讲了自定义标签.简单介绍了mvc设计模式.然后做了案例 1. 自定义标签 1.1 为什么要有自定义标签 前面所说的EL.JSTL等技术都是为了提高jsp的可读性.可维护性.方便性而取 ...
- Java jsp 自定义标签
1 自定义标签 1.1 引入 需求: 向浏览器输出当前客户的IP地址 (只能使用jsp标签) 1.2 第一个自定义标签开发步骤 1)编写一个普通的java类,继承SimpleTagSupport类,叫 ...
- JSP第六篇【自定义标签之传统标签】
为什么要使用自定义标签? JSTL标签库只提供了简单的输出等功能,没有实现任何的HTML代码封装,并且某些复杂类型转换,或者逻辑处理的时候,JSTL标签库完成不了,需要自定义标签! 编写自定义标签的步 ...
- JSP传统标签开发
1.标签技术的API类继承关系 1).JspTag接口是所有自定义标签的父接口 该接口中没有任何属性和方法,只有两个直接子接口,Tag接口和SimpleTag接口,把实现Tag接口的自定义标签叫做传统 ...
- JSP 自定义标签
0 标签技术的API继承体系 1 作用 jsp自定义标签用于移除页面中的java代码 2 实现 2.1 标签处理类ViewIPTag.java package com.zsm.util; import ...
- javaweb学习总结(二十四)——jsp传统标签开发
一.标签技术的API 1.1.标签技术的API类继承关系 二.标签API简单介绍 2.1.JspTag接口 JspTag接口是所有自定义标签的父接口,它是JSP2.0中新定义的一个标记接口,没有任何属 ...
- JavaWeb学习记录(十九)——jstl自定义标签库之传统标签
一.传统标签 (1)JSP引擎将遇到自定义标签时,首先创建标签处理器类的实例对象,然后按照JSP规范定义的通信规则依次调用它的方法. public void setPageContext(PageCo ...
- JSP自定义标签——简单标签(1)
前面一篇博客介绍了自定义标签的传统标签使用方式,但是我们会发现,使用传统标签非常的麻烦,而且接口还多,现在传统标签基本都没用了,除了一些比较久的框架.Sun公司之后推出了一个新的标签使用方式,称之为简 ...
随机推荐
- sqlserver 分页查询总结
sqlserver2008不支持关键字limit ,所以它的分页sql查询语句将不能用mysql的方式进行,幸好sqlserver2008提供了top,rownumber等关键字,这样就能通过这几个关 ...
- linux(Centos 6.3)学习笔记
一.系统分区 1,磁盘分区 使用分区编辑器(partition editor)在磁盘上划分几个逻辑部分.碟片一旦划分成 数个分区,不同类的目录与文件可以存储进不同 ...
- bmp图片数据提取
仿照别人的程序写的bmp数据提取C代码,并将提取的数据放到txt文档中 /* date : 2014/06/24 designer :pengxiaoen version : dev4.9.9.0 f ...
- 编写存储过程导出oracle表数据到多个文本文件
1.测试表和数据: create table test(id )); begin .. loop insert into test values(k,'test'||k); end loop; end ...
- c语言‘\0’ ,‘0’, “0” ,0之间的区别
首先比较一下‘\0’和‘0’的区别.有一个共同点就是它们都是字符,在c语言中,字符是按其所对应的ASCII码来存储的,一个字符占一个字节.请翻开你的ASCII字符集表吧,一般在你的C语言教材的附录上, ...
- JAVA平台上的网络爬虫脚本语言 CrawlScript
JAVA平台上的网络爬虫脚本语言 CrawlScript 网络爬虫即自动获取网页信息的一种程序,有很多JAVA.C++的网络爬虫类库,但是在这些类库的基础上开发十分繁琐,需要大量的代码才可以完成一 个 ...
- 基于visual Studio2013解决算法导论之047赫夫曼编码
题目 赫夫曼编码 解决代码及点评 // 赫夫曼编码.cpp : 定义控制台应用程序的入口点. // #include <iostream> #include <stdio.h ...
- 【Android LibGDX游戏引擎开发教程】第06期:图形图像的绘制(下)图片整合工具的使用
在上一篇文章中,我们提到了图片必须是2的n次方的问题.但是随着Libgdx的不断完善和发展,使用一些工具就 可以很好的解决了这样一个问题,但是它的功能又不仅仅只限于此,那么下面就来让我们看看Textu ...
- python-Day5-深入正则表达式--冒泡排序-时间复杂度 --常用模块学习:自定义模块--random模块:随机验证码--time & datetime模块
正则表达式 语法: mport re #导入模块名 p = re.compile("^[0-9]") #生成要匹配的正则对象 , ^代表从开头匹配,[0 ...
- shapefile 编码错误问题解决 Wrong codepage of shapefile Warning 1: One or several characters couldn't be converted correctly from UTF-8 to ISO-8859-1.
linux下运行,因为大部分shapefile 文件,在使用时都没有指定字符集,所以qgis只能从环境变量中获取设置环境变量中获取SHAPE_ENCODING. 目前唯一的解决办法就是设置环境变量 $ ...