demo下载:test-tag.zip
开始学jsp的时候觉得jstl很酷炫,很神秘,还经常因为jar包找不到而沮丧,工作之后发现很多项目都有自定义tag库,tag库用的好,确实能减少service层的复杂性,通过查阅资料,对其有了一定的了解,将其写出来,共哪些对这个主题感兴趣的同学借鉴,
java自带的tag库的层级如下
如果只是简单的处理,可以继承自SimpleTagSupport,重载doTag()方法,先来个HelloTag.java
public class HelloTag extends SimpleTagSupport { private String name; @Override public void doTag() throws JspException, IOException { JspWriter writer = this.getJspContext().getOut(); writer.write("hello " + name); } public void setName(String name) { this.name = name; } }
public class HelloTag extends SimpleTagSupport { private String name; @Override public void doTag() throws JspException, IOException { JspWriterwriter = this.getJspContext().getOut(); writer.write("hello " + name); } public void setName(String name) { this.name = name; } }
如果你的tag需要支持属性,比如HelloTag中的name属性,那么需要为其添加一个setter方法。doTag()的实现也很简单,获取JspWriter,向页面输出”hello ” + name内容。接下来需要创建一个.tld的描述文件,内容如下:
<?xml version="1.0" encoding="UTF-8" ?> <taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" version="2.0"> <tlib-version>1.0</tlib-version> <jsp-version>2.0</jsp-version> <short-name>Example TLD with Body</short-name> <uri>http://javacoder.cn/jsp/jtag</uri> <tag> <name>hello</name> <tag-class>cn.javacoder.test.tag.HelloTag</tag-class> <body-content>empty</body-content> <attribute> <name>name</name> <rtexprvalue>false</rtexprvalue> <required>true</required> <description> <![CDATA[ this is a hello test ]]> </description> </attribute> </tag> </taglib>
<?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/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" version="2.0"> <tlib-version>1.0</tlib-version> <jsp-version>2.0</jsp-version> <short-name>ExampleTLDwithBody</short-name> <uri>http://javacoder.cn/jsp/jtag</uri> <tag> <name>hello</name> <tag-class>cn.javacoder.test.tag.HelloTag</tag-class> <body-content>empty</body-content> <attribute> <name>name</name> <rtexprvalue>false</rtexprvalue> <required>true</required> <description> <![CDATA[ this is a hellotest ]]> </description> </attribute> </tag> </taglib>
大家也不必强记这个文件格式,在<%@ taglib prefix=”fmt” uri=”http://java.sun.com/jsp/jstl/fmt”%> 处,”ctrl+鼠标左键”可以查看该tag库的tld,然后依猫画虎啦。
这个tld文件其实就是一个xml文件,引入web-jsptaglibrary_2_0.xsd是为了内容验证,当然uri也可以不加的。rtexprvalue表示值的内容是否为表达式,比如el表达式。
接下来创建一个test.jsp,添加内容如下:
<%@ taglib prefix=”ex” uri=”/WEB-INF/classes/custom.tld”%>
<ex:hello name=”javacoder.cn”/>
第一行代码的作用是导入我们的标签库,第二行是调用我们的tag。
部署到服务器,访问这个页面,那么会向页面输出”javacoder.cn”
这就是TagSupport和BodyTagSupport抽象类大显身手的时候了。
TagSupport中几个重要的,需要我们根据实际的业务重载的方法如下:
public int doStartTag() throws JspException
标识tag处理开始,处理流程和在doTag()方法中一样,获取Writer,向页面输出内容。如果需要处理tag的boby部分,就是这个tag有包含的内容,那么返回EVAL_BODY_INCLUDE否则返回SKIP_BODY。
public int doEndTag() throws JspException
标识一个tag处理结束。合法的返回值是EVAL_PAGE和SKIP_PAGE。一般当包含子tag的时候,才需要实现doEndTag()方法,比如当然tag输出table元素,那么在子元素处理完成后,需要在这个方法中输出”</table>”这样的结束元素。
public int doAfterBody() throws JspException
当doStartTag方法返回EVAL_BODY_BUFFERED时,tag的处理流程如下。
当doStartTag()执行完成后,会创建一个bodyContent对象,然后,处理该tag包含的子元素,当子元素处理完成后,会调用doAfterBody方法,如果doAfterBody返回 EVAL_BODY_AGAIN,那么会再次处理子元素,如果返回SKIP_BODY那么调用doEndTag(),结束本tag的处理。这个可以参考core标签库的c:forEach的实现。
BodyTagSupport类继承自TagSupport,一个重要的扩展是我们可以高效地处理tag的body内容。这个基类的一个重要扩展是添加了bodyContent。demo中的cn.javacoder.test.tag.LoopTag虽然有点无聊,但是也是对这个功能的一个演示。
本demo还实现了另外的两个标签,TableTag, TrTag,用来演示el表达式的使用。欢迎下载
本文由javacoder.cn博主提供,转载请注明出处!
Posted in:WEB开发