三个步骤:1,java的实现类继承TagSupport ,BodyTagSupport 或者simpleTagSupport
2,*.tld的标签文件的配置 ,位置在WEB-INF下面
3,(可选)web.xml中的标签的名字配置
4, 页面的引入
第一个简单的标签:
·实现类:
public class Tag1 extends TagSupport{
//<a>-->标签的开始 </a>--->标签的结束
public int doStartTag(){
JspWriter out = super.pageContext.getOut();
try {
out.print("<b>hello!world</b>");
} catch (IOException e) {
e.printStackTrace();
}
return SKIP_BODY;
}
}
·标签文件
<tag>
<name>showHello</name> //这个就相当于<c:forEach>
<tag-class>myTag.Tag1</tag-class>
<body-content>empty</body-content>
</tag>
·web.xml中(可选)
<jsp-config>
<taglib>
<taglib-uri>firstTag</taglib-uri>
//下面是指定.tld文件的位置
<taglib-location>/WEB-INF/mytld.tld</taglib-location>
</taglib>
</jsp-config>
·jsp页面:
//如果是配置了web.xml的话
//<%@ taglib prefix="firstTag" uri="firstTag"%>
//没有配置web.xml
<%@ taglib prefix="firstTag" uri="/WEB-INF/mytld.tld"%>
java实现类:
public class DateFormat extends TagSupport{
private String formatString ; //利用反射机制调用setter方法来赋值
public String getFormatString() {
return formatString;
}
public void setFormatString(String formatString) {
this.formatString = formatString;
}
@Override
public int doStartTag() throws JspException {
SimpleDateFormat simpleDateFormat= new SimpleDateFormat(formatString);
Date date = new Date();
String dateString = simpleDateFormat.format(date);
try {
super.pageContext.getOut().print(dateString);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return SKIP_BODY; //跳过标签体
}
}
标签文件:
<tag>
<name>dateFormat</name> //这个就相当于<c:forEach>
<tag-class>myTag.DateFormat</tag-class>
<body-content>empty</body-content>
<attribute>
<name>formatString</name> //这个名字要和java类中的字段一样
<required>true</required> //此属性一定要设置
<rtexprvalue>true</rtexprvalue> //是否接受表达式
</attribute>
</tag>
对于web.xml和页面的设置和上面是一样的
· EVAL_BODY_INCLUDE(执行标签体内的内容),
·EVAL_PAGE 执行jsp页面
·SKIP_BODY 跳过标签体
·SKIP_PAGE 结束jsp页面
实现类中这样写:
public int doStartTag() throws JspException {
if(num > 0){
return EVAL_BODY_INCLUDE;
}
return SKIP_BODY;
}
其他的跟上面的列子一样的
迭代自定义标签
页面代码:
<my:loop var="s" name="list" scope="request">
${s }
</my:loop>
实现类:
public class LoopTag extends TagSupport {
private String name; //可以把这个字段名看做是jsp页面里面的字段里面的值
private String scope; //是通过反射setter来赋值的
private String var;//对于循环的每一个对象
//这个是个很重要的东西,这个不需要getter和setter方法
//迭代器,用来判断是否有下一个
private Iterator iterator ;
public int doStartTag() throws JspException {
Object val = null;
if("request".equalsIgnoreCase(scope)){
val = super.pageContext.getAttribute(this.name,PageContext.REQUEST_SCOPE);
}
if(val != null && val instanceof List<?>){
iterator = ((List<?>)val).iterator(); //这里要注意,把list转变为迭代器,以为要判断下一个是否存在
if (iterator.hasNext()) {//***这里不是while,是if,只需要判读一次
super.pageContext.setAttribute(this.var, iterator.next()); //把val存放到页面中名字为var中的值的对象*******
return EVAL_BODY_INCLUDE; //执行body里面的代码 ${..}
}else {
return SKIP_BODY;
}
}else {
return SKIP_BODY;
}
}
@Override
public int doAfterBody() throws JspException {
if (iterator.hasNext()) { //如果还有下一个,就重复执行body里面
super.pageContext.setAttribute(this.var, iterator.next());//ooo return EVAL_BODY_AGAIN;
}else {
return SKIP_BODY;
}
}
....setter getter方法
}
public class BodyTagSupport extends TagSupport implements BodyTag
BodyTagSupport与TagSupport的不同就是它可以得到标签体里面的内容,在BodyTagSupport里面得到标签体里面的内容是getBodyContent().getString();且要写在doAfterTagSupport()里面,
在TagSupport里面得到输出流是pageContext.getOut();
在BodyTagSupport里面需要getPreviousOut();来得到
例子:大写的转换
public int doAfterBody() throws JspException {
--count;
if(count > 0){
//得到标签里面的内容,getBodyContent().getString()这个要写到doAfterBody()里面
String content = getBodyContent().getString();
if(content!=null){
String upContent = content.toUpperCase();
try {
//得到输出流
this.getPreviousOut().print(upContent);
} catch (IOException e) {
e.printStackTrace();
}
}
return EVAL_BODY_AGAIN;
}else{
return SKIP_BODY;
}
}
对于SimpleSupport与TagSupport和BodyTagSupport的不同就是,SimpleSupport简化了一下操作,它只要重新doTag() 就可以了,SimpleSupport是通过getJspContext()来得到隐士对象的,相当于TagSupport的pageContext,通过getJspBody来的的标签体对象
迭代的例子:(其他部分都跟上面的的相同)
public void doTag() throws javax.servlet.jsp.JspException ,java.io.IOException {
Object value = this.getJspContext().getAttribute(name,PageContext.REQUEST_SCOPE);
if(value != null && value instanceof List<?>){
iterator = ((List<?>)value).iterator();
while (iterator.hasNext()) {
this.getJspContext().setAttribute(this.var, iterator.next());
//执行标签里面的内容,null意思就是知识执行标签里面生成的内容
super.getJspBody().invoke(null); //执行${ },因为在上面已经设置了值
}
}
};
配置文件:
<tag>
<name>loop</name>
<tag-class>myTag.LoopTag</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>name</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>scope</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>var</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
日期转换:
@Override
public void doTag() throws JspException, IOException {
SimpleDateFormat sd = new SimpleDateFormat(format);
String dateString = sd.format(new Date());
getJspContext().getOut().print(dateString);
}