JSP标记学习笔记浅析

开发 后端
JSP标记学习笔记是学习JSP标记的一个归纳总结,那么本文就将向你讲述在JSP标记学习过程中所要注意的问题。

1.概述

1)什么是JSP标记

顾名思义,JSP标记就是在JSP文件中使用的标记。它类似于html语法中的标记,像head、table。通过在JSP文件中引用它(就像使用html标记那样),可以更方便的实现对Java代码模块的重用。

2)为什么要使用JSP标记技术(与javabean相比)

好处

JSP标记可以处理JSP正文的内容,比如改变文本显示样式;而javabean不可以。

JSP标记接口简单,易于使用,也易于开发和维护。

坏处

JSP标记在进行设置时要比javabean复杂很多,体现在JSP标记库描述文件(*.tld)的配置上。

JSP标记实现的功能远不如javabean强大。

当前只要JSP1.1支持JSP标记,而JSP1.0和1.1都支持对Bean的使用。

2.JSP标记的开发简介。

JSP标记的开发需要编写2种独立的文件。一种是定义标记功能的java类文件,一种是将xml元素名称(标记)映射到标记实现的标记库描述符文件。

⑴编写JSP标记处理程序类文件

需要继承javax.servlet.jsp.tagext.TagSupport类;

简单示例:

  1. //文件名ExampleTag.java  
  2.  
  3. importjavax.servlet.jsp.*&#59;  
  4.  
  5. importjavax.servlet.jsp.tagext.*&#59;  
  6.  
  7. importjava.io.*&#59;  
  8.  
  9.  
  10.  
  11. publicclassExampleTagextendsTagSupport{  
  12.  
  13. //程序的执行起始点  
  14.  
  15. publicintdoStartTag(){  
  16.  
  17. try{  
  18.  
  19. JspWriterout=pageContext.getOut()&#59;  
  20.  
  21. out.print(“Customtagexample”)&#59;  
  22.  
  23. }catch(IOExceptionioe){  
  24.  
  25. System.out.println(“ErrorinExampleTag:“+ioe)&#59;  
  26.  
  27. }  
  28.  
  29. return(SKIP_BODY)&#59;//当标记包括的内容为空时返回SKIP_BODY,表示标记功能  
  30.  
  31. //已执行完成  
  32.  
  33. }  
  34.  

编译好的class文件将位于服务器的的特定位置。

⑵编写JSP标记库描述符文件

将标记名和其代表的功能实现联系在一起。

简单示例:

  1. ﹤!--文件名:csajsp-taglib.tld--﹥;  
  2.  
  3. ﹤?xmlversion=”1.0”encoding=”ISO-8859-1”?﹥;  
  4.  
  5. ﹤!DOCTYPEtaglib  
  6.  
  7. PUBLIC“-//SunMicrosystem,Inc.//DTDJSPTagLibrary1.1//EN”  
  8.  
  9. http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd﹥;  
  10.  
  11. //以上是标准的文件头  
  12.  
  13. //以下是标签库描述  
  14.  
  15. ﹤tlibversion﹥;1.0﹤/tlibversion﹥;//Tag库的版本  
  16.  
  17. ﹤jspversion﹥;1.1﹤/jspversion﹥;//JSP库的版本  
  18.  
  19. ﹤shortname﹥;csajsp﹤/shortname﹥;//自定义标记前缀名  
  20.  
  21. ﹤uri﹥;﹤/uri﹥;//标记描述符文件的uri,可以是空  
  22.  
  23. ﹤info﹥;Mycustomtag!﹤/info﹥;//标记库的描述信息  
  24.  
  25. //以下定义新标记  
  26.  
  27. ﹤tag﹥;  
  28.  
  29. ﹤name﹥;example﹤/name﹥;//自定义的标记名  
  30.  
  31. ﹤tagclass﹥;tags.ExampleTag﹤/tagclass﹥;//定位标签处理类文件  
  32.  
  33. ﹤info﹥;Simplestexample﹤/info﹥;//描述信息  
  34.  
  35. ﹤bodycontent﹥;EMPTY﹤/bodycontent﹥;//不处理JSP文件正文内容  
  36.  
  37. ﹤/tag﹥;  
  38.  
  39. ﹤/taglib﹥; 

此文件将配置在服务器的特定位置

⑶使用以上自定义的JSP标记

  1. ﹤!--文件名:simpleExample.jsp--﹥;  
  2.  
  3. ﹤!DOCTYPEHTMLPUBLIC“-//W3C//DTDHTML4.0Transitional//EN”﹥;  
  4.  
  5. ﹤HTML﹥;  
  6.  
  7. ﹤HEAD﹥;  
  8.  
  9. ﹤%@tagliburi=“csajsp-taglib.tld”prefix=“csajsp”%﹥;//进行标记使用声明  
  10.  
  11. ﹤TITLE﹥;﹤csajsp:example/﹥;﹤TITLE﹥;  
  12.  
  13. LINKREL=STYLESHEETHREF=”JSP-styles.css”  
  14.  
  15. TYPE=”text/css”﹥;  
  16.  
  17. ﹤HEAD﹥;  
  18.  
  19. ﹤BODY﹥;  
  20.  
  21. ﹤H1﹥;﹤csajsp:example/﹥;﹤H1﹥;/使用标记  
  22.  
  23. ﹤csajsp:example/﹥;  
  24.  
  25. ﹤/BODY﹥;  
  26.  
  27. ﹤/HTML﹥;  
  28.  

这样最终在在浏览器上输出为

Customtagexample

3.深入的JSP标记开发

⑴添加标记属性

在标记处理类中可以通过函数setAttribute(Stringvalue)为JSP标记分配属性,这样标记处理程序根据获取的属性值来实现相关功能。

比如:

  1. privateStringmessage=“DefaultMessage”&#59;  
  2.  
  3. publicvoidsetMessage(Stringmessage){  
  4.  
  5. this.message=message&#59;  
  6.  

注意:属性名message是小写的,设置函数中的Message是大写的。

◆与之相关的在tld文件中需要在tag元素中添加如下元素

  1. ﹤tag﹥;  
  2.  
  3. …  
  4.  
  5. ﹤attribute﹥;  
  6.  
  7. ﹤name﹥;message﹤/name﹥;//属性名  
  8.  
  9. ﹤required﹥;false﹤/requied﹥;//属性值是否必须提供。False表示不必,存在缺省值。  
  10.  
  11. ﹤rtexprvalue﹥;true﹤/rtexprvalue﹥;//ture表示属性值可以使用JSP表达式,false表示禁  
  12.  
  13. //止使用  
  14.  
  15. ﹤/attribute﹥;  
  16.  
  17. …  
  18.  
  19. ﹤/tag﹥; 

◆对应JSP文件中引用为:﹤prefix:namemessage=“Hello!”/﹥;

⑵使用标记正文

即是在标记中使用一些包含JSP脚本元素、文本等的内容,这些内容由JSP引擎处理。

形式如下:

﹤prefix:tagname﹥;body(正文内容)﹤prefix:tagname﹥;

在处理JSP标记的正文前,将会调用处理程序的doStartTag()方法,此时要在此方法中返回EVAL_BODY_INCLUDE以表明包含有标记正文;处理完后,将会调用doEndTag()方法,此后要让jsp引擎继续处理后面的页面,得返回EVAL_PAGE,否则返回SKIP_PAGE。

◆对应在tld文件中需要在tag元素中添加如下元素

  1. ﹤tag﹥;  
  2.  
  3. …  
  4.  
  5. ﹤bodycontent﹥;JSP﹤/bodycontent﹥;//表明包含正文  
  6.  
  7. …  
  8.  
  9. ﹤/tag﹥; 

另外:可以设置一些条件来判断是否包含正文的,如下:

  1. publicintdoStartTag(){  
  2.  
  3. ServletRequestrequest=pageContext.getRequest()&#59;  
  4.  
  5. StringdebugFlag=request.getParameter(“debug”)&#59;  
  6.  
  7. If((debugFlag!=null)&&(!debugFlag.equalsIgnoreCase(“false”))){  
  8.  
  9. Return(EVAL_BODY_INCLUDE)&#59;  
  10.  
  11. }  
  12.  
  13. else{  
  14.  
  15. return(SKIP_BODY)&#59;  
  16.  
  17. }  
  18.  

这样只有在url尾部给出请求参数值debug=true,才会显示标记正文的内容。这样可以隐藏一些调试信息。

⑶对标记正文进行处理

JSP的标记可以对包含的正文进行处理(修改),然后再输出。这需要标记处理类继承BodyTagSupport类(TagSupport类的继承)。这个类提供了2个重要的方法用于正文处理。

→doAfterBody:默认执行的方法,在此方法中包含正文的处理过程。

→getBodyContent:返回BodyContent类型的的对象,此对象包含了有关标记正文的信息。

BodyContent类型包含的重要方法:

→getEnclosingWriter:返回JspWriter方法,输出内容。

→getString:返回包含全部JSP标记正文的字符串。

注意:这里和⑵中介绍的输出JSP标记正文的方式不一样。前者的输出是先由JSP引擎解释,这里是在JSP标记处理程序中直接输出到给浏览器。

另外,在doAferBody中返回SKIP_BODY,表示终止标记正文处理;若返回的是EVAL_BODY_TAG,将会再一次调用doAferBody方法,重新处理标记正文,直到返回SKIP_BODY为止。

示例:

→标记处理程序片:

下面的程序片将调用一个filter方法,此方法用于把JSP正文中的字符﹤﹥;“&分别用&it&#59;&gt&#59;&guot&#59;&amp&#59;来代替。以使浏览器按字符原样输出,不进行解释。

  1. publicclassFillterTagextendsBodyTagSupport{  
  2.  
  3. publicintdoAfterBody(){  
  4.  
  5. BodyContentbody=getBodyContent()&#59;  
  6.  
  7. StringfilteredBody=ServletUtilities.filter(body.getString())&#59;//将正文得到的字符串过滤  
  8.  
  9. Try{  
  10.  
  11. JspWriterout=body.getEnclosingWriter()&#59;  
  12.  
  13. out.print(filteredBody)&#59;//输出过滤后的文本  
  14.  
  15. }catch(IOExceptionioe){  
  16.  
  17. System.out.println(“ErrorinFilterTag:“+ioe)&#59;  
  18.  
  19. }  
  20.  
  21. return(SKIP_BODY)&#59;//终止JSP正文处理  
  22.  

→标记符描述文件片

  1. …  
  2.  
  3. ﹤tag﹥;  
  4.  
  5. ﹤name﹥;filter﹤/name﹥;  
  6.  
  7. ﹤tagclass﹥;tags.FilterTag﹤/tagclass﹥;  
  8.  
  9. ﹤bodycontent﹥;JSP﹤/bodycontent﹥;  
  10.  
  11. ﹤/tag﹥;  
  12.  
  13. … 

→JSP文件片

  1. ﹤csajsp:filter﹥;  
  2.  
  3. ﹤STRONG﹥;Iloveyou!﹤/STRONG﹥;  
  4. ;  
  5.  
  6. ﹤EM﹥;Iloveyou!﹤EM﹥;  
  7.  
  8. ﹤/csajsp:filter﹥; 

这样,在浏览器中输出的标记正文应当是

  1. ﹤STRONG﹥;Iloveyou!﹤/STRONG﹥;  
  2. ;  
  3.  
  4. ﹤EM﹥;Iloveyou!﹤EM﹥; 

而不是

Iloveyou!

Iloveyou!

⑶使用JSP嵌套标记。

可以对多个JSP标记进行嵌套引用,这样子标记就可以访问和存储父标记的数据和方法。

子标记访问父标记需要使用BodyTagSupport类中的findAccetorWithClass方法。注意它只能查找临近的父标记。

假如在JSP文件中如下的嵌套引用:

 

  1. ﹤!--此嵌套标记模拟条件判断--﹥;  
  2.  
  3. ﹤csajsp:if﹥;  
  4.  
  5. ﹤csajsp:condition﹥;true﹤/csajsp:condition﹥;  
  6.  
  7. ﹤csajsp:then﹥;Conditionwastrue﹤/csajsp:then﹥;  
  8.  
  9. ﹤csajsp:else﹥;Conditionwasfalse﹤/csajsp:else﹥;  
  10.  
  11. ﹤/csajsp:if﹥;  
  12.  
  13. 相应的标记处理程序片:  
  14.  
  15. →对于if标记,执行类如下:  
  16.  
  17. publicclassIfTagextendsTagSupport{  
  18.  
  19. privatebooleancondition&#59;  
  20.  
  21. privateBooleanhasCondition=flase&#59;  
  22.  
  23. publicvoidsetCondition(Booleancondition){//设置判断条件的真假;condition子标  
  24.  
  25. //记调用  
  26.  
  27. this.condition=condition&#59;  
  28.  
  29. hasCondition=true&#59;  
  30.  
  31. }  
  32.  
  33. publicBooleangetCondition(){//获取判断条件的真假then、else子标  
  34.  
  35. //记调用  
  36.  
  37. return(condition)&#59;  
  38.  
  39. }  
  40.  
  41. publicvoidsetHasCondition(Booleanflag){//判断if标记后是否存在条件,由  
  42.  
  43. //condition子标记调用  
  44.  
  45. this.hasCondition=flag&#59;  
  46.  
  47. }  
  48.  
  49. publicBooleangetHasCondition(){//获取是否存在判断条件的信息,由  
  50.  
  51. //then、else标记调用  
  52.  
  53. return(hasCondition)&#59;  
  54.  
  55. }  
  56.  
  57. publicintdoStartTag(){  
  58.  
  59. return(EVAL_BODY_INCLUDE)//包含子标记  
  60.  
  61. }  
  62.  
  63. }  
  64.  

→那么对于condition等其它子标记的处理程序,需要获取父标记处理程序对象:

IfTagparent=(IfTag)findAncestorWithClass(this,IfTag.class)

之后就可以操作父标记处理程序的相应方法。

示例:(对于condition标记)

  1. publicclassIfConditionTagextendsBodyTagSupport{  
  2.  
  3. ifTagparent=(IfTag)findAncestorWithClass(this,IfTag.class)&#59;//获取父标记对应的对象  
  4.  
  5. If(parent==null){  
  6.  
  7. ThrownewJspTagException(“conditionnotinsideit”)&#59;  
  8.  
  9. }  
  10.  
  11. return(EVAL_BODY_TAG)&#59;  
  12.  
  13. }  
  14.  
  15.  
  16.  
  17. publicintdoAfterBody(){  
  18.  
  19. ifTagparent=(IfTag)findAncestorWithClass(this,IfTag.class)&#59;  
  20.  
  21. StringbodyString=getBodyContent().getString()&#59;  
  22.  
  23. If(bodyString.trim().equals(“true”)){  
  24.  
  25. Parent.setCondition(true)//访问父标记处理类中的方法  
  26.  
  27. }else{  
  28.  
  29. parent.setCondition(false)&#59;  
  30.  
  31. }  
  32.  
  33. return(SKIP_BODY)&#59;  
  34.  
  35. }  
  36.  
  37. }  
  38.  

其余标记类和此相似。

4.小结

对于一些不太复杂和功能单一的逻辑描述,需要传递的参数要求不高时,使用JSP标记,要方便的多。对于大多数的商业逻辑应用,还是使用bean要好的多,也宜于servlet控制。

这个东东是俺学习人邮出的Servletlet与JSP核心技术》时随手写下的。里面的程序还没具体配置过。过段时间弄了再搞篇实验体会吧。

以上就是JSP标记学习笔记,希望对于初学者有所帮助,对你的开发有一定的引导。

【编辑推荐】

  1. 基于JSP实现数据库中图片的存储与显示
  2. JSP入门之避免Form表单重复提交的几种方案
  3. JSP入门需要知道的五个方面
  4. JSP导出Oracle数据表的操作浅谈
  5. 在JSP中实现页面跳转
责任编辑:仲衡 来源: chinaunix
相关推荐

2009-07-03 09:08:23

JSP标记学习笔记

2010-08-10 16:41:54

FlexJSP

2009-06-29 17:39:31

JSP设计模式

2009-07-06 13:52:56

编写JSP Tag

2009-08-11 14:05:28

JSP验证码

2009-08-03 09:15:39

JSP标准标记库JSTL

2009-07-02 11:34:42

JSP指令JSP开发

2010-09-07 10:33:04

CSS

2009-07-14 10:47:47

MyEclipse J

2009-07-06 14:05:11

JSP服务器

2009-07-07 14:33:44

JSP入门

2009-07-03 17:48:34

JSP页面翻译

2009-07-01 18:20:29

JSP的优势

2009-07-02 10:51:21

脚本编程JSP开发

2009-06-16 15:20:48

ApplicationJSP程序

2009-07-06 17:11:38

Servlet文件上传

2009-03-17 16:18:51

JspActionStruts

2009-07-06 12:49:33

JSP编译器

2010-02-22 09:16:49

Spring 3.0.JSP标记

2009-07-03 14:41:03

点赞
收藏

51CTO技术栈公众号