JSP自定义标签详解

先看一个例子来作为开胃菜吧。

示例一

jsp页面:

<%@taglib prefix="my" uri="/mytag"%>
<html>
	<head>
		<title>hello</title>
	</head>
	<body>
		<my:hello/>
	</body>
</html>

<my:hello/>用于输出hello

web.xml:

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

这是填写映射,其中mytags.tld文件:

<?xml version="1.0" encoding="UTF-8"?>
<taglib xmlns="http://java.sun.com/xml/ns/javaee" 
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                version="3.0" 
                xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

  <tlib-version>1.0</tlib-version>
  <short-name>chen</short-name>
  <display-name>my tag</display-name>
  <description>this is from mr.chen</description>
  
  <tag>
    <name>hello</name>  
    <tag-class>traditional.HelloTag</tag-class>
    <body-content>empty</body-content>
  </tag>

</taglib>

这是标签描述符文件,其中的HelloTag类:

package traditional;

import java.io.IOException;

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

/*
 * 功能:<my:hello/>输出hello字符
 * */
public class HelloTag implements Tag{
	
	private PageContext pc;
	private Tag parent;

	@Override
	public int doEndTag() throws JspException{
		// TODO Auto-generated method stub
		JspWriter out = pc.getOut();
		try {
			out.write("hello");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return Tag.EVAL_PAGE;
	}

	@Override
	public int doStartTag() throws JspException {
		// TODO Auto-generated method stub
		return Tag.SKIP_BODY;
	}

	@Override
	public Tag getParent() {
		// TODO Auto-generated method stub
		return parent;
	}

	@Override
	public void release() {
		// TODO Auto-generated method stub
	}

	@Override
	public void setPageContext(PageContext pc) {
		// TODO Auto-generated method stub
		this.pc = pc;
	}

	@Override
	public void setParent(Tag tag) {
		// TODO Auto-generated method stub
		this.parent = tag;		
	}
	
}

大功告成。在浏览器地址请求jsp页面就可以看到hello字符串了。

接下来看看一个带属性的max标签的例子:

示例二

package traditional;

import java.io.IOException;

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

public class MaxTag extends TagSupport{
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 4446743607084515654L;
	
	private int num1;
	private int num2;
	
	public int doEndTag() throws JspException{
		int i = num1>num2?num1:num2;
		JspWriter out = this.pageContext.getOut();
		try {
			out.print(i);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return Tag.EVAL_PAGE;
	}
	public int getNum1() {
		return num1;
	}
	public void setNum1(int num1) {
		this.num1 = num1;
	}
	public int getNum2() {
		return num2;
	}
	public void setNum2(int num2) {
		this.num2 = num2;
	}
}

用于求最大值,在浏览器地址中输入:http://localhost:8080/tag/jsp/max.jsp?num1=1&num2=2 可看到2

tld文件:

<?xml version="1.0" encoding="UTF-8"?>
<taglib xmlns="http://java.sun.com/xml/ns/javaee" 
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                version="3.0" 
                xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

  <tlib-version>1.0</tlib-version>
  <short-name>chen</short-name>
  <display-name>my tag</display-name>
  <description>this is from mr.chen</description>
  
  <tag>
    <name>hello</name>  
    <tag-class>traditional.HelloTag</tag-class>
    <body-content>empty</body-content>
  </tag>
  
  <tag>
    <name>max</name>  
    <tag-class>traditional.MaxTag</tag-class>
    <body-content>empty</body-content>
    
    <attribute>
      <name>num1</name>
      <required>true</required>
      <rtexprvalue>true</rtexprvalue>
    </attribute>
    <attribute>
      <name>num2</name>
      <required>true</required>
      <rtexprvalue>true</rtexprvalue>
    </attribute>
  </tag>

</taglib>

max.jsp页面:

<%@taglib prefix="my" uri="/mytag"%>
<%
	int a = Integer.parseInt(request.getParameter("num1"));
	int b = Integer.parseInt(request.getParameter("num2"));
 %>
<html>
	<head>
		<title>max</title>
	</head>
	<body>
		<my:max num1="<%=a %>" num2="<%=b %>"/>
	</body>
</html>

完成。

示例三

再看一个处理标签体的例子:

package traditional;

import java.io.IOException;

import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyTag;
import javax.servlet.jsp.tagext.BodyTagSupport;
import javax.servlet.jsp.tagext.IterationTag;
import javax.servlet.jsp.tagext.Tag;

public class GreetTag extends BodyTagSupport{
	
	/**
	 * 
	 */
	private static final long serialVersionUID = -5083245804167668973L;
	
	private int count = 0;
	
	public int doStartTag(){
		return BodyTag.EVAL_BODY_BUFFERED;
	}
	
	public int doAfterBody(){
		
		if(count < 3){
			count++;
			return IterationTag.EVAL_BODY_AGAIN;
		}
		else{
			return Tag.SKIP_BODY;
		}		
	}
	
	public int doEndTag(){
		JspWriter out = this.bodyContent.getEnclosingWriter();
		try {
			out.println(this.bodyContent.getString());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return Tag.EVAL_PAGE;
	}

}

tld文件增加:

<tag>
    <name>greet</name>  
    <tag-class>traditional.GreetTag</tag-class>
    <body-content>JSP</body-content>
  </tag>

jsp页面:

<%@page pageEncoding="GBK" %>
<%@taglib prefix="my" uri="/mytag"%>
<html>
	<head>
		<title>greet</title>
	</head>
	<body>
		<my:greet>
			欢迎访问
		</my:greet>
	</body>
</html>

ok,这是传统标签的开发。

看完了几个例子,接下来细细分析JSP自定义标签,这里面大有文章,哈哈。

自定义标签实际上是实现了特定接口的类,封装了一些常用的功能,在运行时被相应的代码替换。要编写自己的标签,关键就是编写标签处理器类,一个标签对应一个标签处理器类。以下是在javax.servlet.jsp.tagext包下的标签库的主要类的关系:

JSP自定义标签详解_第1张图片

使用左边编写的标签为传统标签,JSP2.0后可以使用简单标签,即SimpleTag。

Tag接口,实现了Tag接口的标签处理器类的执行流程如下:

JSP自定义标签详解_第2张图片

Tag接口

定义了以下常量:

EVAL_BODY_INCLUDE:作为doStartTag()的返回值,代表输出标签体到JSP页面

SKIP_BODY:作为doStartTag()的返回值,代表跳过标签体

EVAL_PAGE:作为doEndTag()的返回值,代表继续执行余下的页面

SKIP_PAGE:作为doEndTag()的返回值,代表跳过余下的页面

IterationTag接口

增加了一个方法:doAfterTag()用于迭代处理标签体的内容,新增了一个常量:EVAL_BODY_AGAIN,作为doAfterTag()的返回值代表重复执行

BodyTag接口

可以获得标签体执行后的内容做其他的处理

增加了两个方法:

setBodyContent(BodyContent bc)

doInitBody():setBodyContent()执行后被调用

增加了一个常量:

EVAL_BODY_BUFFERED:作为doStartTag返回值,会创建一个BodyContent对象来代表标签体执行后的结果


ok,写完了标签处理器类后还应该写tld文件(标签库描述符),将它放在jar的META-INF下或web应用的WEB-INF下。再在web.xml下填写映射就可以在jsp页面中使用<hello/>了

特别特别注意:

在tomcat4.1之后的版本中默认开启了标签缓冲池(websphere和weblogic并不会这么做),所以执行完标签后并不会执行release()方法(_jspDestroy()时才释放),也就是说同一个jsp页面自定义标签不管使用多少次只会存在一个实例,但也并不是每一个标签都会为其创建一个缓冲池,要根据参数来判断,例如:

<cc:UserInfoTag user=”…” />

<cc:UserInfoTag />

上面例子中由于参数不同就会创建两个标签缓冲池。

ok,以上是传统标签的开发,SimpleTag的开发,后面再写吧。

你可能感兴趣的:(jsp,标签,自定义标签)