JSP扩展标签实例教程

用jsp/servlet开发 Web应用,最大的问题是如何让JSP文件中的脚本语言尽可能的少。我们现在广泛采用的jsp/servlet/javabean模式,虽然保证了在 jsp中不会出现大量的商业逻辑代码和数据库的访问,但是不可避免的是仍然会有大量的循环、条件等流程控制语句,降低了代码的可读性,不利于页面设计人员的修改。 为此,JSP1.1提供了javax.servlet.jsp.tagext包,允许我们定制自己的标签。 下面我们用四个实例,一步步阐明它的具体使用。 首先从hello world开始。 在jsp中我们用<sharetop:helloworld />代替<% out.println("hello world")%> 为了让JSP引擎能够解析我们上面写的标签,我们需要在jsp文件中引入我们的标签库,如下句: <%@ taglib uri="/hello" prefix="sharetop" %> 同时修改web.xml文件,加上: <taglib>  <taglib-uri>/hello</taglib-uri>  <taglib-location>/WEB-INF/tlds/hello.tld</taglib-location> </taglib> 这样,JSP引擎就知道到哪里去找我们的标签定义声明了。然后开始编写我们自己的标签库定义文件 hello.tld <?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd"> <taglib> <tlibversion>1.0</tlibversion> <jspversion>1.1</jspversion> <shortname>sharetop</shortname> <info /> <tag> ... </tag> </taglib> 这就是最基本的tld文件格式,也是基于XML的,各个标签什么意思我就不多说了。我们主要操作的是其中的<tag>标签内容。 比如上例,我们建立如下<tag>段: <tag> <name>helloworld</name> <tagclass>com.sharetop.tagext.bbb.HelloWorldTag</tagclass> <bodycontent>JSP</bodycontent> <info/> </tag> 很明显,到这步我们就把定义的标签与将要用于解析这个标签的类关联上了。下面我们要做的事就是实现这个HelloWorldTag类。JSP引擎对自定义标签的解析是采用SAX方式的。所以,我们要做的事就是实现一些接口定义的回调函数。 在javax.servlet.jsp.tagext包里有两个接口:Tag 和 BodyTag,从字面上可以看出它们是分别解析标签和标签体的。在接口Tag中定义了两个方法: public int doStartTag() throws JspTagException; //标签开始解析触发此事件 public int doEndTag() throws JspTagException;  //标签结束解析触发此事件 BodyTag接口继承了Tag,新增了两个方法: public int doInitBody() throws JspTagException;//准备解析标签体触发此事件 public int doAfterBody() throws JspTagException;//完成标签体解析触发此事件 注意这几个方法的返回值都是整数,JSP引擎需要根据返回值决定下一步的操作。 在Tag接口定义的返回常量是EVAL_BODY_INCLUDE、 EVAL_PAGE、 SKIP_BODY和 SKIP_PAGE 。而 BodyTag又新增了一个常量EVAL_BODY_TAG,要注意的是如果在BodyTag中的doStartTag()方法是不能返回 EVAL_BODY_INCLUDE的,只能返回EVAL_BODY_TAG,并且也只有BodyTag的doStartTag()方法可以返回 EVAL_BODY_TAG。 我们不需要直接实现这两个接口(主要是太麻烦),可以继承tagext包为我们提供的两个类:TagSupport 和 BodyTagSupport。 上面HelloWorldTag的代码如下: package com.sharetop.tagext.bbb; import java.io.*; import javax.servlet.jsp.*; import javax.servlet.jsp.tagext.*; public class HelloWorldTag extends TagSupport { public HelloWorldTag() { } public int doEndTag() throws JspTagException {  try{   pageContext.getOut().println("hello world");  }  catch(Exception ex){   //写失败   throw new JspTagException("can't write");  }  //继续分析页面其它部分  return super.EVAL_PAGE; } } 我们的处理很简单,就是用pageContext得到一个JspWriter,输出一句hello world。 注意:pageContext很重要,是标签处理类与jsp页面交互的主要工具。它被定义在TagSupport类里是protected类型的。 第二个例子。如果我们的有属性值怎么办? 比如这句:<sharetop:hellofriend name="superfeel">,我们希望输出是hello superfeel. 好,同样在jsp页引入标签库的定义文件(以下同),在tld文件中加入新的<tag>定义: <tag> <name>hellofriend</name> <tagclass>com.sharetop.tagext.bbb.HelloFriendTag</tagclass> <bodycontent>JSP</bodycontent> <info /> <attribute> <name>name</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name>sex</name> <required>false</required> <rtexprvalue>true</rtexprvalue> </attribute> </tag> 上面我们定义了两个属性,name和sex,其中sex是可有可无的(因为下面的例子要用,所以先定义在这里)。 然后就是实现文件HelloFriendTag的代码如下(限于篇幅,后面提供的代码都省略包和import语句): public class HelloFriendTag extends TagSupport { public HelloFriendTag() { } public int doStartTag() throws JspTagException {  try{   pageContext.getOut().println("Hello "+name);  }  catch(Exception ex){   throw new JspTagException(ex.getMessage());  }  return super.EVAL_PAGE; } /** *成员属性即为标签的属性 */ public void setName(String name) { this.name = name; } public String getName() { return name; } public void setSex(String sex) { this.sex = sex; } public String getSex() { return sex; } private String name; private String sex; } 其实很简单,类的成员属性就是标签的属性,所以你只需为这个HelloFriendTag定义两个同名的属性即可。 好,到这里我们了解了扩展标签的基本实现。下一篇我们将讨论标签体、循环和标签嵌套的内容。

你可能感兴趣的:(jsp)