JSP自定义标签——简单标签(1)

  前面一篇博客介绍了自定义标签的传统标签使用方式,但是我们会发现,使用传统标签非常的麻烦,而且接口还多,现在传统标签基本都没用了,除了一些比较久的框架。Sun公司之后推出了一个新的标签使用方式,称之为简单标签。简单标签也作为JSP2.0以后的标准标签使用方式,下面是一张传统标签和简单标签的对比,可以看到简单标签真的简化了不少:

  

  与传统标签的使用步骤是类似的,需要满足以下两个步骤:

  ① 编写一个实现SimpleTag接口(实际上我们更常的是继承SimpleTagSupport接口的实现类从而免于覆写所有的方法)的Java类,这个Java类也称为标签处理器类。

  ② 编写标签的TLD文件,用于指定标签的URI和对标签的声明描述,这一点和EL函数时一样的,TLD文件必须放置在web应用下的【WEB-INF】文件中,可以是除【classes】和【lib】目录以外的任何子目录中。TLD文件的模板可以从【Tomcat】--->【webapps】--->【examples】--->【WEB-INF】--->【jsp2】中有一个“jsp2-example-taglib.tld”文件复制首尾和其中的<Tag>标签。

  注:在TLD文件中我们使用<tag>标签来对每一个自定义标签的Java类进行描述,其中每个<tag>标签下还需要指定<body-content>的值,这个是描述标签体的类型:对于简单标签使用:“empty”(无标签体内容时) 或“scriptless” (有标签体内容时)。

  注意:简单标签在JSP页面中,标签体内容中是不允许使用JSP脚本的。

 

  与传统标签需要使用doStartTag()方法和doEndTag()方法不同,简单标签只需要doTag()方法来处理标签,所有的标签体内容逻辑,迭代,是否执行标签体内容等等都只需要调用doTag()方法即可。因此简单标签能和传统标签的bodyTagSupport能有一样的功能,但是生命周期方式更简单并且只有一个接口。

下图是简单标签SimpleTag接口的所有方法:

  

  其中除了getParent方法以外,其他都是生命周期方法,这一点和传统标签类似。简单自定义标签的生命周期顺序为:① 创建自定义标签的实例对象 ---> ② setJspContext方法 ---> ③ setJspBody方法(如果有标签体才调用) ---> ④ setParent方法(如果有父类自定义标签才调用)---> ⑤ doTag方法 ---> ⑥ 该自定义标签的实例对象将被垃圾回收器回收(与传统自定义标签不同,简单标签的标签处理器类对象不会缓存)。

  下面简单地介绍下这几个生命周期方法:

  setJspContext(JspContext  pc)方法,JSP容器对简单标签进行实例化对象后,通过调用这个方法,将pageContext对象(pageContext是JspContext的子类)传入标签处理器类从而使得在标签处理器类处理标签和标签体时(doTag)能通过这个对象获取其他八大web对象。

  setJspBody(JspFragment jspBody)方法,是将标签体内容封装为一个JspFragment对象传入给标签处理器类,也就是说JspFragment对象就代表标签体的内容。如果想要执行标签体,只需要调用JspFragment对象的invoke(Writer out)方法传入一个输出流对象即可,或者如果往invoke方法中传入的参数为null的话,默认参数为JspWriter对象,等效于invoke(this.getJspContext.getOut)。如果不调用invoke方法,那么就不会执行标签体内容,另外可以随意调用多次invoke方法。另外如果简单标签没有标签体内容,那么setJspBody不会被调用。

  setParent方法,只有在该自定义标签嵌入在另一个自定义标签中才会调用,记住父标签必须也是自定义标签才可以,如果父标签只是简单的HTML标签那么该setParent方法不会被调用。

doTag()方法,由JSP容器来调用,通常是由我们开发人员来覆写这个方法的实现,我们要使用标签来完成任何功能的实现都在这个方法中。如果我们不想执行这个标签后面余下的JSP页面,那么只需要在这个方法内抛出一个“SkipPageException”异常即可。

  如果要想直接实现SimpleTag接口,那么在这个实现类中一定要有一个无参的构造函数。通常我们选择继承SimpleTag接口的实现类,也就是SimpleTagSupport类。继承SimpleTagSupport类的话,继承的子类中还可以使用SimpleTagSupport类给子类提供的方法获取pageContext对象或者JspFragment对象:

  

 

例1:使用简单标签来控制是否执行标签体内容

编写标签处理器类:

 1 package com.fjdingsd.simpletag;
 2 public class ShowTagBodyOrNot extends SimpleTagSupport {
 3     @Override
 4     public void doTag() throws JspException, IOException {
 5         
 6         JspFragment fragment = this.getJspBody();        
 7         fragment.invoke(this.getJspContext().getOut());
 8         //上面的代码等效于fragment.invoke(null);
 9     }
10 }
View Code

在TLD文件中声明描述标签:

 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 <taglib xmlns="http://java.sun.com/xml/ns/j2ee"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
 5     version="2.0">
 6     <description>A tag library exercising SimpleTag handlers.</description>
 7     <tlib-version>1.0</tlib-version>
 8     <short-name>SimpleTagLibrary</short-name>
 9     <uri>simpletag</uri>
10    
11      <tag>
12         <name>showbody</name>
13         <tag-class>com.fjdingsd.simpletag.ShowTagBodyOrNot</tag-class>
14         <body-content>scriptless</body-content>
15     </tag>
16 
17 </taglib>
View Code

在JSP页面中导入taglib指令:

    <%@ taglib uri="simpletag" prefix="simple" %>

最后就可以在JSP页面的主体中使用刚才定义的简单标签了:

1     <simple:showbody>
2             银魂
3        </simple:showbody>
View Code

在浏览器中观察:

  

  分析:能显示的原因,是因为在这个标签中,将标签体封装成JspFragment对象,并且通过这个对象调用了invoke()方法,即执行标签体内容,如果我们想控制标签体内容不输出显示的话,只要不调用invoke()方法即可,修改例1的标签处理器类:

1 public class ShowTagBodyOrNot extends SimpleTagSupport {
2     @Override
3     public void doTag() throws JspException, IOException {
4         
5         JspFragment fragment = this.getJspBody();    //这句代码,或者甚至这个方法没有都可以,都能控制标签体内容不执行,要想执行必须要有JspFragment.invoke方法    
6         
7     }
8 }
View Code

  其他TLD文件等等内容都不变,则浏览器中不会对这个标签显示任何内容。

 

例2:使用简单标签来控制标签体内容执行次数

编写标签处理器类:

 1 package com.fjdingsd.simpletag;
 2 public class LoopTagBody extends SimpleTagSupport {
 3     @Override
 4     public void doTag() throws JspException, IOException {    
 5         JspFragment fragment = this.getJspBody();
 6         for(int i=0;i<3;i++) {
 7             fragment.invoke(null);     //标签体执行3次
 8         }
 9     }    
10 }
View Code

在TLD文件中描述(这里省略首尾,详细内容请看例1):

1 <tag>
2       <name>loopbody</name>
3       <tag-class>com.fjdingsd.simpletag.LoopTagBody</tag-class>
4       <body-content>scriptless</body-content>
5  </tag>
View Code

在JSP页面中导入taglib指令(此处略)后,在JSP页面的主体中使用刚才定义的简单标签:

1     <simple:loopbody>
2             神乐  <br>
3       </simple:loopbody>
View Code

在浏览器中观察:

  

 

例3:使用简单标签来修改标签体内容再输出(这里将标签体内容中所有字母变为大写)

  分析:要想使用简单标签来修改标签体内容再输出,需要先获取标签体对象(JspFragment),我们知道要想执行标签体必须调用invoke(Writer out)方法,但是如果我们使用非缓冲的Writer输出流,那么就直接输出给浏览器了,无法达到修改目的,因此我们应该使用带有缓冲流的字符流对象,将标签体内容通过invoke方法先存入字符流,再从字符流中取出修改最后再输出给浏览器。

编写标签处理器类:

 1 package com.fjdingsd.simpletag;
 2 public class ModifyTagBody extends SimpleTagSupport {
 3     @Override
 4     public void doTag() throws JspException, IOException {
 5         JspFragment fragment = this.getJspBody();
 6         StringWriter writer = new StringWriter();
 7         fragment.invoke(writer);
 8         
 9         String tagContent = writer.toString().toUpperCase();
10         this.getJspContext().getOut().write(tagContent);
11     }    
12 }
View Code

另:使用StringWriter缓冲流是因为StringWriter能够获得缓冲区中的值:

  

在TLD文件中描述(这里省略首尾,详细内容请看例1):

1 <tag>
2         <name>modifybody</name>
3         <tag-class>com.fjdingsd.simpletag.ModifyTagBody</tag-class>
4         <body-content>scriptless</body-content>
5 </tag>
View Code

在JSP页面中导入taglib指令(此处略)后,在JSP页面的主体中使用刚才定义的简单标签:

1     <simple:modifybody>
2             long live sd
3      </simple:modifybody>
View Code

在浏览器中观察:

  

 

例4:使用简单标签来控制便签后余下的JSP页面是否显示

  若想使用简单标签来控制便签后余下的JSP页面不显示,只需要在标签处理器类的doTag方法中抛出“SkipPageException”异常即可。

 编写标签处理器类:

1 package com.fjdingsd.simpletag;
2 public class HideRemainJSP extends SimpleTagSupport {
3     @Override
4     public void doTag() throws JspException, IOException {
5         
6         throw new SkipPageException();
7     }
8 }
View Code

在TLD文件中描述(这里省略首尾,详细内容请看例1):

1 <tag>
2           <name>hidepage</name>
3           <tag-class>com.fjdingsd.simpletag.HideRemainJSP</tag-class>
4           <body-content>empty</body-content>
5 </tag>
View Code

在JSP页面中导入taglib指令(此处略)后,在JSP页面的主体中使用刚才定义的简单标签:

 1 <simple:hidepage/>
 2 
 3 <!DOCTYPE HTML>
 4 <html>
 5   <head>
 6     <title>My JSP 'simpletagdemo.jsp' starting page</title>
 7   </head>
 8   
 9   <body>
10 。。。
11   </body>
12 </html>
View Code

  结果:我在JSP页面最开始的地方使用了刚才自定义的简单标签,控制该标签后的页面不再执行,因此浏览器访问该页面中将只会看到空白页面,包括页面源码也是为空。

 

 

 

 

    

 

转载于:https://www.cnblogs.com/fjdingsd/p/5118166.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值