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

来源:互联网 发布:sap hana数据库价格 编辑:程序博客网 时间:2024/05/20 14:41
自定义标签的功能拓展:

开发人员在编写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”标签写一个标签处理器类:


我们重写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 {@Overridepublic 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重启,然后测试一下:

发现我们是能够看到“HelloWorld”的,然后我们将标签处理库类的返回值换成“SKIP_BODY”:
@Overridepublic int doStartTag() throws JspException {return Tag.SKIP_BODY;}

再重启Web应用,发现已经看不到HelloWorld了。

以上就是使用标签控制页面内容是否输出的实现。

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 {@Overridepublic 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项目,访问该页面:

我们右键点击查看源码,发现源码中也是空空如也:



我们将<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;@Overridepublic int doStartTag() throws JspException {return Tag.EVAL_BODY_INCLUDE;}@Overridepublic 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工程,访问页面之后显示:

这就是用自定义标签控制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 {@Overridepublic int doStartTag() throws JspException {return BodyTag.EVAL_BODY_BUFFERED;}@Overridepublic 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应用,测试:

我们的小写英文变成了大写。

我们讲解完了自定义标签的内容,但是,回顾一下这张图:

我们所讲述的是左边的技术,它其实是jsp2.0以前的技术,后来sun公司觉得Tag的学习成本比较高,不利于标签开发技术的推广,于是在jsp2.0的时候他们又定义了SimpleTag接口,单单使用这一个接口,就可以完成左边3个接口完成的事情。

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

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