自定义标签
主要用于移除JSP页面中的java代码
未使用自定义标签输出客户机IP:
您的IP是:
<%
Stringip=request.getRemoteAddr();//得到客户端的远程地址
out.println(ip);
%>
使用自定义标签输出客户机IP:
<dhw:viewIP>
自定义标签的创建步骤:
(1) 标签处理器——java类,实现Tag接口
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.TagSupport;
publicclass CusTagDemo1 extends TagSupport{
//标签处理器————把JSP页面中嵌入的java代码拿出来,放到该类的doStartTag()方法中,向输出用户的IP地址
@Override
public int doStartTag() throwsJspException {
HttpServletRequestrequest=(HttpServletRequest) this.pageContext.getRequest();
//获取输出流对象
JspWriter jw=pageContext.getOut();
Stringip=request.getRemoteAddr();//得到客户端的远程地址
try{
jw.println(ip);
} catch (IOException e) {
// TODO Auto-generatedcatch block
throw newRuntimeException();
}
return super.doStartTag();
}
}
导入自定义标签库:
<%@taglib uri=”http://www.hbsi.edu.cn” prefix=”hbsi”%>
TagDemo1中:
%@taglib uri=”http://www.hbsi.edu.cn” prefix=”hbsi”%
您的IP是:<hbsi:viewIP/>
(2) 编写名字叫tld的文件——用来编写自定义标签
<?xmlversion="1.0" encoding="UTF-8" ?>
<taglibxmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2eehttp://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
<tlib-version>1.0</tlib-version>
<short-name>hbsi</short-name>
<uri>http://www.hbsi.edu.cn</uri>
<tag>
<name>viewIP</name>
<tag-class>com.hbsi.tag.CusTagDemo1</tag-class>
<body-content>empty</body-content>
</tag>
</taglib>
遇到自定义中的子标签时自动调用doStartTag()
遇到自定义中的尾标签时自动调用doEndTag()
Release()方法:释放标签处理器运行时占用的资源(服务器停掉时才会调用)
自定义功能扩展:
1、通过自定义标签可以控制jsp页面某一部分内容是否执行
2、通过自定义标签可以控制标签后的页面是否执行
Tag接口:
(1) 通过doStartTag()的返回值决定是否处理标签体的内容
Tag.EVAL_BODY_INCLUDE Tag.SKIP_BODY
(2) 通过doEndTag()方法的返回值决定是否继续处理jsp页面中该自定义标签之后的内容
Tag.SKIP_PAGE //跳过自定义标签后的所有内容
Tag.EVAL_PAGE //处理完自定义标签以后还会继续处理后面的内容
Tag接口的执行流程:
1) JSP引擎遇到自定义标签时,创建标签处理器类的实例对象
2) 调用setPageContext()方法,将pageContext对象传递给标签处理器
3) 调用setPageParent()方法将当前标签传递给当前标签处理器,如果当前标签没有父标签,则传递给setParent的值为null
4) 调用doStartTag()方法
5) 调用doEndTag()方法
6) 通常情况下web容器执行完自定义标签后,标签处理器会驻留在内存中,为其他请求服务器,直至停止web应用时,web容器才会调用release()方法
IterationTag接口:
1) 将自定义标签对应的标签处理器实例化成对象
2) 调用标签处理器对象的setPageContext()将jsp页面的pageContext对象做参数传给标签处理器
3) 调用标签处理器对象setParent()将父标签对象作为参数传递给标签处理器对象
4) 调用doStartTag(),返回值决定是否要执行标签体
5) 标签体的处理
6) 在尾标签之前调用doAfterBody[标签体处理完,调用doEndTag()方法之前]——返回值可以决定是否要重复执行标签体的内容
7) 调用doEndTag()
标签的内容存放到BodyContent对象的缓冲区中
3、通过自定义标签可以控制jsp页面某一部分内容重复执行
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.IterationTag;
import javax.servlet.jsp.tagext.Tag;
import javax.servlet.jsp.tagext.TagSupport;
publicclass CusTagDemo4 extends TagSupport {
private int count=5;
@Override
public int doAfterBody() throwsJspException {
// TODO Auto-generated method stub
count--;
if(count>0){
returnIterationTag.EVAL_BODY_AGAIN;
}
else{
returnIterationTag.SKIP_BODY;
}
}
@Override
public int doStartTag() throwsJspException {
// TODO Auto-generatedmethod stub
returnTag.EVAL_BODY_INCLUDE;//显示标签体
}
}
4、通过自定义标签可以修改jsp页面内容输出
import java.io.IOException;
import javax.management.RuntimeErrorException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyContent;
import javax.servlet.jsp.tagext.BodyTag;
import javax.servlet.jsp.tagext.BodyTagSupport;
import javax.servlet.jsp.tagext.Tag;
//能够获取到标签体的内容,对标签体的内容进行相应的修改,再输出到客户端
publicclass CusTagDemo5 extends BodyTagSupport {
@Override
public int doEndTag() throws JspException{
// TODO Auto-generated method stub
BodyContentbc=this.getBodyContent();
String str=bc.getString();//得到标签体的内容并转换成字符串
str=str.toUpperCase();//大小写转换,全部转化为大写
try {
pageContext.getOut().write(str);
} catch (IOException e) {
// TODO Auto-generatedcatch block
throw newRuntimeException();//抛出运行时异常
}
return Tag.EVAL_PAGE;//也可以写为this.EVAL_PAGE;
}
@Override
public int doStartTag() throwsJspException {
// TODO Auto-generated method stub
returnBodyTag.EVAL_BODY_BUFFERED;//把标签体的内容存入到BodyContent对象的缓冲区中
}
}
tld文件中的四种标签体类型:
EMPTY、JSP、scriptless、tagdepentend
TIP:简单标签
简单标签定义的5个方法:
1、 setJspContext方法
用于把JSP页面的pageContext对象传递给标签处理器对象
2、 setParent方法
用于把父标签处理器对象传递给当前标签处理器对象
3、 getParent方法
用于获得当前标签的父标签处理器对象
4、 setJspBody方法
用于把代表标签体的JspFragment对象传递给标签处理器对象
5、 doTag方法
用于完成所有的标签逻辑,包括输出、迭代、修改标签体内容等。在doTag方法中可以抛出javax.servlet.jsp.SkipPageException异常,用于通知WEB容器不再执行JSP页面中位于结束标记后面的内容,这等效于在传统标签的doEndTag方法中返回Tag.SKIP_PAGE常量的情况。
TIP:Simple Tag接口方法的执行顺序:
1、 当web容器开始执行标签时,会调用如下方法完成标签的初始化
(1)WEB容器调用标签处理器对象的setJspContext方法,将代表JSP页面的pageContext对象传递给标签处理器对象。
(2)WEB容器调用标签处理器对象的setParent方法,将父标签处理器对象传递给这个标签处理器对象。注意,只有在标签存在父标签的情况下,WEB容器才会调用这个方法。
(3)如果调用标签时设置了属性,容器将调用每个属性对应的setter方法把属性值传递给标签处理器对象。如果标签的属性值是EL表达式或脚本表达式,则WEB容器首先计算表达式的值,然后把值传递给标签处理器对象。
(4)如果简单标签有标签体,容器将调用setJspBody方法把代表标签体的JspFragment对象传递进来。
2、 执行标签时:
容器调用标签处理器的doTag()方法,开发人员在方法体内通过操作JspFragment对象,就可以实现是否执行、迭代、修改标签体的目的
TIP:invoke方法
利用这个方法可以控制是否执行和输出标签体的内容、是否迭代执行标签体的内容或对标签体的执行结果进行修改后再输出
在标签处理器中如果没有调用JspFragment.invoke方法,其结果就相当于忽略标签体内容;
在标签处理器中重复调用JspFragment.invoke方法,则标签体内容将会被重复执行;
若想在标签处理器中修改标签体内容,只需在调用invoke方法时指定一个可取出结果数据的输出流对象(例如StringWriter),让标签体的执行结果输出到该输出流对象中,然后从该输出流对象中取出数据进行修改后再输出到目标设备,即可达到修改标签体的目的。
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;
publicclass SimpleTagDemo extends SimpleTagSupport {
@Override
public void doTag() throws JspException,IOException {
// TODO Auto-generated method stub
//系统自动调用,把标签体中的内容封装成对象
JspFragmentjf=this.getJspBody();//得到标签体对象
jf.invoke(this.getJspContext().getOut());//输出到客户端
//jf.invoke(null);//输出到客户端
super.doTag();
}
}