




已阅读5页,还剩92页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
JSP自定义标签的开发与应用在JSTL提供了四个标签库(核心标签库、国际化标签库、数据库标签库和XML标签库),涉及到了几十个标签。虽然这些标签可以完成比较复杂的工作,但它们仍然无法满足程序中的特殊需求。因此,就需要用户根据自己的需要来定制JSP标签,这种由用户自己实现的JSP标签被称为自定义标签。1自定义标签基础自定义标签和JSTL中的标签从技术上看没有任何区别,可以将这些标签统称为JSP标签。JSP标签在JSP页面中通过XML语法格式被调用,当JSP引擎将JSP页面翻译成SERVLET时,就将这些调用转换成执行相应的JAVA代码。也就是说,JSP标签实际上就是调用了某些JAVA代码,只是在JSP页面中以另外一种形式(XML语法格式)表现出来。11编写输出随机数的标签开始自定义标签的学习之前,在这一节先来实现一个简单的自定义标签,以使读者做一下热身,同时读者通过本节的例子可以对自定义标签的实现方法和过程有一个感性的认识。【实例11】实现输出随机数的标签1实例说明在本例实现的自定义标签(RANDOM标签)的功能是输出一个指定范围的随机整数。RANDOM标签有如下几个特征没有标签体。有两个属性MIN和MAX。其中MIN属性表示生成随机数的最小值,MAX属性表示生成随机数的最大值。MIN属性的默认值是0,MAX属性的默认值是INTEGERMAX_VALUE。生成随机数的范围是MIN其中“CT”是调用标签时的前缀,通过TAGLIB指定的PREFIX属性指定。上面的代码的功能是输出一个在1(包括)和100(不包括)之间的随机数。2编写标签类标签类是自定义标签的核心部分。实现标签类的方法有很多,但最简单的方法是编写一个从JAVAXSERVLETJSPTAGEXTTAGSUPPORT类继承的JAVA类,并在该类中覆盖TAGSUPPORT类的DOSTARTTAG方法。为了读取标签中的属性值,还需要在标签类中为每一个标签属性提供一个相应数据类型的标签类属性以及该属性的SETTER方法(不需要GETTER方法)。生成随机数的代码需要放在标签类的DOSTARTTAG方法中。该标签类的实现代码如下PACKAGECHAPTER1IMPORTJAVAIOIOEXCEPTIONIMPORTJAVAUTILRANDOMIMPORTJAVAXSERVLETJSPJSPEXCEPTIONIMPORTJAVAXSERVLETJSPTAGEXTTAGSUPPORTPUBLICCLASSRANDOMTAGEXTENDSTAGSUPPORT/封装RANDOM标签的两个属性的JAVABEAN属性PRIVATEINTMIN0PRIVATEINTMAXINTEGERMAX_VALUE/MIN属性的SETTER方法PUBLICVOIDSETMININTMINTHISMINMIN/MAX属性的SETTER方法PUBLICVOIDSETMAXINTMAXTHISMAXMAX/覆盖TAGSUPPORT类的DOSTARTTAG方法/当遇到标签(也就是)的开始标记时调用该方法OVERRIDEPUBLICINTDOSTARTTAGTHROWSJSPEXCEPTIONTRYRANDOMRANDOMNEWRANDOM/生成一个在MIN和MAX之间的随机数INTRESULTMINRANDOMNEXTINTMAXMIN/将生成的随机数输出到客户端PAGECONTEXTGETOUTWRITESTRINGVALUEOFRESULTCATCHIOEXCEPTIONE/TAGSUPPORT类的DOSTARTTAG方法默认返回SKIP_BODY,表示忽略自定义标签体RETURNSUPERDOSTARTTAG在RANDOMTAG类的DOSTARTTAG方法中使用了一个PAGECONTEXT变量来获得JSPWRITER对象(JSP的OUT内置对象)。PAGECONTEXT变量是在TAGSUPPORT类中定义的一个类变量,该变量通过TAGSUPPORT类中的SETPAGECONTEXT方法进行赋值。实际上,SETPAGECONTEXT方法是在TAG接口中定义的,而TAGSUPPORT实现了TAG接口的SETPAGECONTEXT方法。SERVLET容器在调用DOSTARTTAG方法之前,会先调用TAG接口的SETPAGECONTEXT方法来初始化PAGECONTEXT变量。TAG接口将在113节介绍,在这里只要知道所有的标签类都必须实现TAG接口。为了简化标签类的实现,JSPAPI提供了一个TAGSUPPORT类,有了TAGSUPPORT类,用户在编写标签类时就不需要实现TAG接口的所有方法了。3编写标签库描述符文件(TLD文件)在JSTL中有若干TLD文件(详见图91),其中TLD是TAGLIBRARYDESCRIPTOR(标签库描述符)的缩写。要想使一个自定义标签正常工作,必须在TLD文件中对该标签进行配置。在TLD文件中主要配置如下两部分内容标签库的配置信息、标签库中具体标签的配置信息标签库的配置信息主要包括如下的内容标签库的版本使用标签设置。正常使用标签库中的标签所需要的最低JSP版本使用标签设置。标签库的默认前缀使用标签设置。标签库的URI使用标签设置。标签库的描述信息使用标签设置。标签的配置信息主要包括如下的内容标签名使用标签设置。标签对应的JAVA类使用标签设置。标签体的类型使用标签设置。标签的描述信息使用标签设置。标签属性的信息每一个标签属性对应一个标签。在标签中可以指定标签名(使用标签设置)、该属性是否必须指定(使用标签设置)、该属性是否支持动态属性值(使用标签指定)等配置信息。在WEBINF目录中建立一个JSPTAGLIBTLD文件,并在该文件中输入如下的内容自定义标签库11CTHTTP/NOKIAGUYBLOGJAVANET产生一个指定范围的随机数RANDOMCHAPTER1RANDOMTAGEMPTYMINFALSEFALSEMAXFALSEFALSE上面的配置代码分为三部分标签库描述符文件头、标签库配置信息和RANDOM标签的配置信息。其中描述库文件头的内容并不需要读者去记忆,读者只需要将JSTL中的任何一个TLD文件打开,将其中的标签库描述文件头部分复制过来即可。如果在标签库描述符文件中包含中文,需要将ENCODING属性改成“UTF8”或“GBK”。标签库的URI被元素指定为“HTTP/NOKIAGUYBLOGJAVANET”,该标签值就是TAGLIB指令的URI属性值。元素指定了标签库的默认前缀。要注意的是,该默认前缀并不等于TAGLIB指令的PREFIX属性值,也就是说,TAGLIB指令的PREFIX属性值和元素的值毫无关系。元素值实际上只是个推荐的标签库前缀,如国际化标签库的描述符文件(FMTTLD)中的元素值是“FMT”。在使用TAGLIB指令引用某个标签库时,应尽量使用元素推荐的标签库前缀,当然,也可以设置其他的前缀名。RANDOM标签的标签体类型为“EMPTY”(元素的值),表示该标签不支持标签体。关于元素支持的其他值,将在后面的部分详细介绍。RANDOM标签的MIN属性和MAX属性都被设置可选的属性,并且都不支持动态属性值。因此,在JSP页面中设置RANDOM标签的这两个属性时只能直接为它们赋值。4测试RANDOM标签在CHAPTER1目录建立一个RANDOMJSP文件(在本章的所有JSP文件都放在该目录下),并输入如下的内容在浏览器地址栏中输入如下的URLHTTP/LOCALHOST8080/DEMO/CHAPTER1/RANDOMJSP浏览器显示的输出结果如图11所示。图11使用RANDOM标签产生1个10至200之间的随机数5程序总结在部署和安装自定义标签时,TLD文件应放在WEBINF目录或其子目录中(包括CLASSES和LIB目录)。根据本例实现的RANDOM标签,可以将开发自定义标签的基本步骤总结如下实现一个标签类。该标签类可以实现TAG接口、继承TAGSUPPORT类或实现其他的接口(这些接口将在后面的部分详细介绍)。在标签库描述符文件(TLD文件)中配置自定义标签。部署和安装自定义标签。主要是将CLASS文件放在WEBINFCLASSES目录中,并且将TLD文件放在WEBINF目录或其子目录中。112自定义标签能做什么自定义标签除了可以读取标签的属性值外,还可以完成如下的工作单次执行标签体中的内容、重复执行标签体中的内容。修改标签体中的内容。忽略JSP页面中位于自定义标签后面的内容。在上一节介绍了TAG接口中的DOSTARTTAG方法,该方法在WEB容器执行到自定义标签的开始标记时被调用。除了这个方法,在TAG接口中还有DOENDTAG方法,该方法在WEB容器中执行到自定义标签的结束标记时被调用。DOSTARTTAG方法可以通过返回如下两个值来控制WEB容器是否执行自定义标签的标签体EVAL_BODY_INCLUDE执行自定义标签的标签体。SKIP_BODY忽略(不执行)自定义标签的标签体。DOENDTAG方法可以通过返回如下两个值来控制WEB容器是否忽略JSP页面中位于自定义标签后面的内容EVAL_PAGE继续执行自定义标签后面的内容。SKIP_PAGE忽略自定义标签后面的内容。其中EVAL_BODY_INCLUDE、SKIP_BODY、EVAL_PAGE和SKIP_PAGE是在TAG接口中定义的整型常量,所有实现TAG接口的类都可以直接使用这些常量。除此之外,实现ITERATIONTAG接口的标签类还可以重复执行标签体。ITERATIONTAG是TAG接口的子接口。在ITERATIONTAG接口中有一个DOAFTERBODY方法,该方法可以通过返回如下两个值来决定是否重复执行自定义标签体的内容EVAL_BODY_AGAIN重复执行标签体的内容。SKIP_BODY不再执行标签体的内容。其中EVAL_BODY_AGAIN是在ITERATIONTAG接口中定义的整型常量。如果DOAFTERBODY方法返回SKIP_BODY,WEB容器会继续执行自定义标签的结束标记,同时会调用DOENDTAG方法。从上面的描述可以将WEB容器执行自定义标签的过程总结如下1WEB容器首先会执行自定义标签的开始标记,同时会调用标签类的DOSTARTTAG方法。2如果DOSTARTTAG方法返回EVAL_BODY_INCLUDE,WEB容器在执行完标签体的内容后,会调用标签类的DOAFTERBODY方法;如果DOSTARTTAG方法返回SKIP_BODY,DOAFTERBODY方法不会被调用,WEB容器会直接调用标签类的DOENDTAG方法。3如果DOAFTERBODY方法被调用,并且该方法返回EVAL_BODY_AGAIN,WEB容器会再次执行标签体的内容;如果DOAFTERBODY方法返回SKIP_BODY,WEB容器会调用标签类的DOENDTAG方法。4如果DOENDTAG方法返回EVAL_PAGE,WEB容器会执行自定义标签后面的内容;如果DOENDTAG方法返回SKIP_PAGE,WEB容器会忽略自定义标签后面的内容。113自定义标签API自定义标签API中除了前面介绍的TAG接口和ITERATIONTAG接口外,还有另外三个核心接口JSPTAG、BODYTAG和SIMPLETAG。为了简化自定义标签的编程工作,在自定义标签API中提供了TAGSUPPORT类、SIMPLETAGSUPPORT类和BODYTAGSUPPORT类。其中TAGSUPPORT类实现了ITERATIONTAG接口,SIMPLETAGSUPPORT类实现了SIMPLETAG接口,BODYTAGSUPPORT类是TAGSUPPORT的子类,并实现了BODYTAG接口。上述五个接口和三个类的关系如图12所示。图12自定义标签API的核心接口和类的关系图上述的接口和类都在JAVAXSERVLETJSPTAGEXT包中,读者可以从如下的网址来查询这些接口和类的详细介绍HTTP/JAVASUNCOM/JAVAEE/5/DOCS/API/JAVAX/SERVLET/JSP/TAGEXT/PACKAGESUMMARYHTML访问上面的网址将得到如图13所示的页面。图13自定义标签API的官方文档上述五个接口的功能和作用如下1JSPTAG接口JSPTAG接口是所有自定义标签的父接口。它没有任何属性和方法。TAG接口和SIMPLETAG接口是JSPTAG的两个直接子接口。其中JSPTAG和SIMPLETAG是JSP20新增的接口。在JSP20之前的版本的所有自定义标签的父接口是TAG。因此,可以将所有实现TAG接口的自定义标签称为传统标签,把所有实现SIMPLETAG接口的标签称为简单标签。在本章主要介绍传统标签,简单标签将在下一章详细介绍。2TAG接口TAG接口是所有传统标签的父接口。该接口有两个核心方法(DOSTARTTAG和DOENDTAG)以及四个常量(EVAL_BODY_INCLUDE、SKIP_BODY、EVAL_PAGE和SKIP_PAGE)。其中DOSTARTTAG方法可以返回EVAL_BODY_INCLUDE和SKIP_BODY,用于控制WEB容器是否执行标签体的内容;DOENDTAG方法可以返回EVAL_PAGE和SKIP_PAGE,用于控制WEB容器是否执行自定义标签后面的内容。3ITERATIONTAG接口ITERATIONTAG接口继承了TAG接口。ITERATIONTAG接口可用于实现需要循环执行标签体内容的自定义标签。在ITERATIONTAG接口中只有一个DOAFTERBODY方法和一个EVAL_BODY_AGAIN常量。DOAFTERBODY方法通过返回EVAL_BODY_AGAIN常量或TAG接口中的SKIP_BODY常量来控制WEB容器是否重复执行标签体中的内容。DOSTARTTAG方法、DOAFTERBODY方法和DOENDTAG方法的调用关系详见112节中的介绍。并不是每一个自定义标签都需要循环执行标签体的内容,或是控制自定义标签后面的内容是否被执行。因此,JSPAPI中提供了一个实现ITERATIONTAG接口的TAGSUPPORT类。在TAGSUPPORT类中对TAG接口和ITERATIONTAG接口中定义的方法都提供了默认的实现。如DOSTARTTAG方法、DOENDTAG方法和DOAFTERBODY方法都提供了默认的返回值,代码如下PUBLICCLASSTAGSUPPORTIMPLEMENTSITERATIONTAG,SERIALIZABLEPUBLICTAGSUPPORTPUBLICINTDOSTARTTAGTHROWSJSPEXCEPTIONRETURNSKIP_BODYPUBLICINTDOENDTAGTHROWSJSPEXCEPTIONRETURNEVAL_PAGEPUBLICINTDOAFTERBODYTHROWSJSPEXCEPTIONRETURNSKIP_BODY/此处省略了TAGSUPPORT类中的其他方法和属性标签类通过继承TAGSUPPORT类,就不需要实现TAG接口和ITERATION接口中的每一个方法了,这样将大大简化自定义标签的开发工作。4BODYTAG接口BODYTAG接口继承了ITERATIONTAG接口。BODYTAG接口不仅拥有ITERATIONTAG接口的所有功能,而且还可以初始化和修改标签体的内容。在BODYTAG接口中定义了两个方法(DOINITBODY和SETBODYCONTENT)和两个常量(EVAL_BODY_BUFFERED和EVAL_BODY_TAG),这两个常量的含义相同。其中EVAL_BODY_TAG常量是在JSP12中的遗留产物,在JSP的后续版本中可能不支持该常量,因此,建议使用EVAL_BODY_BUFFERE常量。如果DOSTARTTAG方法返回EVAL_BODY_BUFFERE,WEB容器就会将标签体的执行结果保存在BODYCONTENT对象中,然后WEB容器在处理标签时会调用标签类的SETBODYCONTENT方法将BODYCONTENT对象传入标签类的对象实例,接下来就可以在标签类的对象实例中处理标签体的执行结果了。由于BODYTAG接口及其父接口中定义了很多方法,为了在实现BODYTAG接口的类中不用再实现所有的方法,JSPAPI提供了一个BODYTAGSUPPORT类,该类是TAGSUPPORT类的子类,并且实现了BODYTAG接口。在BODYTAGSUPPORT类中改变了DOSTARTTAG方法的默认返回值,并且覆盖了其他的核心方法,代码如下PUBLICCLASSBODYTAGSUPPORTEXTENDSTAGSUPPORTIMPLEMENTSBODYTAGPROTECTEDBODYCONTENTBODYCONTENTPUBLICBODYTAGSUPPORTSUPERPUBLICVOIDSETBODYCONTENTBODYCONTENTBTHISBODYCONTENTBPUBLICBODYCONTENTGETBODYCONTENTRETURNBODYCONTENT/改变了DOSTARTTAG方法的默认返回值PUBLICINTDOSTARTTAGTHROWSJSPEXCEPTIONRETURNEVAL_BODY_BUFFEREDPUBLICINTDOENDTAGTHROWSJSPEXCEPTIONRETURNSUPERDOENDTAGPUBLICVOIDDOINITBODYTHROWSJSPEXCEPTIONPUBLICINTDOAFTERBODYTHROWSJSPEXCEPTIONRETURNSKIP_BODY/此处省略了BODYTAGSUPPORT类的其他方法和属性从前面的内容可知,自定义标签API涉及到了三个方法(DOSTARTTAG、DOAFTERBODY和DOENDTAG)以及这三个方法可能返回的六个常量(EVAL_BODY_INCLUDE、EVAL_BODY_BUFFERE、SKIP_BODY、EVAL_BODY_AGAIN、EVAL_PAGE和SKIP_PAGE)。表11给出了这三个方法的返回值和这六个常量的关系。表11DOSTARTTAG、DOAFTERBODY和DOENDTAG方法的返回值及其作用方法名返回值DOSTARTTAGDOAFTERBODYDOENDTAGEVAL_BODY_INCLUDE执行标签体中的内容(直接将标签体的执行结果输出到OUT对象的缓冲区中)EVAL_BODY_BUFFERE执行标签体中的内容,并将标签体的执行结果保存在BODYCONTENT对象中,以备后续处理和加工SKIP_BODY忽略标签体的内容不再重复执行标签体的内容EVAL_BODY_AGAIN重复执行标签体的内容EVAL_PAGE继续执行自定义标签后面的内容SKIP_PAGE忽略自定义标签后面的内容5SIMPLETAG接口SIMPLETAG是JSP20新增的一个接口。该接口只有一个DOTAG方法,这个方法只在WEB容器执行自定义标签时调用一次。所有的处理逻辑(包括是否执行标签体、重复执行标签体等)都要写在DOTAG方法中,因此,SIMPLETAG接口的功能相当于BODYTAG接口,只是SIMPLETAG接口要比BODYTAG接口更容易使用。为了更进一步简化自定义标签的开发工作,JSPAPI提供了一个实现SIMPLETAG接口的SIMPLETAGSUPPORT类,建议读者在编写简单标签时,标签类从SIMPLETAGSUPPORT类继承。12实现基本的自定义标签一个自定义标签最基本的功能就是控制是否执行标签体的内容,以及控制是否执行自定义标签后面的内容。通过实现TAG接口的DOSTARTTAG方法和DOENDTAG方法可以很容易地完成这两个功能。在TAG接口中还有定义了一些其他的方法(SETPAGECONTEXT、SETPARENT等),通过实现这些方法,可以编写更高级的自定义标签。121TAG接口JAVAXSERVLETJSPTAGEXTTAG接口是所有传统标签的父接口,该接口定义了WEB容器处理自定义标签的基本方法。这些方法主要包括WEB容器执行到标签的开始标记时发生的标签开始事件(调用TAG接口的DOSTARTTAG方法)和执行到标签的结束标记时发生的标签结束事件(调用TAG接口的DOENDTAG方法)。在TAG接口中定义了四个常量,并由DOSTARTTAG方法和DOENDTAG方法返回相应的常量以通知WEB容器如何执行自定义标签。TAG接口中定义的常量和方法如下所示1TAG接口中定义的常量在TAG接口中定义了如下四个整型常量EVAL_BODY_INCLUDESKIP_BODYEVAL_PAGESKIP_PAGE其中EVAL_BODY_INCLUDE和SKIP_BODY将作为DOSTARTTAG方法的返回值返回给WEB容器,WEB容器根据DOSTARTTAG方法的返回值来决定是否执行自定义标签的标签体。EVAL_PAGE和SKIP_PAGE将作为DOENDTAG方法的返回值返回给WEB容器,WEB容器根据DOENDTAG方法的返回值决定是否执行的自定义标签后面的内容。2SETPAGECONTEXT方法在WEB容器创建标签类的对象实例后,会首先调用标签类的SETPAGECONTEXT方法将PAGECONTEXT对象实例传入标签类的对象实例,然后会调用标签类中的其他方法,这样在标签类中的其他方法就可以使用PAGECONTEXT对象了。SETPAGECONTEXT方法的定义如下PUBLICVOIDSETPAGECONTEXTPAGECONTEXTPAGECONTEXT3SETPARENT方法和GETPARENT方法WEB容器在调用标签类的SETPAGECONTEXT方法后,会调用标签类的SETPARENT方法,该方法用来设置当前标签的父标签的对象实例。通过GETPARENT标签可以获得当前标签的父标签的对象实例。如果当前标签没有父标签,SETPARENT方法的参数值为NULL。SETPARENT方法和GETPARENT方法的定义如下PUBLICVOIDSETPARENTTAGTPUBLICTAGGETPARENT4DOSTARTTAG方法WEB容器在依次调用SETPAGECONTEXT方法、SETPARENT方法以及设置当前标签属性的SETTER方法后,就会调用标签类的DOSTARTTAG方法。当WEB容器调用DOSTARTTAG方法时,就意味着WEB容器已经开始处理当前标签的开始标记。如果DOSTARTTAG方法返回EVAL_BODY_INCLUDE,WEB容器会在执行完标签体后调用标签类的DOENDTAG方法;如果DOENDTAG方法返回SKIP_BODY,WEB容器并不会执行标签体,而是直接调用标签类的DOENDTAG方法。DOSTARTTAG方法的定义如下INTDOSTARTTAGTHROWSJSPEXCEPTION5DOENDTAG方法WEB容器在遇到标签的结束标记时,会调用标签类的DOENDTAG方法。如果DOENDTAG方法返回EVAL_PAGE,WEB容器会继续执行结束标记后面的内容;如果DOENDTAG方法返回SKIP_PAGE,结束标签后面的内容都不会被执行,也就是说,WEB容器在执行当前JSP页面时,执行到标签的结束标记处就会终止执行当前的JSP页面。DOENDTAG方法的定义如下INTDOENDTAGTHROWSJSPEXCEPTION6RELEASE方法JSP规范要求WEB容器必须在垃圾回收器回收标签类的对象实例时调用RELEASE方法,以便自定义标签可以利用该方法释放所占用的相关资源。但JSP规范并没有规定WEB容器调用RELEASE方法的具体时间,因此,RELEASE方法的调用时间由具体的WEB容器厂商决定。RELEASE方法的定义如下PUBLICVOIDRELEASE122标签类中方法的调用顺序在本节给出一个例子来测试标签类中方法的调用顺序。本示例测试了WEB容器在调用自定义标签时调用标签类中的SETPAGECONTEXT方法、SETPARENT方法、设置标签属性的SETTER方法、DOSTARTTAG方法、DOENDTAG方法和RELEASE方法的顺序。【实例12】测试标签类中方法的调用顺序1编写INVOKEORDERTAG类INVOKEORDERTAG是一个标签类,在该类中覆盖了TAGSUPPORT类中的相关方法,并在这些方法的调用轨迹输出到控制台。INVOKEORDERTAG类的实现代码如下PACKAGECHAPTER1IMPORTJAVAXSERVLETJSPJSPEXCEPTIONIMPORTJAVAXSERVLETJSPPAGECONTEXTIMPORTJAVAXSERVLETJSPTAGEXTTAGIMPORTJAVAXSERVLETJSPTAGEXTTAGSUPPORTPUBLICCLASSINVOKEORDERTAGEXTENDSTAGSUPPORT/定义了两个属性,用于设置和读取标签的相应属性值PRIVATESTRINGATTR1PRIVATESTRINGATTR2/设置ATTR1属性的值PUBLICVOIDSETATTR1STRINGATTR1SYSTEMOUTPRINTLN“SETATTR1“THISATTR1ATTR1/设置ATTR2属性的值PUBLICVOIDSETATTR2STRINGATTR2SYSTEMOUTPRINTLN“SETATTR2“THISATTR2ATTR2OVERRIDEPUBLICVOIDSETPAGECONTEXTPAGECONTEXTPAGECONTEXTSYSTEMOUTPRINTLN“PAGECONTEXT“SUPERSETPAGECONTEXTPAGECONTEXTOVERRIDEPUBLICVOIDSETPARENTTAGTSYSTEMOUTPRINTLN“SETPARENT“SYSTEMOUTPRINT“父标签“SYSTEMOUTPRINTLNTSUPERSETPARENTTPUBLICINTDOSTARTTAGTHROWSJSPEXCEPTIONSYSTEMOUTPRINTLN“DOSTARTTAG“RETURNSUPERDOSTARTTAGPUBLICINTDOENDTAGTHROWSJSPEXCEPTIONSYSTEMOUTPRINTLN“DOENDTAG“RETURNSUPERDOENDTAGOVERRIDEPUBLICVOIDRELEASESYSTEMOUTPRINTLN“RELEASE“SUPERRELEASE2安装INVOKEORDER标签在JSPTAGLIBTLD文件中添加如下的内容来安装INVOKEORDER标签测试标签类中方法的调用顺序INVOKEORDERCHAPTER1INVOKEORDERTAGEMPTYATTR1FALSEFALSEATTR2FALSEFALSE3编写INVOKEORDERJSP页面INVOKEORDERJSP页面用来调用INVOKEORDER标签。当访问INVOKEORDERJSP页面后,就会在TOMCAT控制台输出相应的方法调用轨迹。INVOKEORDERJSP页面的代码如下4测试INVOKEORDER标签在浏览器地址栏中输入如下的URLHTTP/LOCALHOST8080/DEMO/CHAPTER1/INVOKEORDERJSPTOMCAT的控制台将输出如下的信息PAGECONTEXTSETPARENT父标签ORGAPACHETAGLIBSSTANDARDTAGRTCOREIFTAG8C436BSETATTR2SETATTR1DOSTARTTAGDOENDTAG从上面的输出信息可知,WEB容器会根据使用标签时属性的位置来调用设置属性值的SETTER方法(在INVOKEORDERJSP页面中调用INVOKEORDER标签时,ATTR2属性在ATTR1属性前面)。123控制是否执行标签体在本节的例子通过DOSTARTTAG方法的返回值来控制WEB容器是否执行标签体的内容。【实例13】控制是否执行标签体1实例说明本示例根据是否存在BODY请求参数来决定DOSTARTTAG方法的返回值。如果存在BODY请求参数,DOSTARTTAG方法返回EVAL_BODY_INCLUDE,否则返回SKIP_BODY。2编写DISPLAYBODYTAG类DISPLAYBODYTAG是一个标签类。该类负责判断是否存在BODY请求参数,并根据判断结果决定DOSTARTTAG方法的返回值。DISPLAYBODYTAG类的实现代码如下PACKAGECHAPTER1IMPORTJAVAXSERVLETJSPJSPEXCEPTIONIMPORTJAVAXSERVLETJSPPAGECONTEXTIMPORTJAVAXSERVLETJSPTAGEXTTAGIMPORTJAVAXSERVLETJSPTAGEXTTAGSUPPORTPUBLICCLASSDISPLAYBODYTAGEXTENDSTAGSUPPORTPUBLICINTDOSTARTTAGTHROWSJSPEXCEPTION/获得BODY请求参数的值STRINGBODYPAGECONTEXTGETREQUESTGETPARAMETER“BODY“/存在BODY请求参数,返回EVAL_BODY_INCLUDEIFBODYNULLRETURNTHISEVAL_BODY_INCLUDE/不存在BODY请求参数,返回SKIP_BODYELSERETURNTHISSKIP_BODY3安装DISPLAYBODY标签在JSPTAGLIBTLD文件中添加如下的内容来安装DISPLAYBODY标签显示标签体的内容DISPLAYBODYCHAPTER1DISPLAYBODYTAGJSP在上面的配置代码中的元素的值是JSP,该值表示标签体的内容可以是任意JSP页面元素,JSP也是元素的默认值。4编写DISPLAYBODYJSP页面DISPLAYBODYJSP页面用来调用DISPLAYBODY标签,在DISPLAYBODY的标签体中有一行字符串,如果访问DISPLAYBODYJSP页面时包含BODY请求参数,则DISPLAYBODY标签会显示这行字符串。DISPLAYBODYJSP页面的代码如下DISPLAYBODY标签体的内容如果存在请求参数BODY,则输出标签体的内容5测试DISPLAYBODY标签在浏览器地址栏中输入如下的URLHTTP/LOCALHOST8080/DEMO/CHAPTER1/DISPLAYBODYJSPBODY浏览器显示的信息如图14所示。图14访问DISPLAYBODYJSP页面时带BODY请求参数如果在访问DISPLAYBODYJSP页面时不带BODY请求参数,则在浏览器中输出的信息如图15所示。图15访问DISPLAYBODYJSP页面时不带BODY请求参数从图15所示的输出结果可以看出,当访问DISPLAYBODYJSP页面的URL不包含BODY请求时,标签体中的内容并没有输出。124控制是否执行标签后面的内容在本节的例子通过DOENDTAG方法的返回值来控制WEB容器是否执行标签后面的内容。【实例14】控制是否执行标签后面的内容1实例说明本示例根据访问JSP页面的客户端IP地址来决定是否执行LOCALPAGE标签后面的内容。如果IP地址为127001,则允许执行LOCALPAGE标签后面的内容,否则,WEB容器只执行到LOCALPAGE标签的结束标记为止。2编写LOCALPAGETAG标签LOCALPAGETAG是一个标签类,负责验证客户端的IP地址,并根据验证结果决定是否执行LOCALPAGE标签后面的内容。LOCALPAGETAG类的代码如下PACKAGECHAPTER1IMPORTJAVAXSERVLETJSPJSPEXCEPTIONIMPORTJAVAXSERVLETJSPPAGECONTEXTIMPORTJAVAXSERVLETJSPTAGEXTTAGIMPORTJAVAXSERVLETJSPTAGEXTTAGSUPPORTPUBLICCLASSLOCALPAGETAGEXTENDSTAGSUPPORTPUBLICINTDOENDTAGTHROWSJSPEXCEPTION/获得客户端的IP地址STRINGREMOTEADDRPAGECONTEXTGETREQUESTGETREMOTEADDR/如果客户端的IP地址是127001,则返回EVAL_PAGEIFREMOTEADDREQUALS“127001“RETURNTHISEVAL_PAGE/如果是其他的客户端IP地址,则返回SKIP_PAGEELSERETURNTHISSKIP_PAGE3安装LOCALPAGE标签在JSPTAGLIBTLD文件中添加如下的内容来安装LOCALPAGE标签只有使用本地的IP(127001)或主机名(LOCALHOST才能执行标签后面的内容LOCALPAGECHAPTER1LOCALPAGETAGEMPTY4编写LOCALPAGEJSP页面LOCALPAGEJSP页面负责调用LOCALPAGE标签。如果访问LOCALPAGEJSP页面的客户端IP地址是127001,则WEB容器会继续执行LOCALPAGE标签后面的内容,否则,WEB容器将不会执行LOCALPAGE标签后面的内容。LOCALPAGEJSP页面的代码如下LOCALPAGE标签前的内容LOCALPAGE标签后的内容5使用本地主机名访问LOCALPAGEJSP页面在浏览器地址栏中输入如下的URLHTTP/LOCALHOST8080/DEMO/CHAPTER1/LOCALPAGEJSP浏览器显示的输出结果如图16所示。图16执行LOCALPAGE标签后面的内容6使用远程IP访问LOCALPAGEJSP页面假设本地的IP地址为19216817127。在浏览器地址栏中输入如下的URLHTTP/192168171278080/DEMO/CHAPTER1/LOCALPAGEJSP浏览器显示的输出结果如图17所示。图17未执行LOCALPAGE标签后面的内容125限定自定义标签的父标签TAG接口的GETPARENT方法可以获得当前标签的父标签的对象实例。利用这个功能可以限定自定义标签的父标签,如限定某一个标签只能在标签的标签体中使用。【实例15】可以生成表格的自定义标签1实例说明在这个示例中将编写一个可以生成HTML表格的标签,该标签只能在标签的标签体中使用。用于根据标签的ITEMS属性指定的集合生成表格的行()。ITEMS属性指定的集合中的元素必须是JAVAUTILLIST类型。否则该标签将抛出异常。2编写TRTAG类TRTAG是一个标签类,负责根据标签的ITEMS属性指定的集合元素生成相应的。TRTAG类的代码如下PACKAGECHAPTER1IMPORTJAVAIOIOEXCEPTIONIMPORTORGAPACHETAGLIBSSTANDARDTAGRTCOREFOREACHTAGIMPORTJAVAXSERVLETJSPTAGEXTTAGIMPORTJAVAXSERVLETJSPJSPEXCEPTIONIMPORTJAVAXSERVLETJSPTAGEXTTAGSUPPORTPUBLICCLASSTRTAGEXTENDSTAGSUPPORTOVERRIDEPUBLICINTDOSTARTTAGTHROWSJSPEXCEPTION/返回TR标签的父标签的对象实例TAGTAGGETPARENT/如果TR标签的父标签的对象实例是FOREACHTAG,则继续执行下面的操作IFTAGINSTANCEOFFOREACHTAGFOREACHTAGFOREACHTAGFOREACHTAGTAG/获得FOREACH标签当前迭代的元素OBJECTCURRENTFOREACHTAGGETLOOPSTATUSGETCURRENT/如果当前迭代的元素为NULL,不处理该元素IFCURRENTNULLRETURNTHISSKIP_BODY/如果当前迭代的元素类型是JAVAUTILLIST,继续处理当前迭代的元素IFCURRENTINSTANCEOFJAVAUTILLISTJAVAUTILLISTROWJAVAUTILLISTCURRENT/开始生成STRINGTR“FOROBJECTCELLROWTR“CELL“TR“TRY/将生成的输出的客户端PAGECONTEXTGETOUTWRITETRCATCHIOEXCEPTIONE/如果当前迭代的元素类型不是JAVAUTILLIST,则抛出JSPEXCEPTION异常ELSETHROWNEWJSPEXCEPTION“当前元素必须是JAVAUTILLIST类型“/如果TR标签的父标签的对象实例不是FOREACHTAG,则抛出JSPEXCEPTION异常ELSETHROWNEWJSPEXCEPTION“CONTINUE标签必须在FOREACH标签体中使用“RETURNTHISSKIP_BODY3安装TR标签在JSPTAGLIBTLD文件中添加如下的内容来安装TR标签生成表格中的TR标签TRCHAPTER1TRTAGEMPTY4编写TRJSP页面TRJSP页面使用标签和标签生成一个表格。其中标签对一个JAVAUTILLIST对象进行迭代,该对象中的元素也是JAVAUTILLIST对象,每当标签迭代到一个元素时,就会调用标签来生成表格行()。TRJSP页面的代码如下ROWSNEWJAVAUTILARRAYLISTJAVAUTILLISTROW1NEWJAVAUTILARRAYLISTJAVAUTILLISTROW2NEWJAVAUTILARRAYLISTJAVAUTILLISTROW3NEWJAVAUTILARRAYLISTROW1ADD“足球“ROW1ADD30ROW1ADD12ROW2ADD“跑步机“ROW2ADD321ROW2ADD25ROW3ADD“自行车“ROW3ADD221ROW3ADD6ROWSADDROW1ROWSADDROW2ROWSADDROW3REQUESTSETATTRIBUTE“ROWS“,ROWS商品名称单价数量5测试TR标签在浏览器地址栏中输入如下的URLHTTP/LOCALHOST8080/DEMO/CHAPTER1/TRJSP浏览器的输出信息如图18所示。图18使用标签生成表格如果在标签的父标签不是,在调用标签时就会抛出如图19所示的异常信息。图19标签的父标签不是时抛出的异常信息13自定义标签的属性自定义标签可以定义一个或多个属性。在前面的例子已经多次使用到自定义标签的属性。在自定义标签中使用属性的一般形式如下131定义标签属性可按如下两步向自定义标签添加属性1在标签类中编写和标签属性对应的SETTER方法。2在TLD文件中使用元素配置每一个标签属性。假设标签MYTAG有两个属性URI和NAME。首先需要在MYTAG标签所对应的标签类(MYTAG类)中编写两个SETTER方法(SETURI和SETNAME),代码如下PUBLICCLASSMYTAGEXTENDSTAGSUPPORTPRIVATESTRINGURIPRIVATESTRINGNAMEPUBLICVOIDSETURISTRINGURITHISURIURIPUBLICVOIDSETNAMESTRINGNAMETHISNAMENAME/此处省略了MYTAG类的其他属性和方法WEB容器在调用MYTAG标签时,如果发现MYTAG类中有SETURI方法和SETNAME方法,会自动将MYTAG标签的URI属性和NAME属性的值分别通过SETURI方法和SETNAME方法传入MYTAG类的对象实例,这些在MYTAG类中就可以直接使用URI属性和NAME属性的值了。如下面的调用MYTAG标签的代码将“/URITAG”和“TEST”分别作为MYTAG对象的URI属性和NAME属性值传入MYTAG对象。如果和某个标签属性对应的SETTER方法需要传递非字符串类型的参数值,如INT、DOUBLE、BOOLEAN等,WEB容器会调用相应类的VALUEOF方法进行类型转换。假设DOUBLETAG标签有一个VALUE属性(该属性的值是“1234”),与VALUE属性对应的SETTER方法的参数类型是DOUBLE。WEB容器在调用SETTER方法时,会使用DOUBLEVALUEOF“1234“方法将字符串“1234”转换成双精度浮点数1234。JAVA中的所有基本类型(BYTE、SHORT、INT、LONG、FLOAT、DOUBLE、BOOLEAN)都支持这种转换机制。除了在标签类中编写相应的SETTER方法外,还需要在TLD文件中使用元素来配置这些属性,配置代码如下带属性的标签MYTAGMYTAGEMPTYURIFALSEFALSENAMEFALSEFALSE上面代码中的黑体字部分配置了URI属性和NAME属性。元素的所有子元素的含义如表12所示。表12元素的所有子元素的含义元素名是否必须指定含义NAME是用于设置标签属性的名称。属性名称是大小写敏感的。REQUIRED否用于指定当前标签属性是否必须指定。默认值是FALSE。如果该元素的值为TRUE,表示在使用自定义标签时必须指定当前属性;如果该元素的值为FALSE,表示在使用自定义标签时可以不指定当前属性。RTEXPRVALUE否RTEXPRVALUE是RUNTIMEEXPRESSIONVALUE(运行时表达式值)的英文缩写,用于指定当前属性是否支持动态属性值。默认值是FALSE。如果该元素值设为TRUE,表示属性值可以是JSP表达式或EL,否则,属性值只能是字符串。TYPE否用于指定标签属性值对应的JAVA数据类型。DESCRIPTION否用于指定属性的描述信息。132编写数学运算标签在本节给出一个数学运算标签MATH标签)的例子。MATH标签可以调用JAVALANGMATH类中所有只含有一个DOUBLE类型参数的静态方法(如SIN、COS、TAN、SQRT等)。MATH标签有如下四个属性METHOD(必选)指定MATH类中的静态方法名。VALUE(必选)指定要调用的静态方法的参数值。该属性值必须可转换成DOUBLE数据类型。ANGLE(可选)如果调用的是三角函数,该属性指定VALUE属性的值是否表示角度。默认值是FALSE。如果该属性值为TRUE,表示VALUE属性的值是弧度。PATTERN(可选)指定格式化静态方法返回值的模式字符串。默认值是“000”。模式字符串的格式和DECIMALFORMAT类所使用的模式字符串格式相同,详见8212节的内容。【实例16】数学运算标签1编写MATHTAG类MATHTAG是一个标签类,负责读取MATH标签的属性值,并调用相应的静态
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 知识产权共有与品牌授权及市场推广合作协议
- 政认识民法典课件-2024-2025学年统编版道德与法治七年级下册
- 医学减肥健康宣教
- 《应对地震安全:教育课件》
- 服务基本礼仪培训
- 《IPv6解决方案》课件
- 《临床用药管理与策略》课件
- 信息机房安全培训课件
- 《临床护理操作规程》课件
- 《慢性心力衰竭治疗》课件
- 新技术、新工艺、对提高工程质量、缩短工期、降低造价的可行性
- 金属矿床地下开采复习题及答案
- GB 5009.34-2022食品安全国家标准食品中二氧化硫的测定
- 教学课件《断裂力学》
- 慢阻肺的管理课件
- 电工基本知识培训资料课件
- 北师大版《相遇问题》公开课课件
- 邻补角、对顶角、同位角、内错角、同旁内角经典习题-一对一专用
- HP系列培训手册
- 毕业论文-原油电脱水方法与机理的研究
- 陕西省2022年普通高中学业水平考试(真题)
评论
0/150
提交评论