1、自定义标签
JspTag接口:---------是所有自定义标签的父接口,Tag 接口和SimpeTag 是其直接子接口。
A: Tag接口
Tag接口是传统标签的父接口,定义了两个重要方法doStartTag()、doEndTag() ;
四个常量(EVAL_BODY_INCLUDE、SKIP_BODY、EVAL_PAGE、SKIP_PAGE )。
1、调用doStartTag() 方法执行后向Web容器返回常EVAL_BODY_INCLUDE、SKIP_BODY 。
返回EVAL_BODY_INCLUDE 则执行自定义标签的标签体;
返回SKIP_BODY则忽略自定义标签的标签体,直接解释执行自定义标签的结果标记。
2、调用doEndTag() 方法、执行后向Web容器返回常量EVAL_PAGE、SKIP_PAGE 。
返回EVAL_PAGE 则执行JSP页面位于结束标记后面的JSP代码;
返回SKIP_PAGE则忽略JSP页面中位于结束标记后面的所有内容,例如<jsp:forward> 标签。
IterationTag接口
IterationTag继承Tag接口,并增加了doAfterBody() 方法和EVAL_BODY_AGAIN 常量。
能通知Web容器是否重复执行标签体内容。当调用doAfterBody() 方法返回EVAL_BODY_AGAIN 时,
会重复执行标签,直到返回SKIP_BODY,Web容器才会处理标签的结束标记和调用doEndTag() 。
BodyTag接口
BodyTag接口继承自IterationTag 接口,增加2个方法setBodyContent()、doInitBody() 方法和EVAL_BODY_BUFFERED 常量。
当doStartTag()方法返回EVAL_BODY_BUFFERED 常量时,Web容器会创建专门用于捕获标签体运行结果的BodyContent 对象,
然后调用标签处理器的setBodyContent() 将BodyContent 对象传入标签处理器,Web容器将标签体的执行结果写入BodyContent 对象中。
在标签处理器的后续事件方法中,可以通过保存的BodyContent 的对象的引用来获取标签体的执行结果,
然后调用BodyContent对象特有的方法对BodyContent对象的内容进行修改和控制。
注:JSP API提供BodyTag接口的实现类BodyTagSupport 。
BodyTagSupport 类实现的BodyTagSupport类的doStartTag方法的返回值为EVAL_BODY_BUFFERED。
doAfterBody() 返回值为SKIP_BODY,doEndTag() 返回值为EVAL_PAGE 。
B: SimpleTag接口
SimpleTag接口为JSP2.0新增标签接口,在SimpleTag之中定义了一个用于处理标签逻辑的doTag()方法,
该方法在Web容器执行自定义标签时调用,而且只调用一次即完成传统标签的是否执行标签体、迭代标签等功能。
SimpleTagSupport类是SimpleTag接口的实现类。
简单自定义标签实例:
//自定义标签类 public class HtmlTag extends BodyTagSupport{ private static final long serialVersionUID = 1L; private JspWriter out ; private String name; private String pass; private int count ; @Override public int doStartTag() throws JspException { count = 0; out = this.pageContext.getOut(); try { out.write("hello world ! "+name +" "+ pass+"<br/>"); } catch (Exception e) { e.printStackTrace(); } //多次调用时同一个对象,每次都会调用set/get方法复制属性 System.out.println(" this : "+ this); return EVAL_BODY_INCLUDE; } @Override public int doAfterBody() throws JspException { if(count <5){ count ++; return EVAL_BODY_AGAIN; } return SKIP_BODY; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPass() { return pass; } public void setPass(String pass) { this.pass = pass; } }
配置TLD文件:该文件可以放置于WEB-INF目录或者其子目录下面
<?xml version="1.0" encoding = "utf-8"?> <taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"> <tlib-version>1.0</tlib-version> <short-name>mm</short-name> <uri>http://www.mm.org</uri> <tag> <name>html</name> <tag-class>com.liusheng.tag.HtmlTag</tag-class> <body-content>JSP</body-content> <attribute> <name>name</name> <required>true</required> </attribute> <attribute> <name>pass</name> <required>true</required> </attribute> </tag> </taglib>
使用自定义标签
<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%> <%@ taglib prefix="mm" uri="http://www.mm.org" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> </head> <body> <mm:html name="liushegn" pass="12345"> 1111 </mm:html> <mm:html name="zhangsan" pass="34534"> 2222 </mm:html> </body> </html>