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(); } }
ld文件:
<tag> <name>BodyContentToLowerCase</name> <tag-class>tag.Demo1</tag-class> <body-content>tagdependent</body-content> </tag>
效果:
如果文章有错的地方欢迎指正,大家互相交流。