JSP第六篇【自定义标签之传统标签】(修订版)(二)

简介: 笔记

带属性的标签


上面我们编写的自定义标签都没有附带属性的,我们在使用core标签库的时候,标签一般都带有属性

其实JSTL标签库的原理就是自定义标签,把自定义标签搞明白了,对JSTL标签库的使用就有更好的理解了

  • 想要自定义标签带有属性也非常简单,只要在标签处理器类上加一个成员变量和setter、getter(),再在tld文件中描述下该属性即可!它的原理是这样的:当标签使用到属性的时候,引擎就会调用它的setter()方法
  • 下面我想要完成的功能是:使用标签的人,传入一个字符串格式就可以显示想要的格式日期
  • 编写标签处理器类,增加一个成员变量以及对应的setter、getter方法
public class Demo1 extends TagSupport {
    //创建成员对象,对应的setter、getter方法
    private String format = null;
    @Override
    public int doStartTag() throws JspException {
        //创建日期格式化对象
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        //格式化日期并向浏览器输出
        try {
            pageContext.getOut().write(simpleDateFormat.format(new Date()));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return 0;
    }
    public String getFormat() {
        return format;
    }
    public void setFormat(String format) {
        this.format = format;
    }
}
  • 在tld文件中描述标签和属性,name代表的是属性的名字,required代表的是是否为必须,rtexprvalue代表能否使用EL表达式
<tag>
    <name>formatDate</name>
    <tag-class>tag.Demo1</tag-class>
    <body-content>empty</body-content>
    <attribute>
        <name>format</name>
        <required>true</required>
        <rtexprvalue>true</rtexprvalue>
    </attribute>
</tag>
  • 我们来看一下效果:

37.png38.png


标签的继承关系


  • 在深入讲解之前,我们先来看一下各种Tag接口、类之间的关系,这样学习下去才不会晕

39.png


IterationTag说明


  • 我们已经使用过了Tag接口和TagSupport类了。接下来我们看一下IterationTag是什么玩意。
public interface IterationTag extends Tag {
    int EVAL_BODY_AGAIN = 2;
    int doAfterBody() throws JspException;
}
  • 从关系图我们也可以看出,IterationTag接口实现了Tag接口,InterationTag接口和Tag接口最主要的区别就是多了个doAfterBody()方法和EVAL_BODY_AGAIN变量
  • 理解起来也很简单:当doAfterBody()返回的是EVAL_BODY_AGAIN变量,那么标签体的内容就一直循环!当然了,TagSupport也实现了Iteration接口,也就是说TagSupport类也能完成Iteration接口的事情
  • 我们来使用一下吧:
public class Demo1 extends TagSupport {
    @Override
    public int doStartTag() throws JspException {
        try {
            pageContext.getOut().write("hello");
        } catch (IOException e) {
            e.printStackTrace();
        }
        //执行标签体
        return EVAL_BODY_INCLUDE;
    }
    @Override
    public int doAfterBody() throws JspException {
        //标签体不断循环,直到doAfterBody()返回的是SKIP_BODY
        return EVAL_BODY_AGAIN;
    }
}
  • tld文件中描述,既然标签体有内容,就不能用empty了
<tag>
    <name>foreverEval</name>
    <tag-class>tag.Demo1</tag-class>
    <body-content>tagdependent</body-content>
</tag>
  • 注意看横向的滑轮,已经死循环输出了:

40.png

  • doAfterBody()中只要返回的是SKPI_BODY就退出循环,执行doEndTag()方法
//定义一个变量,规定标签体循环的次数
int x = 0;
@Override
public int doStartTag() throws JspException {
    try {
        pageContext.getOut().write("hello");
    } catch (IOException e) {
        e.printStackTrace();
    }
    //执行标签体
    return EVAL_BODY_INCLUDE;
}
@Override
public int doAfterBody() throws JspException {
    x++;
    if (x >= 10) {
        return SKIP_BODY;
    }
    //标签体不断循环,直到doAfterBody()返回的是SKIP_BODY
    return EVAL_BODY_AGAIN;
}
  • 现在我们已经能控制循环的次数了

41.png


BodyTag说明


前面我们已经使用到了带标签体的自定义标签了,前面的都是只能直接输出而得不到标签体的内容,既然得不到标签体的内容,就更别说修改标签体了

  • 此时,我们就需要BodyTag接口的支持了!它专门用来处理带标签体的标签,下面我们来看一下BodyTag的源码
public interface BodyTag extends IterationTag {
    /** @deprecated */
    int EVAL_BODY_TAG = 2;
    int EVAL_BODY_BUFFERED = 2;
    void setBodyContent(BodyContent var1);
    void doInitBody() throws JspException;
}
  • BodyTag多了EVAL_BODY_BUFFERED变量【一个已经标识过时了】,多了setBodyContent和doInitBody()两个方法
  • 其实使用BodyTag十分简单
  • 如果doStartTag()方法返回的是EVAL_BODY_BUFFERED,把标签体的内容缓存起来
  • 接着调用setBodyContent()方法和doInitBody()方法,封装标签体的内容到BodyContent对象中
  • 接着调用doEndTag()方法
  • 对于标签体的内容,我们可以通过getBodyContenet()来获取!
  • 再看回上面的关系图,BodyTag实现了IterationTag和Tag接口,如果直接实现BodyTag接口做开发,要实现的方法就太多了。一般我们使用继承BodyTag的BodyTagSupport来做开发


BodyTagSupport说明


  • 首先来看一下源代码吧:
public class BodyTagSupport extends TagSupport implements BodyTag {
    protected BodyContent bodyContent;
    public BodyTagSupport() {
    }
    public int doStartTag() throws JspException {
        return 2;
    }
    public int doEndTag() throws JspException {
        return super.doEndTag();
    }
    public void setBodyContent(BodyContent b) {
        this.bodyContent = b;
    }
    public void doInitBody() throws JspException {
    }
    public int doAfterBody() throws JspException {
        return 0;
    }
    public void release() {
        this.bodyContent = null;
        super.release();
    }
    public BodyContent getBodyContent() {
        return this.bodyContent;
    }
    public JspWriter getPreviousOut() {
        return this.bodyContent.getEnclosingWriter();
    }
}
  • 可以发现:BodyTagSupport主要扩充了以下的内容:
  • 把BodyContent直接定义为成员变量,在获取标签体内容的时候就不需要通过getBodyContent()获取了
  • 提供获取JspWriter的方法,不需要从pageConext中获取了
  • 以上的两个扩充都简化了我们的代码书写
protected BodyContent bodyContent;
public JspWriter getPreviousOut() {
    return this.bodyContent.getEnclosingWriter();
}
  • 从BodyTag接口中,我就说到了:标签体的内容封装到了BodyContent类中,那么BodyContent类究竟是什么?我们来看一下源码
public abstract class BodyContent extends JspWriter {
    private JspWriter enclosingWriter;
    protected BodyContent(JspWriter e) {
        super(-2, false);
        this.enclosingWriter = e;
    }
    public void flush() throws IOException {
        throw new IOException("Illegal to flush within a custom tag");
    }
    public void clearBody() {
        try {
            this.clear();
        } catch (IOException var2) {
            throw new Error("internal error!;");
        }
    }
    public abstract Reader getReader();
    public abstract String getString();
    public abstract void writeOut(Writer var1) throws IOException;
    public JspWriter getEnclosingWriter() {
        return this.enclosingWriter;
    }
}
  • 原来BodyContent继承着JspWriter,它与JspWriter最大的区别是:BodyContent类的任何写入的内容并不自动地向页面输出!
  • 我们一般使用BodyContent都使用两个方法:
//将数据转变成Reader对象
public abstract Reader getReader();
//将数据转变成String对象
public abstract String getString();
  • 再从关系图我们可以看初,BodyTagSupport继承了TagSupport类实现了BodyTag接口,可以说:BodyTagSupport有着前面讲的接口和类的所有功能!
  • 下面我们来使用下BodyTagSupport将标签体的内容转成是小写的
  • 标签处理器类
public class Demo1 extends BodyTagSupport {
    @Override
    public int doStartTag() throws JspException {
        //想要获取到标签体的内容,就要返回EVAL_BODY_BUFFERED变量
        return EVAL_BODY_BUFFERED;
    }
    @Override
    public int doEndTag() throws JspException {
        //获取到标签体的内容
        String value = bodyContent.getString();
        //将标签体的内容转成小写并输出
        try {
            this.getPreviousOut().write(value.toLowerCase());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return super.doEndTag();
    }
}
  • tld文件:
<tag>
    <name>BodyContentToLowerCase</name>
    <tag-class>tag.Demo1</tag-class>
    <body-content>tagdependent</body-content>
</tag>
  • 效果:

42.png

目录
相关文章
|
5月前
|
SQL XML Java
JSP 教程 之 JSP 标准标签库(JSTL) 4
**JSP的JSTL是用于简化Web开发的标签库,包括核心、格式化、SQL、XML和函数5个部分。SQL标签库允许与数据库交互,如设定数据源、执行查询和更新,以及处理参数。例如, `&lt;sql:setDataSource&gt;` 定义数据源, `&lt;sql:query&gt;` 执行查询。通过使用JSTL,开发者能更整洁地处理JSP页面。**
48 8
|
5月前
|
XML SQL Java
JSP 教程 之 JSP 标准标签库(JSTL) 1
JSP的JSTL是用于简化页面逻辑的标签库,涵盖核心、格式化、SQL、XML和函数五大类标签。要安装,下载Apache的JSTL包,将jar文件放入WEB-INF/lib,tld文件复制到WEB-INF,并在web.xml中配置相应的taglib信息。JSTL促进了JSP页面的清洁和结构化。
42 5
|
5月前
|
XML SQL Java
JSP 教程 之 JSP 标准标签库(JSTL) 6
**JSP JSTL 摘要:** JSTL是JSP的标签库,包含核心、格式化、SQL、XML和函数5类标签。它用于执行常见任务,如迭代、条件判断和XML操作。JSTL函数库提供字符串处理函数,如`contains()`, `endsWith()`, `escapeXml()`等,方便XML和HTML处理。通过`&lt;%@ taglib %&gt;`导入,如`fn:trim()`用于去除字符串两端空白。
39 5
|
5月前
|
Java 容器
JSP 教程 之 JSP 自定义标签 3
JSP自定义标签允许开发人员创建可重用的组件,简化页面逻辑。在JSP 2.0及以上版本,可通过继承`SimpleTagSupport`并覆写`doTag()`方法来创建自定义标签,如`HelloTag`,它有一个`message`属性。属性值通过setter方法`setMessage()`设置。在TLD文件中定义该属性后,可在JSP页面使用`&lt;ex:Hello message=&quot;This is custom tag&quot;/&gt;`来调用,输出定制的文本。
26 0
|
5月前
|
Java 容器
JSP 教程 之 JSP 自定义标签 4
**JSP自定义标签允许创建用户定义的语言元素。它们转换为Servlet中的tag handler,在执行时由Web容器调用。使用SimpleTagSupport继承并重写doTag()方法可创建简单标签。标签可设置属性,如message,通过setter方法访问。TLD文件定义属性元数据,JSP页面则通过prefix和uri引用。例如,&lt;ex:Hello message=&quot;...&quot;/&gt; 显示定制消息。属性可配置为必需、类型、描述及是否为JspFragment。**
29 0
|
5月前
|
搜索推荐 Java 容器
JSP 教程 之 JSP 自定义标签 2
**JSP自定义标签允许用户创建个性化标签,简化页面逻辑。在JSP 2.0中,通过继承`SimpleTagSupport`并重写`doTag()`可创建简单标签处理器。示例展示了一个名为`Hello`的自定义标签,它接收并显示标签体内容。TLD文件配置了标签元数据,JSP页面引用该标签并展示“这是消息主体”。**
24 0
|
5月前
|
Java 容器
JSP 教程 之 JSP 自定义标签 1
**JSP自定义标签简介**:扩展JSP功能,创建用户定义标签,通过Servlet容器调用Tag Handler。在JSP 2.0中,使用SimpleTagHandlers简化定制。以&quot;Hello&quot;标签为例,创建`HelloTag`类继承`SimpleTagSupport`,重写`doTag()`打印消息。编译后,在`custom.tld`定义标签库,JSP页面引用后即可使用。例如 `&lt;ex:Hello/&gt;` 显示 &quot;Hello Custom Tag!&quot;。
28 0
|
5月前
|
Java 应用服务中间件 Android开发
完成你的自定义JSP Tag标签-Basic Coustom Tag
完成你的自定义JSP Tag标签-Basic Coustom Tag
33 0
|
6月前
|
Java
jsp页面中使用jstl标签报错:javax.servlet.jsp.JspTagException
jsp页面中使用jstl标签报错:javax.servlet.jsp.JspTagException
85 0
|
6月前
|
Java 数据安全/隐私保护
Jsp自定义标签(foreach,dept,select)
Jsp自定义标签(foreach,dept,select)
48 0