JSP自定义标签

1.简介

 

标签是一种XML元素,通过标签可以使JSP网页变得简洁并且易于维护。

 

由一系列功能相似、逻辑上互相联系的标签构成的集合称为标签库。

 

标签库描述文件是一个XML文件,这个文件提供了标签库中类和JSP中对标签引用的映射关系。

 

标签处理类是一个Java类,它实现自定义JSP标签的具体功能。

 

2.相关接口和类

 



1)接口JSPTag

 

没有实际方法,用于标识作用

 

2)接口Tag

 

定义了没有内容的标签处理类的一组方法接口以及标签处理的生命周期。

 

void setPageContext(PageContext paramPageContext)

 

设置当前JSP页面的pageContext

 

void setParent(Tag paramTag)

 

设置父级标签,即最接近当前标签的外层标签,不存在则为Null

 

Tag getParent()

 

int doStartTag() throws JspException

 

当标签开始时调用

假如标签库描述文件定义该标签没有标签体,则必须返回SKIP_BODY,

否则可以返回SKIP_BODY或者EVAL_BODY_INCLUDE,

前者将不会处理标签体,后者将标签体的结果输出。

 

int doEndTag() throws JspException 

 

当标签结束时调用

可返回EVAL_PAGE或者SKIP_PAGE

前者表示标签结束后继续执行JSP页面的余下内容,

后者表示标签结束后将不执行JSP页面的余下内容,仅仅是当前页面,不包括外层JSP页面

 

void release()

 

释放资源

 

标签处理过程的生命周期如下图所示:



 

 

3)接口IterationTag

 

新增方法

int doAfterBody()

 

在每次标签体内容处理结束后执行,它将决定是否重新处理标签体,

此时它将返回EVAL_BODY_AGAIN,否则返回SKIP_BODY,然后执行doEndTag()。

 

新的生命周期如下图所示。

 

 

 

4)类TagSupport 

 

--实现的生命周期相关方法

 

public int doStartTag() throws JspException {
      return SKIP_BODY;
}

 

public int doEndTag() throws JspException {
      return EVAL_PAGE;
}

 

public int doAfterBody() throws JspException {
      return SKIP_BODY;
}

 

5)接口BodyTag

 

新增方法

 

当doStartTag()方法返回EVAL_BODY_BUFFERED时,

JSP转译成的JAVA类在标签处理过程中将创建一个BodyContent对象来保存标签体的处理结果,

创建方法为pageContext.pushBody(),此方法将保存之前的out对象,

然后依次调用下列两个方法,标签处理完成后调用pageContext.popBody(),还原out对象为标签处理前的状态。

否则将按照之前的IterationTag生命周期处理。

 

void setBodyContent(BodyContent b)

 

void doInitBody()

 

关于BodyContent

 

String getString()

 

获取BodyContent的String值

 

void writeOut(Writer out)

 

向out输出BodyContent的值

 

新的生命周期如下图所示 

 

6)类BodyTagSupport

 

 

--实现的生命周期相关方法

 

public int doStartTag() throws JspException {
      return EVAL_BODY_BUFFERED;
}

 

public int doEndTag() throws JspException {
      return super.doEndTag();
}

 

public int doAfterBody() throws JspException {
      return SKIP_BODY;
}

 

3.步骤

 

1)没有标签体的标签

 

--extends TagSupport

 

package com.siyuan.tagtest.tagdiv;

import java.io.IOException;
import java.io.Writer;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.Tag;
import javax.servlet.jsp.tagext.TagSupport;

public class SimpleInnerTag extends TagSupport {

	private static final long serialVersionUID = 3036156585358686974L;
	
	private String name;
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		System.out.println("SimpleInnerTag.setName...");
		this.name = name;
	}

	@Override
	public int doAfterBody() throws JspException {
		System.out.println("SimpleInnerTag.doAfterBody...");
		return super.doAfterBody();
	}

	@Override
	public int doEndTag() throws JspException {
		System.out.println("SimpleInnerTag.doEndTag...");
		Writer out = this.pageContext.getOut();
		try {
			out.write("<<end");
		} catch (IOException e) {
			e.printStackTrace();
			throw new JspException(e);
		}
		return super.doEndTag();
	}

	@Override
	public int doStartTag() throws JspException {
		System.out.println("SimpleInnerTag.doStartTag...");
		Writer out = this.pageContext.getOut();
		try {
			out.write("start>>name=" + this.name);
		} catch (IOException e) {
			e.printStackTrace();
			throw new JspException(e);
		}
		return super.doStartTag();
	}

	@Override
	public void release() {
		System.out.println("SimpleInnerTag.release...");
		super.release();
	}

	@Override
	public void setId(String id) {
		System.out.println("SimpleInnerTag.setId...");
		super.setId(id);
	}

	@Override
	public void setPageContext(PageContext pageContext) {
		System.out.println("SimpleInnerTag.setPageContext...");
		super.setPageContext(pageContext);
	}

	@Override
	public void setParent(Tag t) {
		System.out.println("SimpleInnerTag.setParent...");
		super.setParent(t);
	}

	@Override
	public void setValue(String k, Object o) {
		System.out.println("SimpleInnerTag.setValue...");
		super.setValue(k, o);
	}
	
}

 

2)有标签体的标签

 

--extends BodyTagSupport

 

package com.siyuan.tagtest.tagdiv;

import java.io.IOException;
import java.io.Writer;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.BodyContent;
import javax.servlet.jsp.tagext.BodyTagSupport;
import javax.servlet.jsp.tagext.Tag;

public class SimpleOuterTag extends BodyTagSupport {

	private static final long serialVersionUID = 5764792860891484391L;
	
	private String value;

	public String getValue() {
		return value;
	}

	public void setValue(String value) {
		System.out.println("SimpleOuterTag.setValue...");
		this.value = value;
	}

	@Override
	public int doAfterBody() throws JspException {
		System.out.println("SimpleOuterTag.doAfterBody...");
		return super.doAfterBody();
	}

	@Override
	public int doEndTag() throws JspException {
		System.out.println("SimpleOuterTag.doEndTag...");
		Writer out = this.pageContext.getOut();
		try {
			out.write(this.bodyContent.getString());
			out.write("<<<end");
		} catch (IOException e) {
			e.printStackTrace();
			throw new JspException(e);
		}
		return super.doEndTag();
	}

	@Override
	public void doInitBody() throws JspException {
		System.out.println("SimpleOuterTag.doInitBody...");
		super.doInitBody();
	}

	@Override
	public int doStartTag() throws JspException {
		System.out.println("SimpleOuterTag.doStartTag...");
		Writer out = this.pageContext.getOut();
		try {
			out.write("start>>>value=" + this.value);
		} catch (IOException e) {
			e.printStackTrace();
			throw new JspException(e);
		}
		return super.doStartTag();
	}

	@Override
	public BodyContent getBodyContent() {
		return super.getBodyContent();
	}

	@Override
	public JspWriter getPreviousOut() {
		return super.getPreviousOut();
	}

	@Override
	public void release() {
		System.out.println("SimpleOuterTag.release...");
		super.release();
	}

	@Override
	public void setBodyContent(BodyContent b) {
		System.out.println("SimpleOuterTag.setBodyContent...");
		super.setBodyContent(b);
	}

	@Override
	public void setPageContext(PageContext pageContext) {
		System.out.println("SimpleOuterTag.setPageContext...");
		super.setPageContext(pageContext);
	}

	@Override
	public void setParent(Tag t) {
		System.out.println("SimpleOuterTag.setParent...");
		super.setParent(t);
	}
	
}

 

3)标签库描述文件

 

/WEB-INF/testtag.xml

 

<?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>2.3</tlib-version>
	<short-name>t</short-name>
	<uri>/test-tags</uri>
	
	<tag>
		<name>inner</name>
		<tag-class>com.siyuan.tagtest.tagdiv.SimpleInnerTag</tag-class>
		<body-content>empty</body-content>
		<attribute>
	      <name>name</name>
	      <required>false</required>
	    </attribute>
	</tag>
	
	<tag>
		<name>outer</name>
		<tag-class>com.siyuan.tagtest.tagdiv.SimpleOuterTag</tag-class>
		<body-content>JSP</body-content>
		<attribute>
	      <name>value</name>
	      <required>false</required>
	    </attribute>
	</tag>
	
</taglib>

  

4)JSP

 

index.jsp

 

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<%@taglib uri="/test-tags" prefix="t" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'index.jsp' starting page</title>
  </head>
  
  <body>
   Befor SimpleInnerTag<br>
   <t:inner name="SimpleInnerTag"/> <br/>
   After SimpleInnerTag<br>
   <hr>
   Befor SimpleOuterTag<br>
   <t:outer value="SimpleOuterTag">
   	<t:inner name="SimpleInnerTag IN SimpleOuterTag"/>
   </t:outer> <br/>
   After SimpleOuterTag<br>
  </body>
</html>

 

web.xml

 

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
	xmlns="http://java.sun.com/xml/ns/javaee" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  <jsp-config>
  	<taglib>
  		<taglib-uri>/test-tags</taglib-uri>
  		<taglib-location>/WEB-INF/testtag.xml</taglib-location>
  	</taglib>
  </jsp-config>
</web-app>

 

或者

 

index.jsp

 

<%@taglib uri="/WEB-INF/testtag.xml" prefix="t" %>

 

4.运行结果

 

 

 

 

 

 

5.JSP转译后的JAVA类中的相关内容

 

--TOMCAT6

 

private org.apache.jasper.runtime.TagHandlerPool _005fjspx_005ftagPool_005ft_005finner_0026_005fname_005fnobody;
  private org.apache.jasper.runtime.TagHandlerPool _005fjspx_005ftagPool_005ft_005fouter_0026_005fvalue;


  public void _jspInit() {
    _005fjspx_005ftagPool_005ft_005finner_0026_005fname_005fnobody = org.apache.jasper.runtime.TagHandlerPool.getTagHandlerPool(getServletConfig());
    _005fjspx_005ftagPool_005ft_005fouter_0026_005fvalue = org.apache.jasper.runtime.TagHandlerPool.getTagHandlerPool(getServletConfig());

  }

  public void _jspDestroy() {
    _005fjspx_005ftagPool_005ft_005finner_0026_005fname_005fnobody.release();
    _005fjspx_005ftagPool_005ft_005fouter_0026_005fvalue.release();
  }

  public void _jspService(HttpServletRequest request, HttpServletResponse response)
        throws java.io.IOException, ServletException {
            if (_jspx_meth_t_005finner_005f0(_jspx_page_context))
        return;
            if (_jspx_meth_t_005fouter_005f0(_jspx_page_context))
        return;
  }

  private boolean _jspx_meth_t_005finner_005f0(PageContext _jspx_page_context)
          throws Throwable {
    PageContext pageContext = _jspx_page_context;
    JspWriter out = _jspx_page_context.getOut();
    //  t:inner
    com.siyuan.tagtest.tagdiv.SimpleInnerTag _jspx_th_t_005finner_005f0 = (com.siyuan.tagtest.tagdiv.SimpleInnerTag) _005fjspx_005ftagPool_005ft_005finner_0026_005fname_005fnobody.get(com.siyuan.tagtest.tagdiv.SimpleInnerTag.class);
    _jspx_th_t_005finner_005f0.setPageContext(_jspx_page_context);
    _jspx_th_t_005finner_005f0.setParent(null);
    // /index.jsp(28,3) name = name type = java.lang.String reqTime = false required = false fragment = false deferredValue = false expectedTypeName = null deferredMethod = false methodSignature = null
    _jspx_th_t_005finner_005f0.setName("SimpleInnerTag");
    int _jspx_eval_t_005finner_005f0 = _jspx_th_t_005finner_005f0.doStartTag();
    if (_jspx_th_t_005finner_005f0.doEndTag() == javax.servlet.jsp.tagext.Tag.SKIP_PAGE) {
      _005fjspx_005ftagPool_005ft_005finner_0026_005fname_005fnobody.reuse(_jspx_th_t_005finner_005f0);
      return true;
    }
    _005fjspx_005ftagPool_005ft_005finner_0026_005fname_005fnobody.reuse(_jspx_th_t_005finner_005f0);
    return false;
  }

  private boolean _jspx_meth_t_005fouter_005f0(PageContext _jspx_page_context)
          throws Throwable {
    PageContext pageContext = _jspx_page_context;
    JspWriter out = _jspx_page_context.getOut();
    //  t:outer
    com.siyuan.tagtest.tagdiv.SimpleOuterTag _jspx_th_t_005fouter_005f0 = (com.siyuan.tagtest.tagdiv.SimpleOuterTag) _005fjspx_005ftagPool_005ft_005fouter_0026_005fvalue.get(com.siyuan.tagtest.tagdiv.SimpleOuterTag.class);
    _jspx_th_t_005fouter_005f0.setPageContext(_jspx_page_context);
    _jspx_th_t_005fouter_005f0.setParent(null);
    // /index.jsp(32,3) name = value type = java.lang.String reqTime = false required = false fragment = false deferredValue = false expectedTypeName = null deferredMethod = false methodSignature = null
    _jspx_th_t_005fouter_005f0.setValue("SimpleOuterTag");
    int _jspx_eval_t_005fouter_005f0 = _jspx_th_t_005fouter_005f0.doStartTag();
    if (_jspx_eval_t_005fouter_005f0 != javax.servlet.jsp.tagext.Tag.SKIP_BODY) {
      if (_jspx_eval_t_005fouter_005f0 != javax.servlet.jsp.tagext.Tag.EVAL_BODY_INCLUDE) {
        out = _jspx_page_context.pushBody();
        _jspx_th_t_005fouter_005f0.setBodyContent((javax.servlet.jsp.tagext.BodyContent) out);
        _jspx_th_t_005fouter_005f0.doInitBody();
      }
      do {
        out.write("\r\n");
        out.write("   \t");
        if (_jspx_meth_t_005finner_005f1(_jspx_th_t_005fouter_005f0, _jspx_page_context))
          return true;
        out.write("\r\n");
        out.write("   ");
        int evalDoAfterBody = _jspx_th_t_005fouter_005f0.doAfterBody();
        if (evalDoAfterBody != javax.servlet.jsp.tagext.BodyTag.EVAL_BODY_AGAIN)
          break;
      } while (true);
      if (_jspx_eval_t_005fouter_005f0 != javax.servlet.jsp.tagext.Tag.EVAL_BODY_INCLUDE) {
        out = _jspx_page_context.popBody();
      }
    }
    if (_jspx_th_t_005fouter_005f0.doEndTag() == javax.servlet.jsp.tagext.Tag.SKIP_PAGE) {
      _005fjspx_005ftagPool_005ft_005fouter_0026_005fvalue.reuse(_jspx_th_t_005fouter_005f0);
      return true;
    }
    _005fjspx_005ftagPool_005ft_005fouter_0026_005fvalue.reuse(_jspx_th_t_005fouter_005f0);
    return false;
  }

  private boolean _jspx_meth_t_005finner_005f1(javax.servlet.jsp.tagext.JspTag _jspx_th_t_005fouter_005f0, PageContext _jspx_page_context)
          throws Throwable {
    PageContext pageContext = _jspx_page_context;
    JspWriter out = _jspx_page_context.getOut();
    //  t:inner
    com.siyuan.tagtest.tagdiv.SimpleInnerTag _jspx_th_t_005finner_005f1 = (com.siyuan.tagtest.tagdiv.SimpleInnerTag) _005fjspx_005ftagPool_005ft_005finner_0026_005fname_005fnobody.get(com.siyuan.tagtest.tagdiv.SimpleInnerTag.class);
    _jspx_th_t_005finner_005f1.setPageContext(_jspx_page_context);
    _jspx_th_t_005finner_005f1.setParent((javax.servlet.jsp.tagext.Tag) _jspx_th_t_005fouter_005f0);
    // /index.jsp(33,4) name = name type = java.lang.String reqTime = false required = false fragment = false deferredValue = false expectedTypeName = null deferredMethod = false methodSignature = null
    _jspx_th_t_005finner_005f1.setName("SimpleInnerTag IN SimpleOuterTag");
    int _jspx_eval_t_005finner_005f1 = _jspx_th_t_005finner_005f1.doStartTag();
    if (_jspx_th_t_005finner_005f1.doEndTag() == javax.servlet.jsp.tagext.Tag.SKIP_PAGE) {
      _005fjspx_005ftagPool_005ft_005finner_0026_005fname_005fnobody.reuse(_jspx_th_t_005finner_005f1);
      return true;
    }
    _005fjspx_005ftagPool_005ft_005finner_0026_005fname_005fnobody.reuse(_jspx_th_t_005finner_005f1);
    return false;
  }