我们写代码的时候,很多类似重复的很繁琐的代码,为了节省写代码的时间,减少代码冗余,我们可以使用自定义jsp标签来制作符合我们要求的标签,使代码更简洁,可读性更强。
jar包:
标签库的运行离不开tld文件,与web.xml文件在同一目录下:
要使用的标签必须在页面头部导入:
prefix的值是对应的tld文件中的short-name的值,uri的值是对应的tld文件的uri的值:
一般的标签:
<开始标签 属性="属性值">标签体结束标签>
空标签:
1.<开始标签/> 例如:
在这类标签中‘/’代表结束
2.没有标签体的空标签:<开始标签>结束标签>
标签分为三种:数据标签、ui标签、控制标签,以下让我们用c标签来说明这三种标签。
set标签 设置值 页面无输出 属于数据标签 操作数据的标签:
<c:set var="name" value="zs" ></c:set>
由于set标签无输出,我们配合out标签看效果,out标签 属于ui标签 在界面上看得到,展示内容的标签 输出指定值:
<c:out value="${name }"></c:out>
效果图,set标签和out标签都用水平线分开来看,可见set标签无输出但是给name赋值了,out标签输出了set标签赋的值:
if标签,做判断,test返回值为Boolean类型,true则执行标签体内的内容,false则跳过标签体,属于控制标签,用来做流程控制的标签:
<c:if test="true">男</c:if>
<c:if test="false">女</c:if>
1.创建一个标签助手类 继承了BodyTagSupport类;
2.创建标签库描述文件(tld文件),添加自定义标签的配置;
3.tld文件中设置的标签属性必须和助手类中的属性相对应 且助手类要提供对应的get/set方法;
4.在jsp页面头部通过taglib标签导入tld文件;
这张流程图中矩形的表示执行步骤,菱形的表示条件,箭头表示流向;
这张流程图有以下几种执行情况:
1.doStartTag—>SKIP_BODY—>doEndTag;
2.doStartTag—>EVAL_BODY_INCLUDE—>doAfterBody—>SKIP_BODY—>doEndTag;
3.doStartTag—>EVAL_BODY_INCLUDE—>doAfterBody—>EVAL_BODY_AGAIN—>SKIP_BODY—>doEndTag
大白话解释:
首先是实例化标签助手类,然后调用了doStartTag方法,这个方法有两个返回值,一个是SKIP_BODY,跳过主体,直接到doEndTag方法,他也有两个返回值一个是SKIP_PAGE,跳过当前页面的剩余内容,意思是这个页面上这个标签后的内容都不再执行,doEndTag方法另一个返回值EVAL-PAGE,计算页面的后续内容是指页面上这个标签后面的内容也会执行,最后取消引用助手类;回过头来看doStartTag方法另一个返回值EVAL_BODY_INCLUDE,计算标签主体内容并输出意为标签体内容会执行,然后会到doAfterBody方法,这个方法有两个返回值,一个是SKIP_BODY,跳过主体,直接到doEndTag方法,还有一个EVAL_BODY_AGAIN再计算主体一次,意为再执行标签体一次,最后直到SKIP_BODY到doEndTag方法取消引用助手类。
名词 | 解释 |
---|---|
name | 标签名前缀 如 |
tag-class | 处理业务的助手类的完整类名 |
body-content | 主体内容 |
attribute | 属性 |
rtexprvalue | 是否支持特殊表达式 |
required | 是否必填 |
创建一个标签助手类,由于set标签无输出不需要标签体,所以在doStartTag返回值中设置了SKIP_BODY:
package com.zengjing.jsp.day02;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;
public class SetTag extends BodyTagSupport{
private static final long serialVersionUID = 1L;
private String var;
private Object value;
public String getVar() {
return var;
}
public void setVar(String var) {
this.var = var;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
@Override
public int doStartTag() throws JspException {
pageContext.setAttribute(var, value);
return SKIP_BODY;
}
}
tld文件中配置,var(变量名)必填,不能为表达式,value(值)必填可为表达式:
<tag>
<name>set</name>
<tag-class>com.zengjing.jsp.day02.SetTag</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>var</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<name>value</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
因为set标签为设置值,与后面的out标签一起展示效果;
创建一个标签助手类,out标签打印出指定的值:
package com.zengjing.jsp.day02;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyTagSupport;
public class OutTag extends BodyTagSupport{
private static final long serialVersionUID = 1L;
private Object value;
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
@Override
public int doStartTag() throws JspException {
JspWriter out = pageContext.getOut();
try {
out.print(value);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return SKIP_BODY;
}
}
tld文件中配置,value属性必填可为表达式:
<tag>
<name>out</name>
<tag-class>com.zengjing.jsp.day02.OutTag</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>value</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
创建一个标签助手类,test为true则执行标签体,为false则跳过标签体:
package com.zengjing.jsp.day02;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;
public class IfTag extends BodyTagSupport{
private boolean test;
public boolean isTest() {
return test;
}
public void setTest(boolean test) {
this.test = test;
}
@Override
public int doStartTag() throws JspException {
// TODO Auto-generated method stub
return test?EVAL_BODY_INCLUDE:SKIP_BODY;
}
}
tld配置,test必填可为表达式:
<tag>
<name>if</name>
<tag-class>com.zengjing.jsp.day02.IfTag</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>test</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>