这里引入两个接口JspTag
SimpleTag
和一个实现类SimpleTagSupport
它们的关系是 JspTag
是根接口,没有定义任何方法,SimpleTag
接口是JspTag
的子接口 SimpleTagSupport
是SimpleTag
的实现类
还引入两个异常处理类JspException
JspTagException
自定义标签步骤:
1.创建标签的处理类
2.创建标签库描述文件(.tld)
3. 在JSP页面中使用标签
1.空标签的开发
实现SimpleTag接口方式
五个生命周期方法说明:
setJspContext
设置JspContext对象setParent
设置父标签对象setJspBody
若标签带标签体(标签体不能包含JSP脚本),容器调用该方法,将标签体内容存在到JspFragment中getParent
返回当前标签的父标签doTag
核心方法 由容器调用完成简单标签的操作
五个生命周期调用顺序:setJspContext -> setParent -> setJspBody -> doTag
1.创建标签的处理类
package com.mytag;
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;
import java.io.IOException;
public class MyFirstTag implements SimpleTag {
JspContext jspContext = null;
JspTag parent = null;
public void doTag() throws JspException, IOException {
jspContext.getOut().print("这是我的第一个标签");
}
public void setParent(JspTag parent){
this.parent = parent;
}
public JspTag getParent(){
return parent;
}
public void setJspContext(JspContext jspContext){
this.jspContext = jspContext;
}
public void setJspBody(JspFragment body){
}
}
//必须实现上面5个生命周期方法
2.创建标签库描述文件(.tld)
该文件放在web-info目录下
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee" version="2.0">
<tlib-version>1.0</tlib-version>
<short-name>TagExample</short-name>
<uri>http://www.mydomain.com/sample</uri>
<tag>
<name>firstTag</name>
<tag-class>com.mytag.MyFirstTag</tag-class>
<body-content>empty</body-content>
</tag>
</taglib>
说明:
uri
设置地址自定义,需要在jsp的taglib
指令中引入该地址,name
为自定义标签名tag-class
表示标签处理类的路径- 这里
body-content
表示标签体为空(还不能回车换行) - 每个tld文件里
uri
的值是唯一的,可以有多个tag
标签,但是name
值必须不一样
3. 在JSP页面中使用标签
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="demo" uri="http://www.mydomain.com/sample" %>
<html>
<head>
<title>第一个标签</title>
</head>
<body>
<p>您好!!!</p>
<demo:firstTag />
</body>
</html>
说明:
prefix
表示标签前缀,uri
对应tld文件中的uri
标签内容
2.带属性标签的开发
继承SimpleTagSupport类实现
1.创建标签的处理类
package com.mytag;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.SimpleTagSupport;
import java.io.IOException;
public class MathTag extends SimpleTagSupport {
double x;
public void setX(String x){
double num = 1;
try{
num = Double.parseDouble(x);
System.out.println("值获取成功"+num);
this.x=num;
}catch (NumberFormatException nfe){
System.out.println("值获取失败,赋值为默认值");
this.x = num;
}
}
public void doTag() throws JspException, IOException{
JspWriter out = getJspContext().getOut();
out.print(x+ " 的平方根是:"+ x*x);
}
}
说明:
- 这里
setX
表示,设置该标签的属性x的值(由jsp页面中标签的属性值传递而来) - 继承
SimpleTagSupport
类只需要实现doTag
方法即可
2.创建标签库描述文件(.tld)
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee" version="2.0">
<tlib-version>1.0</tlib-version>
<short-name>TagExample</short-name>
<uri>http://www.mydomain.com/sample</uri>
<tag>
<description>Compute Square Root</description>
<name>sqrt</name>
<tag-class>com.mytag.MathTag</tag-class>
<body-content>empty</body-content>
<attribute>
<name>x</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
说明:
- 标签的每一个属性都要在标签
attribute
中定义属性名 - 这里设置属性名为
x
而且是必须添加该属性 rtexprvalue
表示是否能接受请求时表达式的值,默认为false
body-context的值说明:
empty
表示是标签不带标签体,不能包含空格和换行scriptless
表示标签体中不能包含JSP脚本元素(<%%> <%=%>等
)tagdependent
表示容器不会执行标签体,而是在请求时把它传递给标签处理类,由标签处理类决定处理标签体,比如放入SQL语句
3. 在JSP页面中使用标签
使用方式与前面一致
说明:
- 属性值可以是常量 EL表达式 也可以时JSP表达式
<jsp:attribute name="属性名">属性值</jsp:attribute>
. 对于由属性标签必须要做三件事:
1.1 必须在标签处理类中声明一个变量存放属性值
1.2 如果属性不是必需的,则必需提供默认值,或者在代码处理相应的null值
1.3 对于每一个属性都必须实现适当的修改方法(set属性名()
)
3.带标签体的标签
通过继承SimpleTagSupport
类可以实现
说明:
- 通过
getJspContext()
方法获得JspContext
对象 - 通过
invoke(Writer out)
执行标签体中的代码 并将结果发送到Writer对象,如果将结果输出到JSp页面则参数为null
比如geJspBody().invoke(null);
书写在doTag
方法体里
迭代标签
即通过给invoke()
方法传入StringWriter()
对象,然后通过for循环实现
在doTag里
StringWriter sw = new StringWriter();
getJspBody().invoke(sw );
String text = sw.toString();//获取标签体中的内容
for(int i=1;i<=count;i++){
out.print("<h"+i+">"+text+"</h"+i+">");
}//count为属性传递过来的值,表示迭代次数
4.在标签体中使用EL表达式
在标签体里面使用EL表达式来访问doTag里面的添加的内容
getJspContext().setAttribute("product","苹果手机");
getJspBody().invoke(null);
在标签体中${product}
即可显示
5.使用动态属性
在简单标签中还可以处理动态属性(不需要在TLD文件中定义的属性)
需要标签实现类实现DynamicAttribute
接口,还接口只有一个方法,该方法来处理动态属性.方法是public void setDynamicAttribute(String uri,String localName,Object value) throws JspException
参数uri
表示属性的命名空间,localName
表示动态属性名,value
表示属性值
使用:
- 首先实现
DynamicAttribute
接口 - 在标签实现类首先定义一个
String
类型的字符串(这里是output
),用来接受返回的字符 - 实现
setDynamicAttribute(String uri,String localName,Object value)
方法 - 在setDynamicAttribute的方法体 通过if else 对传递过来的参数进行判断,然后给
output
赋值 - 最后将
output
对象作为参数传递给invoke
方法即可
注意: - 当传递过来的属性在tld中没有定义才会调用
DynamicAttribute
方法 ,静态的会按照tld中的定义正常调用set属性名()
每一个动态属性都会调用DynamicAttribute
方法一次 - 在tld文件中动态属性需要添加一个标签
<dynamic-attributes>true</dynamic-attributes>
- 动态属性不能使用EL表达式指定