自定义标签
来源:互联网 发布:餐饮软件破解版 编辑:程序博客网 时间:2024/05/22 23:19
提出问题 : 自定义标签可以降低 jsp 开发的复杂度和维护量.从 html 角度来说,可以使 html 不用去过多的关注那些比较复杂的商业逻辑.利用自定义标签,可以软件开发人员和页面设计人员合理分工:页面设计人员可以把精力集中在使用标签(HTML,XML或者JSP)创建网站上,而软件开发人员则可以将精力集中在实现底层功能上面,如国际化等,从而提高了工程生产力.将具有共用特性的tag库应用于不同的项目中,体现了软件复用的思想。
什么是自定义标签 : 用户定义的一种自定义的jsp标记。当一个含有自定义标签的jsp页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为标签处理类的对象的操作。于是,当jsp页面被jsp引擎转化为servlet后,实际上tag标签被转化为了对tag处理类的操作.
标签库 API: 标签库 API 定义在 javax.servlet.jsp.tagext 包中.
传统标签和简单标签: 开发自定义标签,其核心就是要编写处理器类,一个标签对应一个标签处理器类,而一个标签库则是很多标签处理器的集合。所有的标签处理器类都要实现 JspTag 接口,该接口中没有定义任何方法,主要作为 Tag 和 SimpleTag 接口的父接口. 在 JSP 2.0 以前,所有标签处理器类都必须实现 Tag 接口,这样的标签称为传统标签. JSP 2.0 规范又定义了一种新的类型的标签,称为简单标签,其对应的处理器类要实现 SimpleTag 接口
标签的形式:
空标签:<hello/>
带有属性的空标签:
<max num1=“3” num2=“5”/>
带有内容的标签:
<greeting>
hello
</greeting>
带有内容和属性的标签:
<greeting name=“Tom”>
hello
</greeting>
自定义标签的开发与应用步骤:(这个很重要的哦!)
1. 编写完成标签功能的 Java 类(标签处理器)
2. 编写标签库描述(tld)文件,在tld文件中对自定义中进行描述
3. 在 JSP 页面中导入和使用自定义标签
SimpleTag 接口:
1. setJspContext 方法:该方法把代表 JSP 页面的 pageContext 对象传递给标签处理器对象。
2. setParent 方法:该方法把父标签处理器对象传递给当前标签处理器对象
3. getParent 方法:该方法用于获得标签的父标签处理器对象
4. setJspBody 方法:该方法用于把代表标签体的 JspFragment 对象传递给标签处理器对象
5. doTag 方法:该方法用于完成所有的标签逻辑。该方法可以抛出 javax.servlet.jsp.SkipPageException 异常,用于通知 web 容器不再执行 JSP 页面中位于结束标记后面的内容。
实现 SimpleTag 接口的标签处理器类的生命周期:
1.Jsp 引擎将代表 JSP 页面的 pageContext 对象传递给标签处理器对象
2.Jsp 引擎将父标签处理器对象传递给当前标签处理器对象。只有存在父标签 时,jsp 引擎才会调用该方法
3.设置标签属性。只有定义属性才调用该方法
4. 若存在标签体, JSP 引擎将把标签体封装成一个 JspFragment 对象,调用 setJspBody 方法将 JspFragment 对象传递给标签处理器对象。若标签体为空,这 setJspBody 将不会被 JSP 引擎调用
5.容器调用标签处理器对象的 doTag 方法执 行标签逻辑
JspFragment 类:
该类的实例对象代表 JSP 页面中的一段符合 JSP 语法规范的 JSP 片段,这段 JSP 片段不能包含 JSP 脚本元素(<% … %>).JSP 引擎在处理简单标签的标签体时,会把标签体内容用一个 JspFragment 对象表示,并调用标签处理器对象的 setJspBody 方法把 JspFragment 对象传递给标签处理器对象。得到代表标签体的 JspFragment 对象后,标签开发者和就可以在标签处理器中根据需要调用 JspFragment 对象的方法,进而决定如何处理标签体getJspContext 方法:该方法用于返回代表调用页面的 JspContext 对象
Invoke 方法(java.io.Writer out):该方法用于执行 JspFragment 对象所代表的 JSP 代码片段。在 doTag() 方法中可以根据需要调用该方法。该方法的参数 out 用于指定将 JspFragment 对象的执行结果写入到哪个输出流对象中。若传递参数 out 的值为 null,则将执行结果写入到 JspContext.geOut() 方法返回的输出流对象中。若想在标签处理器中修改标签体内容:需在调用 invoke 方法时指定一个可取出结果数据的输出流对象(如:StringWriter),让标签体的执行结果输出到该输出流中,然后从该输出流对象中取出数据进行修改后在输出到目标设备.
SimpleTagSupport:
为简化简单标签处理器的编写工作,JSP API 中提供了SimpleTag接口的一个实现SimpleTagSupport.
SimpleTagSupport实现了SimpleTag接口中的方法,它内部以成员变量的形式保存了setJspContext方法和setJspBody方法传递进来的参数。此外,它还定义了如下两个方法、来返回这两个参数:
1. getJspContext方法:该方法用于返回代表调用页面的JspContext对象
2. getJspBody方法:该方法用于得到代表标签体的JspFragment对象
标签库描述文件:
标签库描述(Tag Library Description)文件简称为 tld 文件,其扩展名为 .tld多个标签的集合就形成了一个标签库,标签库中的所有标签都必须在标签文件中进行描述Tld 文件可以放置在 web 应用程序的 WEB-INF 目录及其子目录中,但不能放置在 WEB-INF 目录下的 classes 和 lib 子目录中 。tld 文件也可以放置在 WEB-INF/lib 目录下的 jar 包的 META-INF 目录及其子目录中<body-content>:指定标签体的类型。可能取值有 3 种:
empty:没有标签体
scriptless:标签体可以包含 el 表达式和 JSP 动作元素,但不能包含 JSP 的脚本元素
tagdependent:表示标签体交由标签本身去解析处理。若指定 tagdependent,在标签体中的所有代码都会原封不动的交给标签处理器,而不是将执行结果传递给标签处理器
在 JSP 页面引用自定义标签:
在 JSP 页面使用 taglib 指令引入标签库描述文件: <%@ taglib prefix=“” uri=“” %>.uri:属性用于指定所引入的标签库描述(tld)文件中所定义的 <uri> 元素的内容;prefix 属性用于为引入的 tld 文件指定一个”引用代号”。Prefix 属性可以由 jsp 文件的作者任意指定,只要与其他 taglib 指令的 prefix 属性值不同就可以。
EL 自定义函数开发步骤:
1. 编写 EL 自定义函数映射的Java 类中的静态方法: 这个 Java 类必须带有 public 修饰符,方法必须是这个类的带有 public 修饰符的静态方法
2. 编写标签库描述文件(tld 文件), 在 tld 文件中描述自定义函数
3. 在 JSP 页面中导入和使用自定义函数
在 tld 文件中描述 EL 自定义函数:
在 JSP 页面中导入和使用 EL 自定义函数,在标准 JSP 页面中使用 taglib 指令来引入 tld 文件:
<%@ taglib uri="/petrelskyTag" prefix="petrelsky"%>uri:属性用于指定所引入的标签库描述(tld)文件中所定义的 <uri> 元素的内容;prefix 属性用于为引入的 tld 文件指定一个”引用代号”。Prefix 属性可以由 jsp 文件的作者任意指定,只要与其他 taglib 指令的 prefix 属性值不同就可以。调用 EL 自定义函数: ${petrelsky :toGBK (param.username) }
根据上面的理论知识的讲解,现在我将举写例子,并写写我的心得:
第一步,写JAVA类标签处理器
package cn.itcast.simpleTag;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.JspTag;
import javax.servlet.jsp.tagext.SimpleTag;
public class ParamTag implements SimpleTag {
private PageContext pageContext = null;
public void doTag() throws JspException, IOException {
System.out.println("hello doTag....");
HttpServletRequest request = null;
JspWriter out = null;
request = (HttpServletRequest) pageContext.getRequest();
out = pageContext.getOut();
String name = request.getParameter("name");
out.print("Hello: " + name);
}
public JspTag getParent() {
return null;
}
public void setJspBody(JspFragment arg0) {
}
public void setJspContext(JspContext arg0) {
this.pageContext = (PageContext) arg0;
}
public void setParent(JspTag arg0) {
}
}
第2步写TLD 文件
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
version="2.1">
<description>myTag 1.1 core library</description>
<display-name>myTag core</display-name>
<tlib-version>1.0</tlib-version>
<short-name>itcast</short-name>
<uri>http://itcast.cn/jsp/mytag</uri>
<tag>
<name>param</name>
<tag-class>cn.itcast.simpleTag.ParamTag</tag-class>
<body-content>empty</body-content>
</tag>
</taglib>
第三步写JSP 页面 :
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="/WEB-INF/tld/mytag_1_ex.tld" prefix="itcast" %>
<html>
<head><title>My JSP 'test.jsp' starting page</title></head>
<body>
<itcast:param/>
</body>
</html>
由上面可以看出,所谓标签就是用在视图层,JSP页面中根本看不到JAVA 的程序,而是JAVA 程序写了个标签,然后在JSP 页面中使用,页面看起来十分简洁!这个就是自定义标签的强大之处!前提是以JAVA为基础的!看着佟老师在课上写自定义标签是那么的熟练,当时就想自己也能够有这样水平,当然思路很重要,但最重要的是自己经常性学着自己去写的!下面再看个复杂点的!
package cn.itcast.simpleTag.ex;
import java.io.IOException;
import java.io.StringWriter;
import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.JspTag;
import javax.servlet.jsp.tagext.SimpleTag;
public class ToLowerCaseTag implements SimpleTag {
private PageContext pageContext;
private JspFragment bodyContent;
public void doTag() throws JspException, IOException {
// TODO Auto-generated method stub
//1. 得到标签体的文本
StringWriter sw = new StringWriter();
bodyContent.invoke(sw);
String bodyContentString = sw.toString();
//2. 把标签体文本变成小写
bodyContentString = bodyContentString.toLowerCase();
//3. 输出
pageContext.getOut().print(bodyContentString);
}
public JspTag getParent() {
// TODO Auto-generated method stub
return null;
}
public void setJspBody(JspFragment arg0) {
// TODO Auto-generated method stub
this.bodyContent = arg0;
}
public void setJspContext(JspContext arg0) {
// TODO Auto-generated method stub
this.pageContext = (PageContext) arg0;
}
public void setParent(JspTag arg0) {
// TODO Auto-generated method stub
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
version="2.1">
<description>mytag</description>
<display-name>mytag core</display-name>
<tlib-version>1.2</tlib-version>
<short-name>itcast</short-name>
<uri>http://itcast.cn/mytag_ex</uri>
<tag>
<name>toLowerCase</name>
<tag-class>cn.itcast.simpleTag.ToLowerCaseTag</tag-class>
<body-content>scriptless</body-content>
</tag>
</taglib>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="/WEB-INF/tld/mytag.tld" prefix="itcast" %>
<html>
<head><title>My JSP 'test.jsp' starting page</title></head>
<body>
<itcast:toLowerCase>
HELLO ITCAST.CN.
</itcast:toLowerCase>
</body>
</html>
这个例子很明显的证明了开发自定义标签的步骤是多么的重要的!只要自己勤加练习,其实我们也可以写出很漂亮的,很有使用价值的标签供给大家使用的呢!