[学习笔记]JSP自定义标签(1)

一、引入标签


其实在JSP中我们已经使用过了几个标签,比如<jsp:forward>、<jsp:include>等;这些标签都是预先定义好的,如果我们需要自定义标签,就需要学习标签编程。

标签编程的优点就是灵活性+封装性。

灵活性体现在属性的赋值上,可以赋任意值。比如<jsp:forward page="A">   //A处可以赋任意的URL;

封装性体现在内部的行为的封装,因为标签是用一个类实现的,因此类的方法中能够包含任意复杂的动作。

因此标签是为了能够在JSP中使用尽可能少的Scriptlet;

比如:

[html]  view plain  copy
  1. <table>  
  2. <%  
  3.     for(int i=0;i<10;i++){  
  4. %>  
  5.     <tr>  
  6. <%  
  7.         for(int j=0;j<10;j++){  
  8. %>  
  9.         <td><%=i*j%></td>  
  10. <%  
  11.         }  
  12. %>  
  13.     </tr>  
  14. <%  
  15.     }  
  16. %>  
  17. </table>  

这个代码非常混乱,但是如果通过标签,从这段代码都封装在一个标签里,则代码就清晰了很多。


接下来是我通过标签封装后的JSP页面效果;

[html]  view plain  copy
  1. <%@ page contentType="text/html" pageEncoding="GBK"%>  
  2. <%@ taglib prefix="xiazdong" uri="xiazdong"%>  
  3. <html>  
  4.     <head>  
  5.         <title></title>  
  6.     </head>  
  7.     <body>  
  8.         <xiazdong:table row="5" col="3"/>  
  9.     </body>  
  10. </html>  

是不是大大缩短了呢??再来看看我在背后干了什么。。。。

TableTagSupport.java

[java]  view plain  copy
  1. package org.tagext;  
  2. import javax.servlet.jsp.tagext.*;  
  3. import javax.servlet.jsp.*;  
  4. public class TableTagSupport extends TagSupport{  
  5.     private String row;  
  6.     private String col;  
  7.     public String getRow(){  
  8.         return row;  
  9.     }  
  10.     public String getCol(){  
  11.         return col;  
  12.     }  
  13.     public void setRow(String row){  
  14.         this.row = row;  
  15.     }  
  16.     public void setCol(String col){  
  17.         this.col = col;  
  18.     }  
  19.     public int doStartTag()throws JspException{  
  20.         JspWriter out = super.pageContext.getOut();  
  21.         try{  
  22.             out.println("<table border=\"3\"> ");  
  23.             for(int i=0;i<Integer.parseInt(row);i++){  
  24.                 out.println("<tr>");  
  25.                 for(int j=0;j<Integer.parseInt(col);j++){  
  26.                     out.println("<td>"+i*j+"</td>");  
  27.                 }  
  28.                 out.println("</tr>");  
  29.             }  
  30.             out.println("</table>");  
  31.         }  
  32.         catch(Exception e){}  
  33.         return TagSupport.SKIP_BODY;  
  34.     }  
  35. }  

是不是很神奇。。。那接下来就看看实现的过程吧。

注意,在编写标签之前,必须把tomcat\lib中的jsp-api.jar文件配置在CLASSPATH中才可以;


二、基本标签编写


1、TagSupport类


如果要编写一个标签类,则必须继承javax.servlet.jsp.tagext.TagSupport

TagSupport中提供了很多常用方法:

(1)    public int doStartTag()throws JspException;    //    标签开始时调用

能够返回SKIP_BODY(跳过标签体)、EVAL_BODY_INCLUDE(执行标签体)

(2)    public int doEndTag()throws JspException;    //     标签结束时调用

能够返回SKIP_PAGE(立刻停止执行)、EVAL_PAGE(JSP正常运行完毕);

(3)    int SKIP_BODY;        // 跳过标签体

(4)    int EVAL_BODY_INCLUDE;    //执行标签体

(5)    int EVAL_BODY_AGAIN;    //  重复执行标签体,主要是因为集合迭代输出,只能在doAfterBody中使用;

(6)    public int doAfterBody()throws JspException;    //   执行完一次标签体后调用的函数;

能够返回SKIP_BODY(结束标签体)、EVAL_BODY_AGAIN(重复执行标签体)

(7)  JspWriter out = super.pageContext.getOut();//获取向网页输出的输出流;

举例讲述这些函数和常量代表什么意思:

[html]  view plain  copy
  1. <xiazdong:hello>                                <!--标签头 -->  
  2.         <h3><%="xiazdong"%></h3>            <!--    标签体-->  
  3. </xiazdong:hello>                                <!-- 标签尾-->  

执行流程如下:

(1)doStartTag();   <xiazdong:hello>时调用,如果是EVAL_BODY_INCLUDE,则继续;如果是SKIP_BODY,则执行(4)

(2)执行标签体;

(3)如果实现了doAfterBody,则执行;如果返回SKIP_BODY,则执行(4) ; 如果返回EVAL_BODY_AGAIN,则重复执行doAfterBody;

(4)doEndTag():标签尾调用;


 2.制作无属性标签


为了清晰,我们以例子说明。

代码举例1:实现显示Hello world;


1.编写HelloTag.java


[java]  view plain  copy
  1. package org.tagext;  
  2. import javax.servlet.jsp.tagext.*;  
  3. import javax.servlet.jsp.*;  
  4.   
  5. public class HelloTag extends TagSupport{  
  6.     public int doStartTag()throws JspException{  
  7.         JspWriter out = super.pageContext.getOut();  
  8.         try{  
  9.             out.println("<h3>Hello world!!!</h3>");  
  10.         }  
  11.         catch(Exception e){}  
  12.         return TagSupport.SKIP_BODY;  
  13.     }  
  14. }  

注意点:

(1)javax.servlet.jsp.tagext.TagSupport,必须记住;

(2)JspWriter out = super.pageContext.getOut();

(3)public int doStartTag()throws JspException;必须记住;


2.编写xiazdong.tld 


tld文件是标签描述文件,是整个标签编程的核心,用来描述自定义的标签的名字、标签的实现类、是否有标签体、描述属性等;

一个tld文件其实类似于一个标签库,里面能够描述很多标签;每个标签都以

[html]  view plain  copy
  1. <tag>  
  2.     <name>hello</name>      <!--表示标签的名字 类似于<jsp:forward>中的forward-->  
  3.     <tag-class>org.tagext.HelloTag</tag-class>  <!--标签所在类 -->  
  4.     <body-content>empty</body-content>      <!--是否存在标签体-->  
  5. </tag>  

的形式描述;

*.tld文件的模版如下:(因为tld文件前面这些内容都不是很重要,因此可以直接复制黏贴)

[html]  view plain  copy
  1. <?xml version="1.0" encoding="UTF-8" ?>  
  2.   
  3. <taglib xmlns="http://java.sun.com/xml/ns/j2ee"  
  4.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  5.     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"  
  6.     version="2.0">  
  7.     <tlib-version>1.0</tlib-version>  
  8.     //插入tag描述  
  9. </taglib>  


3.在web.xml中编写映射


编写映射的目的类似于给一个网页配置一个映射地址,为了方便访问;

比如本来需要访问/a/b/c/d/e/f/g/1.tld,这个路径非常麻烦,但是如果通过映射,我们可以只需要用"a"表示一长串的文件路径及名称;

[html]  view plain  copy
  1. <jsp-config>  
  2.     <taglib>  
  3.         <taglib-uri>xiazdong</taglib-uri>  
  4.         <taglib-location>/WEB-INF/classes/xiazdong.tld</taglib-location>  
  5.     </taglib>  
  6. </jsp-config>  


4.编写JSP页面并使用自定义的标签


<%@ taglib prefix=""   uri=""%>        prefix类似于<jsp:forward>中的jsp,uri中使用前面所说的映射;

[html]  view plain  copy
  1. <%@ page contentType="text/html" pageEncoding="GBK"%>  
  2. <%@ taglib prefix="xiazdong" uri="xiazdong"%>  
  3. <html>  
  4.     <head>  
  5.         <title></title>  
  6.     </head>  
  7.     <body>  
  8.         <h1><xiazdong:hello/></h1>  
  9.     </body>  
  10. </html>  


 3.制作有属性标签


其实制作有属性和制作无属性没有太大区别,


1.需要在原来的HelloTag.java 中加入属性.


如果做形如:<xiazdong:hello id="" format="" />的属性,则需要在HelloTag.java中添加两个属性,id属性和format属性;

形如:

[java]  view plain  copy
  1. class HelloTag extends TagSupport  
  2. {  
  3.     private String id;  
  4.     private String format;  
  5.     //setter和getter  
  6.     public int doStartTag()throws JspException{}  
  7. }  

在用户使用标签,并为id和format属性赋值时,会自动调用setter方法,将HelloTag类中的id和format赋值;


2.在tld文件中添加属性描述:


属性描述形如:

[java]  view plain  copy
  1. <body-content>empty</body-content>后面加上  
  2. <attribute>  
  3.     <name>name</name>       <!--属性姓名 -->  
  4.     <required>true</required>   <!--属性是否必要 -->  
  5.     <rtexprvalue>empty</rtexprvalue>    <!--是否支持表达式语言 -->  
  6. </attribute>  


代码实例:


HelloTag.java

[java]  view plain  copy
  1. package org.tagext;  
  2. import javax.servlet.jsp.tagext.*;  
  3. import javax.servlet.jsp.*;  
  4.   
  5. public class HelloTag extends TagSupport{  
  6.     private String name;  
  7.     private String age;  
  8.     public String getName(){  
  9.         return name;  
  10.     }  
  11.     public String getAge(){  
  12.         return age;  
  13.     }  
  14.     public void setName(String name){  
  15.         this.name = name;  
  16.     }  
  17.     public void setAge(String age){  
  18.         this.age = age;  
  19.     }  
  20.     public int doStartTag()throws JspException{  
  21.         JspWriter out = super.pageContext.getOut();  
  22.         try{  
  23.             out.println("<h3>姓名:"+name+"</h3>");  
  24.             out.println("<h3>年龄:"+age+"</h3>");  
  25.         }  
  26.         catch(Exception e){}  
  27.         return TagSupport.SKIP_BODY;  
  28.     }  
  29. }  


xiazdong.tld
需要加上attribute的描述:名字、是否必须、是否支持表达式语言
[java]  view plain  copy
  1. <?xml version="1.0" encoding="UTF-8" ?>  
  2.   
  3. <taglib xmlns="http://java.sun.com/xml/ns/j2ee"  
  4.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  5.     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"  
  6.     version="2.0">  
  7.   <tlib-version>1.0</tlib-version>  
  8.   <short-name>x</short-name>  
  9.   <tag>  
  10.     <name>hello</name>  
  11.     <tag-class>org.tagext.HelloTag</tag-class>  
  12.     <body-content>empty</body-content>  
  13.     <attribute>  
  14.         <name>name</name>  
  15.         <required>true</required>  
  16.         <rtexprvalue>empty</rtexprvalue>  
  17.     </attribute>  
  18.     <attribute>  
  19.         <name>age</name>  
  20.         <required>true</required>  
  21.         <rtexprvalue>empty</rtexprvalue>  
  22.     </attribute>  
  23.   </tag>  
  24. </taglib>  

HelloTag.jsp
[html]  view plain  copy
  1. <%@ page contentType="text/html" pageEncoding="GBK"%>  
  2. <%@ taglib prefix="xiazdong" uri="xiazdong"%>  
  3. <html>  
  4.     <head>  
  5.         <title></title>  
  6.     </head>  
  7.     <body>  
  8.         <h1><xiazdong:hello name="xiazdong" age="20"/></h1>  
  9.     </body>  
  10. </html>  

三、IterationTag和Tag接口的区别


Tag接口只有一些最基本的标签编程方法,而IterationTag接口是用于迭代输出,比如EVAL_BODY_AGAIN等;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值