【自定义标签开发】03-自定义标签功能概述

自定义标签的功能拓展:

开发人员在编写JSP页面时,经常还需要在页面中引入一些逻辑,例如:
1.控制jsp页面某一部分内容是否执行。
2.控制整个jsp页面是否执行。
3.控制jap页面内容重复执行。
4.修改jsp页面内容输出。
自定义标签除了可以移除jsp页面代码外,它也可以实现以上功能。

上面4句话对应什么意思呢?我们使用实例说明一下(一下使用的是struts和jstl标签做例子):
1.控制jsp页面某一部分内容是否执行。
例如在页面中,我们希望有一些页面代码只有有权限的人才可以看得到,我们就可以使用自定义标签来完成这个操作:
<s:if test="user!=null">
   欢迎您!<s:property value="user,name"/>
</s:if>

2.控制整个jsp页面是否执行。
我们可以根据用户是不是有权限,来确定是否将整个页面给用户看
<s:if test="#session.SYS_USER!=null">
   <html>
      <head></head>
      <body>
          页面主代码......
      </body>
   </html>
</s:if>

3.控制jap页面内容重复执行。
比如让一段内容输出5遍:
<c:forEach var="i" begin="1" end="5">
   Item <c:out value="${i}"/><p>
</c:forEach>

结果
Item 1
Item 2
Item 3
Item 4
Item 5

4.修改jsp页面内容输出。
可以根据session是否有登录信息,而修改相应的登录信息:
<h2>登录状态:</h2>
<s:if test="#session.SYS_USER!=null">
    您已登录!
</s:if><s:else>
    您未登录!
</s:else>

我们下面就使用自定义标签来实现这四个功能。
1.使用标签控制页面内容是否输出实例
首先我们要开发“heddin”标签,然后让这个HelloWorld在jsp页面中不显示。
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@taglib uri="http://blog.csdn.net/acmman" prefix="zyg" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>使用标签控制页面内容是否输出</title>
  </head>
  
  <body>
     <zyg:heddin>
         HelloWorld!
     </zyg:heddin>
  </body>
</html>

首先说一下Tag接口的doStartTag()方法,它有一个int的返回值,如果想要处理标签体中的数据,就返回int型的“EVAL_BODY_INCLUDE”,如果不想处理,就返回“SKIP_BODY”。

(注意:Tag接口中定义了四个常量,分别是“EVAL_BODY_INCLUDE”、“EVAL_PAGE”、“SKIP_BODY”、“SKIP_PAGE”)

我们接下来为“heddin”标签写一个标签处理器类:
【自定义标签开发】03-自定义标签功能概述_第1张图片

我们重写doStartTag()方法,返回“EVAL_BODY_INCLUDE”参数:
package org.zyg.web.tag;

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

public class HeddinTag extends TagSupport {

	@Override
	public int doStartTag() throws JspException {
		
		return Tag.EVAL_BODY_INCLUDE;
	}
	
}

然后在zyg.tld中注册这个标签处理器类:
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
    version="2.0">
    
    
    <description>A tag library exercising SimpleTag handlers.</description>
    <tlib-version>1.0</tlib-version>
    <short-name>zyg</short-name>
    <uri>http://blog.csdn.net/acmman</uri><!-- 标签绑定的uri,用于引入 -->
    
    
    <tag>
        <name>viewIP</name><!-- 标签名 -->
		<tag-class>org.zyg.web.tag.ViewIPTag</tag-class>
		<body-content>empty</body-content><!-- 有无标签体(单标签还是成对标签) -->
    </tag>
    
    <tag>
        <name>heddin</name><!-- 标签名 -->
		<tag-class>org.zyg.web.tag.HeddinTag</tag-class>
		<body-content>JSP</body-content><!-- 有无标签体(单标签还是成对标签) -->
    </tag>
    
</taglib>

我们将web重启,然后测试一下:
【自定义标签开发】03-自定义标签功能概述_第2张图片
发现我们是能够看到“HelloWorld”的,然后我们将标签处理库类的返回值换成“SKIP_BODY”:
@Override
public int doStartTag() throws JspException {
	
	return Tag.SKIP_BODY;
}

再重启Web应用,发现已经看不到HelloWorld了。
【自定义标签开发】03-自定义标签功能概述_第3张图片
以上就是使用标签控制页面内容是否输出的实现。

2.控制整个jsp是否输出实例
我们先来了解一下doEndTag()方法,这个方法也有一个返回值,是int类型,这个返回值控制的是“是否显示余下的jsp内容”,其中如果返回值是“EVAL_PAGE”,就执行余下的jsp内容,如果返回值是“SKIP_PAGE”,那么就不再执行余下的jsp代码。

于是我们先编辑一个jsp界面,然后加上我们的自定义标签<zyg:heddinPage/>:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@taglib uri="http://blog.csdn.net/acmman" prefix="zyg" %>

<zyg:heddinPage/>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>控制整个jsp是否输出</title>
  </head>
  
  <body>
     这是我们的jsp整个页面
  </body>
</html>

然后创建一个自定义标签库类:


重写Tag的doEngTag()方法,给它一个“SKIP_PAGE”的返回值:
package org.zyg.web.tag;

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

public class HeddinPageTag extends TagSupport {

	@Override
	public int doEndTag() throws JspException {
		
		return Tag.SKIP_PAGE;
	}
}
然后在zyg.tld中注册这个标签:
<tag>
        <name>heddinPage</name><!-- 标签名 -->
        <tag-class>org.zyg.web.tag.HeddinPageTag</tag-class>
        <body-content>empty</body-content><!-- 有无标签体(单标签还是成对标签) -->
</tag>

然后重启Web项目,访问该页面:
【自定义标签开发】03-自定义标签功能概述_第4张图片
我们右键点击查看源码,发现源码中也是空空如也:

【自定义标签开发】03-自定义标签功能概述_第5张图片

我们将<zyg:heddinPage/>移到中间:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@taglib uri="http://blog.csdn.net/acmman" prefix="zyg" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>控制整个jsp是否输出</title>
  </head>
  <zyg:heddinPage/>
  <body>
     这是我们的jsp整个页面
  </body>
</html>

再次访问页面,我们看到下面的代码是没有的:

说明我们的jsp显示控制是有效的。
想放行的话,就将doEndTag()的返回值置为“EVAL_PAGE”即可,这里不再演示。

3.控制jap页面内容重复执行实例。
我们想让页面中的“哈哈哈,猴赛雷o(^▽^)o”重复执行5次:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@taglib uri="http://blog.csdn.net/acmman" prefix="zyg" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>控制jsp页面内容重复执行</title>
  </head>


  <body>
  
     <zyg:repeat>
         哈哈哈,猴赛雷o(^▽^)o <br/>
     </zyg:repeat>


  </body>
</html>

我们来写<zyg:repeat>这个自定义标签。

这个功能仅仅依靠Tag接口是不可能完成的,所以sun公司又对Tag进行了拓展:


想要迭代就需要其中的IterationTag接口,它在Tag的基础上扩充了一个常量EVAL_BODY_AGAIN和一个方法doAfterBody()。

我们使用IterationTag接口的EVAL_BODY_AGAIN常量和doAfterBody()方法既可以控制jsp页面中内容的重复。

doAfterBody()方法是在“标签体执行”动作之后,以及“结束标签”动作之前执行。如果这个方法返回“EVAL_BODY_AGAIN”常量,这个时候就会再把标签体执行一次,然后继续递归执行doAfterBody()方法。以此类推,只要这个方法返回“EVAL_BODY_AGAIN”常量它都会循环执行标签体内容,直到doAfterBody()方法返回“SKIP_BODY”常量之后才结束循环。

我们下面开始开发这个标签类,因为TagSupport类同时也实现了IterationTag接口,所以我们还是继承TagSupport类:


我们在类中重写doStartTag()方法和doAfterBody()方法:
package org.zyg.web.tag;

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

//控制标签体执行5次
public class RepeatTag extends TagSupport {
	
	int x = 5;
	
	@Override
	public int doStartTag() throws JspException {
		
		return Tag.EVAL_BODY_INCLUDE;
	}

	@Override
	public int doAfterBody() throws JspException {

		x--;
		if(x>0){
			return IterationTag.EVAL_BODY_AGAIN;
		}else{
			return IterationTag.SKIP_BODY;
		}
	}
}

首先让doStartTag()方法返回EVAL_BODY_INCLUDE变量放行,然后在doAfterBody()方法中执行循环操作。

然后我们在zyg.tld中注册这个标签:
<tag>
    <name>repeat</name><!-- 标签名 -->
    <tag-class>org.zyg.web.tag.RepeatTag</tag-class>
    <body-content>JSP</body-content><!-- 有无标签体(单标签还是成对标签) -->
</tag>
然后重新发布一下Web工程,访问页面之后显示:
【自定义标签开发】03-自定义标签功能概述_第6张图片
这就是用自定义标签控制jap页面内容重复执行。


4.用标签修改jsp页面内容实例
开发新的标签将下面的小写字母变为大写:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@taglib uri="http://blog.csdn.net/acmman" prefix="zyg" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>修改jsp页面内容</title>
  </head>
  
  <body>
     <zyg:upper>
         abcdefg
     </zyg:upper>
  </body>
  
</html>

这个时候我们需要BodyTag接口(它实现了Tag和IterTag接口),它是专门管理jsp修改功能的,多了两个量“EVAL_BODY_BUFFERED”和“EVAL_BODY_TAG(过时的)”,和两个方法setBodyContent()和doInitBody()。

首先让doStartTag()方法返回“EVAL_BODY_BUFFERED”,服务器拿到标签体之后,会将标签体使用setBodyContent()方法传给标签处理器类。我们就可以在doEndTag()方法中拿到标签中的内容,修改之后再输出。

我们先来创建这个标签类:


重写doStartTag()方法和doEndTag()方法:
package org.zyg.web.tag;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyContent;
import javax.servlet.jsp.tagext.BodyTag;
import javax.servlet.jsp.tagext.BodyTagSupport;
import javax.servlet.jsp.tagext.Tag;


//修改标签体(把标签体改为大写)
public class UpperTag extends BodyTagSupport {
	
	@Override
	public int doStartTag() throws JspException {
		
		return BodyTag.EVAL_BODY_BUFFERED;
	}
	
	@Override
	public int doEndTag() throws JspException {
		BodyContent bc = this.getBodyContent();  //得到标签体对象
		String content = bc.getString();//得到标签体内容
		content = content.toUpperCase();//将标签体内容变为大写
		
		try {
			this.pageContext.getOut().write(content);
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
		
		return Tag.EVAL_PAGE;
	}
}

然后在zyg.tld文件中注册一下这个标签:
<tag>
    <name>upper</name><!-- 标签名 -->
    <tag-class>org.zyg.web.tag.UpperTag</tag-class>
    <body-content>JSP</body-content><!-- 有无标签体(单标签还是成对标签) -->
</tag>

然后我们重启一下Web应用,测试:
【自定义标签开发】03-自定义标签功能概述_第7张图片
我们的小写英文变成了大写。

我们讲解完了自定义标签的内容,但是,回顾一下这张图:
【自定义标签开发】03-自定义标签功能概述_第8张图片
我们所讲述的是左边的技术,它其实是jsp2.0以前的技术,后来sun公司觉得Tag的学习成本比较高,不利于标签开发技术的推广,于是在jsp2.0的时候他们又定义了SimpleTag接口,单单使用这一个接口,就可以完成左边3个接口完成的事情。

我们现在公司使用的很多框架还是jsp2.0之前的技术,所以我们学习老技术还是很有必要的,这样就会理解老标签的源码。

jsp2.0以前的标签叫“传统标签”,以后的叫“简单标签”
下一次我们就讲解新的“简单标签”。
转载请注明出处:http://blog.csdn.net/acmman/article/details/51083295

你可能感兴趣的:(【自定义标签开发】03-自定义标签功能概述)