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类;
简单示例:
- //文件名ExampleTag.java
- importjavax.servlet.jsp.*;
- importjavax.servlet.jsp.tagext.*;
- importjava.io.*;
- publicclassExampleTagextendsTagSupport{
- //程序的执行起始点
- publicintdoStartTag(){
- try{
- JspWriterout=pageContext.getOut();
- out.print(“Customtagexample”);
- }catch(IOExceptionioe){
- System.out.println(“ErrorinExampleTag:“+ioe);
- }
- return(SKIP_BODY);//当标记包括的内容为空时返回SKIP_BODY,表示标记功能
- //已执行完成
- }
- }
编译好的class文件将位于服务器的的特定位置。
⑵编写JSP标记库描述符文件
将标记名和其代表的功能实现联系在一起。
简单示例:
- ﹤!--文件名:csajsp-taglib.tld--﹥;
- ﹤?xmlversion=”1.0”encoding=”ISO-8859-1”?﹥;
- ﹤!DOCTYPEtaglib
- PUBLIC“-//SunMicrosystem,Inc.//DTDJSPTagLibrary1.1//EN”
- http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd﹥;
- //以上是标准的文件头
- //以下是标签库描述
- ﹤tlibversion﹥;1.0﹤/tlibversion﹥;//Tag库的版本
- ﹤jspversion﹥;1.1﹤/jspversion﹥;//JSP库的版本
- ﹤shortname﹥;csajsp﹤/shortname﹥;//自定义标记前缀名
- ﹤uri﹥;﹤/uri﹥;//标记描述符文件的uri,可以是空
- ﹤info﹥;Mycustomtag!﹤/info﹥;//标记库的描述信息
- //以下定义新标记
- ﹤tag﹥;
- ﹤name﹥;example﹤/name﹥;//自定义的标记名
- ﹤tagclass﹥;tags.ExampleTag﹤/tagclass﹥;//定位标签处理类文件
- ﹤info﹥;Simplestexample﹤/info﹥;//描述信息
- ﹤bodycontent﹥;EMPTY﹤/bodycontent﹥;//不处理JSP文件正文内容
- ﹤/tag﹥;
- ﹤/taglib﹥;
此文件将配置在服务器的特定位置
⑶使用以上自定义的JSP标记
- ﹤!--文件名:simpleExample.jsp--﹥;
- ﹤!DOCTYPEHTMLPUBLIC“-//W3C//DTDHTML4.0Transitional//EN”﹥;
- ﹤HTML﹥;
- ﹤HEAD﹥;
- ﹤%@tagliburi=“csajsp-taglib.tld”prefix=“csajsp”%﹥;//进行标记使用声明
- ﹤TITLE﹥;﹤csajsp:example/﹥;﹤TITLE﹥;
- ﹤LINKREL=STYLESHEETHREF=”JSP-styles.css”
- TYPE=”text/css”﹥;
- ﹤HEAD﹥;
- ﹤BODY﹥;
- ﹤H1﹥;﹤csajsp:example/﹥;﹤H1﹥;/使用标记
- ﹤csajsp:example/﹥;
- ﹤/BODY﹥;
- ﹤/HTML﹥;
这样最终在在浏览器上输出为
Customtagexample
3.深入的JSP标记开发
⑴添加标记属性
在标记处理类中可以通过函数setAttribute(Stringvalue)为JSP标记分配属性,这样标记处理程序根据获取的属性值来实现相关功能。
比如:
- privateStringmessage=“DefaultMessage”;
- publicvoidsetMessage(Stringmessage){
- this.message=message;
- }
注意:属性名message是小写的,设置函数中的Message是大写的。
◆与之相关的在tld文件中需要在tag元素中添加如下元素
- ﹤tag﹥;
- …
- ﹤attribute﹥;
- ﹤name﹥;message﹤/name﹥;//属性名
- ﹤required﹥;false﹤/requied﹥;//属性值是否必须提供。False表示不必,存在缺省值。
- ﹤rtexprvalue﹥;true﹤/rtexprvalue﹥;//ture表示属性值可以使用JSP表达式,false表示禁
- //止使用
- ﹤/attribute﹥;
- …
- ﹤/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元素中添加如下元素
- ﹤tag﹥;
- …
- ﹤bodycontent﹥;JSP﹤/bodycontent﹥;//表明包含正文
- …
- ﹤/tag﹥;
另外:可以设置一些条件来判断是否包含正文的,如下:
- publicintdoStartTag(){
- ServletRequestrequest=pageContext.getRequest();
- StringdebugFlag=request.getParameter(“debug”);
- If((debugFlag!=null)&&(!debugFlag.equalsIgnoreCase(“false”))){
- Return(EVAL_BODY_INCLUDE);
- }
- else{
- return(SKIP_BODY);
- }
- }
这样只有在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正文中的字符﹤﹥;“&分别用⁢>&guot;&来代替。以使浏览器按字符原样输出,不进行解释。
- publicclassFillterTagextendsBodyTagSupport{
- publicintdoAfterBody(){
- BodyContentbody=getBodyContent();
- StringfilteredBody=ServletUtilities.filter(body.getString());//将正文得到的字符串过滤
- Try{
- JspWriterout=body.getEnclosingWriter();
- out.print(filteredBody);//输出过滤后的文本
- }catch(IOExceptionioe){
- System.out.println(“ErrorinFilterTag:“+ioe);
- }
- return(SKIP_BODY);//终止JSP正文处理
- }
→标记符描述文件片
- …
- ﹤tag﹥;
- ﹤name﹥;filter﹤/name﹥;
- ﹤tagclass﹥;tags.FilterTag﹤/tagclass﹥;
- ﹤bodycontent﹥;JSP﹤/bodycontent﹥;
- ﹤/tag﹥;
- …
→JSP文件片
- ﹤csajsp:filter﹥;
- ﹤STRONG﹥;Iloveyou!﹤/STRONG﹥;
- ;
- ﹤EM﹥;Iloveyou!﹤EM﹥;
- ﹤/csajsp:filter﹥;
这样,在浏览器中输出的标记正文应当是
- ﹤STRONG﹥;Iloveyou!﹤/STRONG﹥;
- ;
- ﹤EM﹥;Iloveyou!﹤EM﹥;
而不是
Iloveyou!
Iloveyou!
⑶使用JSP嵌套标记。
可以对多个JSP标记进行嵌套引用,这样子标记就可以访问和存储父标记的数据和方法。
子标记访问父标记需要使用BodyTagSupport类中的findAccetorWithClass方法。注意它只能查找临近的父标记。
假如在JSP文件中如下的嵌套引用:
- ﹤!--此嵌套标记模拟条件判断--﹥;
- ﹤csajsp:if﹥;
- ﹤csajsp:condition﹥;true﹤/csajsp:condition﹥;
- ﹤csajsp:then﹥;Conditionwastrue﹤/csajsp:then﹥;
- ﹤csajsp:else﹥;Conditionwasfalse﹤/csajsp:else﹥;
- ﹤/csajsp:if﹥;
- 相应的标记处理程序片:
- →对于if标记,执行类如下:
- publicclassIfTagextendsTagSupport{
- privatebooleancondition;
- privateBooleanhasCondition=flase;
- publicvoidsetCondition(Booleancondition){//设置判断条件的真假;condition子标
- //记调用
- this.condition=condition;
- hasCondition=true;
- }
- publicBooleangetCondition(){//获取判断条件的真假then、else子标
- //记调用
- return(condition);
- }
- publicvoidsetHasCondition(Booleanflag){//判断if标记后是否存在条件,由
- //condition子标记调用
- this.hasCondition=flag;
- }
- publicBooleangetHasCondition(){//获取是否存在判断条件的信息,由
- //then、else标记调用
- return(hasCondition);
- }
- publicintdoStartTag(){
- return(EVAL_BODY_INCLUDE)//包含子标记
- }
- }
→那么对于condition等其它子标记的处理程序,需要获取父标记处理程序对象:
IfTagparent=(IfTag)findAncestorWithClass(this,IfTag.class)
之后就可以操作父标记处理程序的相应方法。
示例:(对于condition标记)
- publicclassIfConditionTagextendsBodyTagSupport{
- ifTagparent=(IfTag)findAncestorWithClass(this,IfTag.class);//获取父标记对应的对象
- If(parent==null){
- ThrownewJspTagException(“conditionnotinsideit”);
- }
- return(EVAL_BODY_TAG);
- }
- publicintdoAfterBody(){
- ifTagparent=(IfTag)findAncestorWithClass(this,IfTag.class);
- StringbodyString=getBodyContent().getString();
- If(bodyString.trim().equals(“true”)){
- Parent.setCondition(true)//访问父标记处理类中的方法
- }else{
- parent.setCondition(false);
- }
- return(SKIP_BODY);
- }
- }
其余标记类和此相似。
4.小结
对于一些不太复杂和功能单一的逻辑描述,需要传递的参数要求不高时,使用JSP标记,要方便的多。对于大多数的商业逻辑应用,还是使用bean要好的多,也宜于servlet控制。
这个东东是俺学习人邮出的Servletlet与JSP核心技术》时随手写下的。里面的程序还没具体配置过。过段时间弄了再搞篇实验体会吧。
以上就是JSP标记学习笔记,希望对于初学者有所帮助,对你的开发有一定的引导。
【编辑推荐】