jsp中自定义Taglib详解 一、自定义标签入门之无参数自定义标签 1.开发自定义标签类 当我们在JSP页面使用一个简单的标签时,底层实际上由标签处理类提供支持,从而可以使用简单的标签来封装复杂的功能,从而使团队更好地协作开发(能让美工人员更好地参与JSP页面的开发)。 自定义标签类都必须继承一个父类:javax.servlet.jsp.tagext.SimpleTagSupport,或者TagSupport除此之外,JSP自定义标签类还有如下要求。 如果标签类包含属性,每个属性都有对应的getter和setter方法。 重写doTag()或者doStartTag()或doEndTag()方法方法,这个方法负责生成页面内容。 首先介绍是不带属性的标签以HelloWorld为例: Java代码如下: public class HelloWorldTag extends TagSupport { private static final long serialVersionUID = -3382691015235241708L; @Override public int doEndTag() throws JspException { try { pageContext.getOut().write("Hello World !"); return super.doEndTag(); } catch (JspException e) { e.printStackTrace(); return 0; } catch (IOException e) { e.printStackTrace(); return 0; } } @Override public int doStartTag() { try { pageContext.getOut().write("Hello World"); return super.doStartTag(); } catch (JspException e) { e.printStackTrace(); return 0; } catch (IOException e) { e.printStackTrace(); return 0; } } } 注意: 问题1:tagsupport中的dostartTag和doEndTag这两个方法有什么区别 doStartTag是在扫描到起始标签时调用,doEndTag是在扫描到结束标签是调用。 例如: helloWorld 则jsp引擎分析到 时调用doStratTag, 分析到时调用doEndTag 2、建立TLD文件 TLD是Tag Library Definition的缩写,即标签库定义,文件的后缀是tld,每个TLD文件对应一个标签库,一个标签库中可包含多个标签,TLD文件也称为标签库定义文件。 标签库定义文件的根元素是taglib,它可以包含多个tag子元素,每个tag子元素都定义一个标签。通常我们可以到Web容器下复制一个标签库定义文件,并在此基础上进行修改即可。例如Tomcat6.0,在webapps\examples\WEB-INF\jsp2路径下包含了一个jsp2-example-taglib.tld文件,这就是示范用的标签库定义文件。 将该文件复制到Web应用的WEB-INF/路径,或WEB-INF的任意子路径下,并对该文件进行简单修改,修改后的helloworld.tld文件代码如下: 1.0 myhelloworld helloWorld org.lxh.taglib.HelloWorldTag empty 问题1: 为什么要用TagSupport与BodyTagSupport的区别主要是标签处理类是否需要与标签体交互,如果不需要交互的就用TagSupport,否则就用BodyTagSupport。 交互就是标签处理类是否要读取标签体的内容和改变标签体返回的内容。用TagSupport实现的标签,都可以用BodyTagSupport来实现,因为BodyTagSupport继承了TagSupport而不去实现IterationTag接口的,因为BodyTagSupport继承了TagSupport类,并且该类已经实现了IterationTag接口并且实现了功能. doStartTag()方法在标签开始时执行,要记住每次都要对类进行初始化,避免上一次的遗留数据对操作造成影响。然后判断是否有数据需要处理,如果有,则返回EVAL_BODY_INCLUDE开始处理标签里的内容,如果没有,返回 EVAL_PAGE跳过标签内容执行标签下面的内容。 doAfterBody()方法在每次处理完标签内部内容后执行,判断循环是否已经结束,如果可以继续循环,返回EVAL_BODY_AGAIN用循环得到新的数据再次处理标签内部内容,如果循环结束就返回EVAL_PAGE结束标签。 二、自定义JSP标签的处理过程: 1.在JSP中引入标签库:   2.在JSP中使用标签库标签 3.Web容器根据第二个步骤中的prefix,获得第一个步骤中声明的taglib的uri属性值 4.Web容器根据uri属性在web.xml找到对应的元素 5.从元素中获得对应的元素的值 6.Web容器根据元素的值从WEB-INF/目录下找到对应的.tld文件 7.从.tld文件中找到与tagname对应的元素 8.凑元素中获得对应的元素的值 9.Web容器根据元素的值创建相应的tag handle class的实例 10. Web容器调用这个实例的doStartTag/doEndTag方法完成相应的处理 三、创建和使用一个Tag Library的基本步骤: 1.创建标签的处理类(Tag Handler Class) 2.创建标签库描述文件(Tag Library Descrptor File) 3.在web.xml文件中配置元素 4.在JSP文件中引人标签库 四、TagSupport类简介: 1.处理标签的类必须扩展javax.servlet.jsp.TagSupport. 2.TagSupport类的主要属性: A.parent属性:代表嵌套了当前标签的上层标签的处理类 B.pageContex属性:代表Web应用中的javax.servlet.jsp.PageContext对象 3.JSP容器在调用doStartTag或者doEndTag方法前,会先调用setPageContext和setParent方法,设置pageContext和parent。因此在标签处理类中可以直接访问pageContext变量 4.在TagSupport的构造方法中不能访问pageContext成员变量,因为此时JSP容器还没有调用setPageContext方法对pageContext进行初始化 五、TagSupport处理标签的方法: 1.TagSupport类提供了两个处理标签的方法: public int doStartTag() throws JspException public int doEndTag() throws JspException 2.doStartTag:但JSP容器遇到自定义标签的起始标志,就会调用doStartTag()方法,doStartTag()方法返回一个整数值,用来决定程序的后续流程。 A.Tag.SKIP_BODY:表示跳过了开始和结束标签之间的代码 B.Tag.EVAL_BODY_INCLUDE:表示标签之间的内容被正常执行 C.Tag.EVAL_BODY_BUFFERED :对包含的内容进行解析 3.doEndTag:但JSP容器遇到自定义标签的结束标志,就会调用doEndTag()方法。doEndTag()方法也返回一个整数值,用来决定程序后续流程。 A.Tag.SKIP_PAGE:表示立刻停止执行网页,网页上未处理的静态内容和JSP程序均被忽略任何已有的输出内容立刻返回到客户的浏览器上。 B.Tag.EVAL_PAGE:表示按照正常的流程继续执行JSP网页 4.doAfterTag:遇到标签体执行 A.Tag.EVAL_BODY_AGAIN;// 如果集合中还有对像,则循环执行标签体,对标签体循环处理,(存在于javax.servlet.jsp.tagext.IterationTag接口中) B.Tag.SKIP_BODY 六、创建含有字段的标签: 1.创建标签处理器类FieldTag package com.able.tag; import java.io.IOException; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.TagSupport; public class FieldTag extends TagSupport { private static final long serialVersionUID = 1540529069962423355L; private String field; private Integer count; @Override public int doEndTag() throws JspException { try { JspWriter out = pageContext.getOut(); out.print(field); out.print(count); } catch (IOException e) { e.printStackTrace(); } return super.doEndTag(); } public String getField() { return field; } public void setField(String field) { this.field = field; } public Integer getCount() { return count; } public void setCount(Integer count) { this.count = count; } } 2.在tag.tld文件中天剑tag标签 field com.able.tag.FieldTag empty field true true count true 3.jsp中定义标签: 七、如何创建标签处理类 1、引入必需的资源 import javax.servlet.jsp.*; import javax.servlet.http.*; import java.util.*; import java.io.*; 2、继承TagSupport类并覆盖doStartTag()/doEndTag()方法 3、从ServletContext对象中获取java.util.Properties对象 4、从Properties对象中获取key对应的属性值 5、对获取的属性进行相应的处理并输出结果 创建标签库描述文件(Tag Library Descriptor) 1、标签库描述文件,简称TLD,采用XML文件格式,定义了用户的标签库。TLD文件中的元素可以分成3类: A.标签库元素 B.标签元素 C.标签属性元素 2、标签库元素用来设定标签库的相关信息,它的常用属性有: A.shortname:指定Tag Library默认的前缀名(prefix); B.uri:设定Tag Library的惟一访问表示符。 3、标签元素用来定义一个标签,它的常见属性有: A.name:设定Tag的名字; B.tagclass:设定Tag的处理类; C.bodycontent:设定标签的主体(body)内容。 1)empty:表示标签中没有body; 2)JSP:表示标签的body中可以加入JSP程序代码; 3)tagdependent:表示标签中的内容由标签自己去处理。 4、标签属性元素用来定义标签的属性,它的常见属性有: A.name:属性名称; B.required:属性是否必需的,默认为false; C.rtexprvalue:属性值是否可以为request-time表达式,也就是类似于< %=…% >的表达式。 八、在Web应用中使用标签 1、如果Web应用中用到了自定义JSP标签,则必须在web.xml文件中加入元素,它用于声明所引用的标签所在的标签库 /sometaglib /WEB-INF/someTLD.tld 2、设定Tag Library的惟一标示符,在Web应用中将根据它来引用Tag Libray; 3、指定和Tag Library对应的TLD文件的位置; 4、在JSP文件中需要加入 /WEB-INF/test.tld /WEB-INF/test.tld 5.2.在JSP中使用此标签 <%@ taglib uri="/testTag" prefix="mytag"%> WEB页面输出结果如下: 自定义标签输出流:Hello,夏中伟! Hi,World! 循环标签体类:ForEach.java  1import java.util.Collection;  2import java.util.Iterator;  3  4import javax.servlet.jsp.JspException;  5import javax.servlet.jsp.tagext.BodyContent;  6import javax.servlet.jsp.tagext.BodyTagSupport;  7  8public class ForEach  extends BodyTagSupport  9{ 10  private String id; 11  private String collection; 12  private Iterator iter; 13  14  public void setCollection(String collection) 15  { 16    this.collection = collection; 17  } 18  public void setId(String id) 19  { 20    this.id = id; 21  } 22  23  //遇到开始标签执行 24  public int doStartTag() throws JspException 25  { 26    Collection coll = (Collection) pageContext.findAttribute(collection); 27    // 表示如果未找到指定集合,则不用处理标签体,直接调用doEndTag()方法。 28    if(coll==null||coll.isEmpty()) return SKIP_BODY; 29    30    iter = coll.iterator(); 31    pageContext.setAttribute(id, iter.next()); 32    // 表示在现有的输出流对象中处理标签体,但绕过setBodyContent()和doInitBody()方法 33    // 这里一定要返回EVAL_BODY_INCLUDE,否则标签体的内容不会在网页上输出显示 34    return EVAL_BODY_INCLUDE; 35  } 36  37  //在doInitBody方法之前执行,在这里被绕过不执行 38  @Override 39  public void setBodyContent(BodyContent arg0) 40  { 41    System.out.println("setBodyContent"); 42    super.setBodyContent(arg0); 43  } 44  //此方法被绕过不会被执行 45  @Override 46  public void doInitBody() throws JspException 47  { 48    System.out.println("doInitBody"); 49    super.doInitBody(); 50  } 51  52  //遇到标签体执行 53  public int doAfterBody() throws JspException 54  { 55    if(iter.hasNext()) 56    { 57      pageContext.setAttribute(id, iter.next()); 58      return EVAL_BODY_AGAIN;// 如果集合中还有对像,则循环执行标签体 59    } 60    return SKIP_BODY;//迭代完集合后,跳过标签体,调用doEndTag()方法。 61  } 62  63  //遇到结束标签执行 64  public int doEndTag() throws JspException 65  { 66    System.out.println("doEndTag"); 67    return EVAL_PAGE; 68  } 69 70}  获取VO属性类:GetProperty.java  1import java.lang.reflect.Method;  2  3import javax.servlet.jsp.JspException;  4import javax.servlet.jsp.tagext.BodyTagSupport;  5  6public class GetProperty extends BodyTagSupport  7{  8  9  private String name; 10  private String property; 11 12  public void setName(String name) 13  { 14    this.name = name; 15  } 16 17  public void setProperty(String property) 18  { 19    this.property = property; 20  } 21 22  @SuppressWarnings("unchecked") 23  public int doStartTag() throws JspException 24  { 25    try 26    { 27      Object obj = pageContext.findAttribute(name); 28      29      if (obj == null) return SKIP_BODY; 30      31      Class c = obj.getClass(); 32      //构造GET方法名字 get+属性名(属性名第一个字母大写) 33      String getMethodName = "get" + property.substring(0, 1).toUpperCase() 34                              + property.substring(1, property.length()); 35      Method getMethod = c.getMethod(getMethodName, new Class[]{}); 36      37      pageContext.getOut().print(getMethod.invoke(obj)); 38      System.out.print(property + ":" + getMethod.invoke(obj) + "t"); 39    } catch (Exception e) 40    { 41      e.printStackTrace(); 42    } 43    return SKIP_BODY; 44  } 45 46  public int doEndTag() throws JspException 47  { 48    return EVAL_PAGE; 49  } 50} 51 52表达式直接访问此类中静态的方法:ELFunction.java 53public class ELFunction 54{ 55 public static int add( int i,int j ) 56 { 57  return i+j; 58 } 59}   写一个测试用的VO类:UserVo.java  1public class UserVo  2{  3  private String name;  4  private String password;  5   6  public String getName()  7  {  8    return name;  9  } 10  public void setName(String name) 11  { 12    this.name = name; 13  } 14  public String getPassword() 15  { 16    return password; 17  } 18  public void setPassword(String password) 19  { 20    this.password = password; 21  } 22}   建好TLD文件tag.tld,放在WEB-INF目录下  1  2  7  8 自定义标签  9 JSTL core 10 1.1 11 firstLabel 12 http://java.sun.com/jsp/jstl/core 13 14 15 16  forEach 17  exercise.taglib.ForEach 18  19  JSP 20  21   id 22   true 23   true 24  25  26   collection 27   true 28   true 29  30 31 32 33 34  getProperty 35  exercise.taglib.GetProperty 36  empty 37  38   name 39   true 40   true 41  42  43   property 44   true 45   true 46  47 48 49 50    51     add 52     exercise.taglib.ELFunction 53     int add(int,int) 54    55 在web.xml文件中配置自定义标签 firstTag /WEB-INF/tag.tld 在jsp文件中使用标签:tag.jsp <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <%@ taglib uri="firstTag" prefix="my"%> <% List list = new ArrayList(); list.add(userVo1); list.add(userVo2); pageContext.setAttribute("voList",list); %> My JSP 'tag.jsp' starting page

This is my JSP page:测试taglib.


自定义迭代标签:

姓名密码

表达式调用类的静态方法:

2+5=${my:add(2,5)} 以上就是小编为大家带来的jsp中自定义Taglib详解全部内容了,希望大家多多支持中文源码网~