JSP传统标签开发
标签技术的api
标签技术的api类继承关系
标签api简单介绍
jsptag接口">jsptag接口
jsptag接口是所有自定义标签的父接口,它是jsp2.0中新定义的一个标记接口,没有任何属性和方法。jsptag接口有tag和simpletag两个直接子接口,jsp2.0以前的版本中只有tag接口,所以把实现tag接口的自定义标签也叫做传统标签,把实现simpletag接口的自定义标签叫做简单标签。
tag接口
tag接口是所有传统标签的父接口,其中定义了两个重要方法(dostarttag、doendtag)方法和四个常量(eval_body_include、skip_body、eval_page、skip_page),这两个方法和四个常量的作用如下:
web容器在解释执行jsp页面的过程中,遇到自定义标签的开始标记就会去调用标签处理器的dostarttag方法,dostarttag方法执行完后可以向web容器返回常量eval_body_include或skip_body。如果dostarttag方法返回eval_body_include,web容器就会接着执行自定义标签的标签体;如果dostarttag方法返回skip_body,web容器就会忽略自定义标签的标签体,直接解释执行自定义标签的结束标记。 web容器解释执行到自定义标签的结束标记时,就会调用标签处理器的doendtag方法,doendtag方法执行完后可以向web容器返回常量eval_page或skip_page。如果doendtag方法返回常量eval_page,web容器就会接着执行jsp页面中位于结束标记后面的jsp代码;如果doendtag方法返回skip_page,web容器就会忽略jsp页面中位于结束标记后面的所有内容。doendtag()方法的返回值——标识是不是继续执行余下的jsp。要想用标签控制余下的jsp是否执行,只需控制doendtag()方法的返回值。
从dostarttag和doendtag方法的作用和返回值的作用可以看出,开发自定义标签时可以在dostarttag方法和doendtag方法体内编写合适的java程序代码来实现具体的功能,通过控制dostarttag方法和doendtag方法的返回值,还可以告诉web容器是否执行自定义标签中的标签体内容和jsp页面中位于自定义标签的结束标记后面的内容。
iterationtag接口
iterationtag接口继承了tag接口,并在tag接口的基础上增加了一个doafterbody方法和一个eval_body_again常量。实现iterationtag接口的标签除了可以完成tag接口所能完成的功能外,还能够通知web容器是否重复执行标签体内容。对于实现了iterationtag接口的自定义标签,web容器在执行完自定义标签的标签体后,将调用标签处理器的doafterbody方法,doafterbody方法可以向web容器返回常量eval_body_again或skip_body。如果doafterbody方法返回eval_body_again,web容器就会把标签体内容再重复执行一次,执行完后接着再调用doafterbody方法,如此往复,直到doafterbody方法返回常量skip_body,web容器才会开始处理标签的结束标记和调用doendtag方法。
可见,开发自定义标签时,可以通过控制doafterbody方法的返回值来告诉web容器是否重复执行标签体内容,从而达到循环处理标签体内容的效果。例如,可以通过一个实现iterationtag接口的标签来迭代输出一个集合中的所有元素,在标签体部分指定元素的输出格式。
在jsp api中也提供了iterationtag接口的默认实现类tagsupport,我们在编写自定义标签的标签处理器类时,可以继承和扩展tagsupport类,这相比实现iterationtag接口将简化开发工作。
bodytag接口
bodytag接口继承了iterationtag接口,并在iterationtag接口的基础上增加了两个方法(setbodycontent、doinitbody)和一个eval_body_buffered常量。实现bodytag接口的标签除了可以完成iterationtag接口所能完成的功能,还可以对标签体内容进行修改。对于实现了bodytag接口的自定义标签,标签处理器的dostarttag方法不仅可以返回前面讲解的常量eval_body_include或skip_body,还可以返回常量eval_body_buffered。如果dostarttag方法返回eval_body_buffered,web容器就会创建一个专用于捕获标签体运行结果的bodycontent对象,然后调用标签处理器的setbodycontent方法将bodycontent对象的引用传递给标签处理器,web容器接着将标签体的执行结果写入到bodycontent对象中。在标签处理器的后续事件方法中,可以通过先前保存的bodycontent对象的引用来获取标签体的执行结果,然后调用bodycontent对象特有的方法对bodycontent对象中的内容(即标签体的执行结果)进行修改和控制其输出。
在jsp api中也提供了bodytag接口的实现类bodytagsupport,我们在编写能够修改标签体内容的自定义标签的标签处理器类时,可以继承和扩展bodytagsupport类,这相比实现bodytag接口将简化开发工作。
simpletag接口
simpletag接口是jsp2.0中新增的一个标签接口。由于传统标签使用三个标签接口来完成不同的功能,显得过于繁琐,不利于标签技术的,因此,sun公司为降低标签技术的学习难度,在jsp 2.0中定义了一个更为简单、便于编写和调用的simpletag接口。simpletag接口与传统标签接口最大的区别在于,simpletag接口只定义了一个用于处理标签逻辑的dotag方法,该方法在web容器执行自定义标签时调用,并且只被调用一次。那些使用传统标签接口所完成的功能,例如是否执行标签体、迭代标签体、对标签体内容进行修改等功能都可以在dotag方法中完成。
在jsp api中也提供了simpletag接口的实现类simpletagsupport,我们在编写简单标签时,可以继承和扩展simpletagsupport类,这相比实现simpletag接口将简化开发工作。
传统标签接口中的各个方法可以返回的返回值说明
下图列举了tag接口、iterationtag接口和bodytag接口中的主要方法及它们分别可以返回的返回值的说明。
开发传统标签实现页面逻辑
开发人员在编写jsp页面时,经常还需要在页面中引入一些逻辑,例如:
控制jsp页面某一部分内容是否执行。 控制整个jsp页面是否执行。 控制jsp页面内容重复执行。 修改jsp页面内容输出。自定义标签除了可以移除jsp页面java代码外,它也可以实现以上功能。
控制jsp页面某一部分内容是否执行
编写一个类实现tag接口,控制dostarttag()方法的返回值,如果这个方法返回eval_body_include,则执行标签体,如果返回skip_body,则不执行标签体。
sun公司针对tag接口提供了一个默认的实现类tagsupport,tagsupport类中实现了tag接口的所有方法,因此我们可以编写一个类继承tagsupport类,然后再重写dostarttag方法。
示例代码如下:
tagdemo1.java:
public class tagdemo1 extends tagsupport { // 控制dostarttag()方法的返回值,即可控制标签体是否输出 @override public int dostarttag() throws jspexception { return tag.skip_body; } }
在web-inf目录下的itcast.tld文件中添加对该标签处理类的描述,如下:
demo1 cn.itcast.web.tag.tagdemo1 jsp
在jsp页面中导入并使用自定义标签,如下:
<%@ page language="java" contenttype="text/html; charset=utf-8" pageencoding="utf-8"%> <%@ taglib uri="http://www.itcast.cn" prefix="itcast" %>
运行效果如下:
控制整个jsp页面是否执行
编写一个类实现tag接口,控制doendtag()方法的返回值,如果这个方法返回eval_page,则执行标签余下的jsp页面,如果返回skip_page,则不执行余下的jsp。
示例代码如下:
tagdemo2.java:
public class tagdemo2 extends tagsupport { @override public int doendtag() throws jspexception { // return tag.skip_page; return tag.eval_page; } }
在web-inf目录下的itcast.tld文件中添加对该标签处理类的描述,如下:
demo2 cn.itcast.web.tag.tagdemo2 empty
在jsp页面中导入并使用自定义标签,如下:
<%@ page language="java" contenttype="text/html; charset=utf-8" pageencoding="utf-8"%> <%@ taglib uri="http://www.itcast.cn" prefix="itcast" %> aaaaaaaaaaaaa
运行效果如下:
控制jsp页面内容重复执行
编写一个类实现iterationtag接口,控制doafterbody()方法的返回值,如果这个方法返回eval_body_again, 则web服务器又执行一次标签体,依次类推,一直执行到doafterbody方法返回skip_body,则标签体才不会重复执行。
doafterbody()方法的执行时机是标签体执行之后以及结束标签执行之前。如果这个方法返回的是eval_body_again,服务器只要接收到这个常量,它这时又会把标签体再执行一次,如果把标签体执行完之后,又会调用doafterbody()方法,…依次类推,一直执行到doafterbody()方法返回skip_body,这时不会再执行标签体,就会执行标签体下面的结束标签。
示例代码如下:
tagdemo3.java:
// 控制标签体执行5次 public class tagdemo3 extends tagsupport { int x = 5; @override public int doafterbody() throws jspexception { x--; if(x>0) { return iterationtag.eval_body_again; } else { return iterationtag.skip_body; } } @override public int dostarttag() throws jspexception { // todo auto-generated method stub return tag.eval_body_include; } }
在web-inf目录下的itcast.tld文件中添加对该标签处理类的描述,如下:
demo3 cn.itcast.web.tag.tagdemo3 jsp
在jsp页面中导入并使用自定义标签,如下:
<%@ page language="java" contenttype="text/html; charset=utf-8" pageencoding="utf-8"%> <%@ taglib uri="http://www.itcast.cn" prefix="itcast" %>
运行效果如下:
修改jsp页面内容输出
编写一个类实现bodytag接口,控制dostarttag()方法返回eval_body_buffered,则web服务器会创建bodycontent对象捕获标签体,然后在doendtag()方法体内,得到代表标签体的bodycontent对象,从而就可以对标签体进行修改操作。
更详细的说法:如果编写的java类实现了bodytag接口,那这时可以控制开始标签对应的方法dostarttag()返回eval_body_buffered,只要返回eval_body_buffered,服务器拿到标签体之后,它会把标签体作为一个对象通过setbodycontent()方法传递给标签处理器类,接下来可以在结束标签对应的方法doendtag()方法里面拿到标签体,从而可以对标签体修改后输出。
sun公司针对bodytag接口提供了一个默认的实现类bodytagsupport,bodytagsupport类中实现了bodytag接口的所有方法,因此我们可以编写一个类继承bodytagsupport类,然后再根据需要重写dostarttag方法和doendtag()方法。
示例代码如下:
tagdemo4.java:
// 修改标签体(把标签体改为大写) public class tagdemo4 extends bodytagsupport { @override public int dostarttag() throws jspexception { return bodytag.eval_body_buffered; } @override public int doendtag() throws jspexception { bodycontent bc = this.getbodycontent(); // 得到标签体 string content = bc.getstring(); content = content.touppercase(); try { this.pagecontext.getout().write(content); } catch (ioexception e) { throw new runtimeexception(e); } // 只是修改标签体,余下的jsp还是要继续执行 return tag.eval_page; } }
在web-inf目录下的itcast.tld文件中添加对该标签处理类的描述,如下:
demo4 cn.itcast.web.tag.tagdemo4 jsp
在jsp页面中导入并使用自定义标签,如下:
<%@ page language="java" contenttype="text/html; charset=utf-8" pageencoding="utf-8"%> <%@ taglib uri="http://www.itcast.cn" prefix="itcast" %>
运行效果如下:
jsp传统标签开发总结
在现在的jsp标签开发中,很少直接使用传统标签来开发了,目前用得较多的都是简单标签,所以jsp的传统标签开发了解一下即可,下一篇重点介绍jsp简单标签的开发。