`
wangtong40
  • 浏览: 252955 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

JSP自定义标签

阅读更多

8.2    自定义标签简单应用

public class ViewIPTag extends TagSupport {
    public int doStartTag() throws JspException {
        String ip = pageContext.getRequest().getRemoteAddr();
        try {
            pageContext.getOut().write(ip);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return super.doStartTag();
    }}
 


创建XXX.tld标签文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
<taglib>
    <jsp-version>1.0</jsp-version>
    <tlib-version>1.0</tlib-version>
    <short-name>wangtongtaglib</short-name>
    <uri>/wangtongtaglib</uri>
    <tag>
        <name>viewip</name>
        <tag-class>tag.ViewIPTag</tag-class>
        <body-content>empty</body-content>
    </tag>
</taglib>
 



JSP文件中标签的使用:

<wangtong:viewip />
 


JSP引擎调用标签处理器的基本原理
1、    Web容器执行自定义标签开始标记时,会调用标签处理器的doStartTag()。可以通过该方法返回的不同的值来控制后续的行为:
是否执行标签体中的内容。
是直接输出标签体的执行结果,还是将标签体的执行结果输出到一个缓冲区对象中,从而可以让后续的时间方法对标签体的执行结果进行修改和控制其输出。
2、    Web容器执行完开始标记后,执行标签体,标签体执行完成后调用doAfterBody()方法。该方法用于标签体执行完后的行为,这个方法可以返回不同的值来控制是否再次重复执行标签体。
3、    Web容器执行完自定义标签体后,会执行自定义标签的结束标记,此时会执行doEndTag()方法。用于处理遇到结束标记这个事件,通过不同的值来控制Web容器是否执行JSP页面中位于结束标记后面的内容。

8.3    自定义标签API
8.3.1    JspTag接口
是所有自定义标签的父接口,Tag 接口和SimpeTag 是其直接子接口。
8.3.2    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> 标签。

8.3.3    IterationTag接口
IterationTag继承Tag接口,并增加了doAfterBody() 方法和EVAL_BODY_AGAIN 常量。能通知Web容器是否重复执行标签体内容。当调用doAfterBody() 方法返回EVAL_BODY_AGAIN 时,会重复执行标签,知道返回SKIP_BODY,Web容器才会处理标签的结束标记和调用doEndTag()
8.3.4    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接口的实现类BodyTagSupportBodyTagSupport 类实现的BodyTagSupport类的doStartTag方法的返回值为EVAL_BODY_BUFFERED。doAfterBody() 返回值为SKIP_BODY,doEndTag() 返回值为EVAL_PAGE
8.3.5    SimpleTag接口
SimpleTag接口为JSP2.0新增标签接口,在SimpleTag中之定义了一个用于处理标签逻辑的doTag()方法,该方法在Web容器执行自定义标签时调用,而且只调用一次即完成传统标签的是否执行标签体、迭代标签等功能。
SimpleTagSupport类是SimpleTag接口的实现类。
8.4    自定义标签基本使用
8.4.1    Tag接口
1、    Tag接口静态常量EVAL_BODY_INCLUDE、SKIP_BODY、EVAL_PAGE、SKIP_PAGE
2、    方法:setPageContext()、setParent()、doStartTag()、doEndTag()、release()

public void setPageContext(PageContext pc);
    public void setParent(Tag tag);
    public int doStartTag();
    public int doEndTag();
    public void release();
 



8.4.1.1    显示用户信息

public class DisplayUserInfoTag extends TagSupport {
    public int doStartTag() throws JspException {
        HttpSession session = pageContext.getSession();
        String username = (String) session.getAttribute("username");
        if (username != null) {
            return EVAL_BODY_INCLUDE;
        } else {
            return SKIP_BODY;
        }}}
 


Tld文件

<taglib>
    <jsp-version>1.0</jsp-version>
    <tlib-version>1.0</tlib-version>
    <short-name>wangtongtaglib</short-name>
    <uri>/wangtongtaglib</uri>
    <tag>
        <name>displayuserinfo</name>
        <tag-class>tag.DisplayUserInfoTag</tag-class>
<body-content>JSP</body-content>
    </tag>
</taglib>
 



JSP文件

<wangtong:displayuserinfo>
    username:${username}
</wangtong:displayuserinfo>
 



8.4.1.2    是否执行JSP页面内容

public class ValidateTag extends TagSupport {
    @Override
    public int doEndTag() throws JspException {
        HttpServletRequest req = (HttpServletRequest) pageContext.getRequest();
        String referrer = req.getHeader("referer");
        String siteParnt = "http://" + req.getServerName();
        if (referrer != null && referrer.startsWith(siteParnt)) {
            return EVAL_PAGE;
        } else {
            try {
                pageContext.getOut().write("对不起,您访问方式不合法");
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return SKIP_PAGE;
        }}}
 




8.5    自定义标签属性
8.5.1    静态属性应用

public class ValidateTag2 extends TagSupport {
    private String url;
   
    public void setUrl(String url) {
        this.url = url;
    }

    public int doEndTag() throws JspException {
        HttpServletRequest req = (HttpServletRequest) pageContext.getRequest();
        String referrer = req.getHeader("referer");
        String siteParnt = "http://" + req.getServerName();
        if (referrer != null && referrer.startsWith(siteParnt)) {
            return EVAL_PAGE;
        } else {
            try {
                pageContext.forward(url);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return SKIP_PAGE;
        }
    }
}
 


Tld:

<tag>
        <name>validatetag2</name>
        <tag-class>tag.ValidateTag2</tag-class>
        <body-content>empty</body-content>
        <attribute>
            <name>url</name>
            <required>true</required>   
        </attribute>
    </tag>
 


JSP页面

<wangtong:validatetag2 url="error.html" />
 


8.5.2    动态属性值应用
可以在attribute元素的rtexprvalue 子元素指定JSP是否为动态元素。

public class DynamicAttributeValueTag extends TagSupport {
    private Date birthday;

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    public int doStartTag() throws JspException {
        JspWriter out = pageContext.getOut();
        try {
            out.write(DateFormat.getInstance().format(birthday));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }return super.doStartTag();}}
 


    Tld配置文件:

    <tag>
        <name>dynamicAttributeValue</name>
        <tag-class>tag.DynamicAttributeValueTag</tag-class>
        <body-content>empty</body-content>
        <attribute>
            <name>birthday</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>
 


JSP文件:

<wangtong:dynamicAttributeValue birthday="<%=new Date() %>"/>
 



8.5.3    动态属性应用
动态属性指在标签处理器类和TLD文件中没有预先声明的属性,但是在JSP页面去可以为这些标签设置这些属性。实现动态属性必须满足下例条件:
1、    继承javax.servlet.jsp.tagext.DynamicAttributes 接口,实现setDynamicAttribute(url,localName,value) 方法。
2、    在TLD文件中使用<dynamic-attributes> 声明标签支持动态属性
8.6    迭代标签
8.6.1    IterationTag接口
IterationTag接口继承自Tag接口,并增加doAfterBody ()方法和EVAL_BODY_AGAIN 常量。
8.6.2    IterationTag实例

public class IterateTag extends TagSupport {
    private String name;
    private String[] items;
    private int i = 1;
    public void setName(String name) {
        this.name = name;
    }
    public void setItems(String[] items) {
        this.items = items;
    }
    public void setI(int i) {
        this.i = i;
    }
    @Override
    public int doStartTag() throws JspException {
        if (items != null && items.length > 0) {
            pageContext.setAttribute("name", items[0]);
            return EVAL_BODY_INCLUDE;
        } else {
            return SKIP_BODY;
        }
    }
    @Override
    public int doAfterBody() throws JspException {
        if (i < items.length) {
            pageContext.setAttribute(name, items[i]);
            i++;
            return EVAL_BODY_AGAIN;// 循环
        } else {
            return SKIP_BODY;
        }}}

 

 

<tag>
        <name>iterate</name>
        <tag-class>tag.IterateTag</tag-class>
        <body-content>JSP</body-content>
        <attribute>
            <name>name</name>
            <required>true</required>
        </attribute>
        <attribute>
            <name>items</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>
 


JSP:

<%String[] books = { "book1", "book2", "book3" };%>
<wangtong:iterate name="bookname" items="<%=books%>">
    %{name}<br />
</wangtong:iterate>
 



8.7    自定义标签定义JSP脚本变量
8.7.1    指定变量名称

<tag>
        <name>scriptvariableiterate</name>
        <tag-class>tag.IterateTag</tag-class>
        <body-content>JSP</body-content>
        <!-- 指定变量名称 -->
        <variable>
            <name-given>bookname</name-given>
        </variable>
        <attribute>
            <name>name</name>
            <required>true</required>
        </attribute>
        <attribute>
            <name>items</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>
 

 

<wangtong:scriptvariableiterate name="bookname" items="<%=books%>">
    <%=bookname %>
</wangtong:scriptvariableiterate>
 



注:JSP中的bookname变量没有明确声明,时通过tld配置文件的variable 标签进行定义的
8.7.2    指定属性名称

<tag>
        <name>scriptattributeiterate</name>
        <tag-class>tag.IterateTag</tag-class>
        <body-content>JSP</body-content>
        <!-- 指定属性名称 -->
        <variable>
            <name-from-attribute>name</name-from-attribute>
        </variable>
        <attribute>
            <name>name</name>
            <required>true</required>
        </attribute>
        <attribute>
            <name>items</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>
 

 

<wangtong:scriptattributeiterate name="name" items="<%=books%>">
    <%=name %>
</wangtong:scriptattributeiterate>
 


注:在使用name-given对变量进行声明,比较死板,只能使用指定的变量名称,故JSP API中提供了通过的指定属性的方法实现类似机制。需要将name-given修改为name-from-attribute。
8.7.3    Variable子元素含义
Description            表述信息
Name-given            指定一个固定的脚本变量名
Name-form-attribute     通过属性指定变量名称,标签易用性较name-given强
Variable-class             指定脚本变量的java类型
Scope                NESTED  从标签开始到标签结束
                    AT _BEGIN 从标签开始到JSP页面结束
                    AT_END         从标签技术到JSP页面结束
8.7.4    用TagExtraInfo 类定义脚本变量
可以使用TagExtraInfo类替代上面再tld文件中配置variable元素实现定义脚本变量。
TagExtraInfo类在使用时可能需要以下2个类:VariableInfo、TagData。
VariableInfo:用于封装脚本变量的定义信息,并提供JSP页面获得这些脚本变量的定义信息的方法。

public VariableInfo(String varname,String classname,boolean declare,int scope);
 

与variable元素的子元素一一对应。
TagData:用来获取标签的属性及属性值。

public String getAttributeString(String attributeName);
 


TagExtraInfo:JSP引擎通过TagExtraInfo类获得JSP脚本变量的定义信息,它是一个抽象类需要实现

getVariableInfo(TagData data)
 

方法。并且需要在tld文件中及进行注册,使用<tei-class>标签。

public class MyTagExtraInfo extends TagExtraInfo {
    @Override
    public VariableInfo[] getVariableInfo(TagData data) {
        return new VariableInfo[]{
                new VariableInfo(data.getAttributeString("name"),
                        "java.lang.String",
                        true,
                        VariableInfo.AT_BEGIN)
        };
    }
}
 

 

<tag>
        <name>scripttagextrainfoiterate</name>
        <tag-class>tag.IterateTag</tag-class>
        <!-- 指定TagExtraInfo实现类 -->
        <tei-class>tag.MyTagExtraInfo</tei-class>
        <body-content>JSP</body-content>
        <attribute>
            <name>name</name>
            <required>true</required>
        </attribute>
        <attribute>
            <name>items</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>
 

8.7.5    userBean标签的实现

public class UseBeanTag extends TagSupport {
    private String name;
    private String type;
    private String scope;
    private int iScope;

    public void setName(String name) {
        this.name = name;
    }

    public void setType(String type) {
        this.type = type;
    }

    public void setScope(String scope) {
        this.scope = scope;
    }

    public void setIScope(int scope) {
        iScope = scope;
    }

    @Override
    public int doStartTag() throws JspException {
        if ("page".equals(scope)) {
            iScope = pageContext.PAGE_SCOPE;
        } else if ("request".equals(scope)) {
            iScope = pageContext.REQUEST_SCOPE;
        } else if ("session".equals(scope)) {
            iScope = pageContext.SESSION_SCOPE;
        } else if ("application".equals(scope)) {
            iScope = pageContext.APPLICATION_SCOPE;
        }
        try {
            Object obj = Class.forName(type).newInstance();
            pageContext.setAttribute(name, obj, iScope);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return EVAL_BODY_INCLUDE;
    }}

public class UseBeanTagExtraInfo extends TagExtraInfo {

    @Override
    public VariableInfo[] getVariableInfo(TagData data) {
        return new VariableInfo[] { new VariableInfo(data
                .getAttributeString("name"), data.getAttributeString("type"),
                true, VariableInfo.AT_BEGIN) };
    }
}
 

 

<tag>
        <name>useBean</name>
        <tag-class>tag.UseBeanTag</tag-class>
        <tei-class>tag.UseBeanTagExtraInfo</tei-class>
        <body-content>JSP</body-content>
        <attribute>
            <name>name</name>
            <required>true</required>
        </attribute>
        <attribute>
            <name>type</name>
            <required>true</required>
        </attribute>
        <attribute>
            <name>scope</name>
            <required>true</required>
        </attribute>
    </tag>
 
<wangtong:useBean name="date" scope="page" type="java.util.Date"/>
<%=date.getYear()+1900%>year<%=date.getMonth()+1%>month
<%=date.getDate()%>date
 



8.8    处理标签体内容
有时候需要对标签体的执行结果进行修改后再输出,在JSP中定义了一个BodyTag 接口支持该功能。
BodyTag接口继承自IterationTag接口,并增加setBodyContent(),doInitBody() 两个方法和一个常量EVAL_BODY_BUFFERED
当doStartTag()方法返回值为EVAL_BODY_BUFFERED 时,JSP引擎创建BodyContent 对象并以此调用setBodyContent()和doInitBody()方法。然后JSP执行标签体内容,并将执行结果输出到BodyContent对象中,然后调用doAfterBody()。当doAfterBody()返回EVAL_BODY_AGAIN时,继续执行标签体内容,知道返回SKIP_BODY为止。
BodyTag常用方法:

public void setBodyContent(BodyContent content);
public void doInitBody();
 


BodyContent类:继承自JspWriter类,增加用于保护数据的缓冲区。

public abstract String getString();
 


以字符串形式返回BodyContent缓冲区内容

public abstract Reader getReader();
 


    返回一个连接到BodyContent对象缓冲区的Reader对象

public void clearBody();
 


    清空BodyContent对象缓冲区内容

public JspWriter getEnclosingWriter();
 


    得到BodyContent对象关联的JSPWriter对象

public abstract void writeOut(Writer out);
 


将BodyContent对象缓冲区内容写入到指定输出流
8.8.1    BodyTag接口简单应用

public class BodyTag extends BodyTagSupport {
    BodyContent bodyContent;
    @Override
    public int doEndTag() throws JspException {
        String content = bodyContent.getString();// 得到标签体内容
        String newContent = "<a href = 'http://'" + content + "'>" + content
                + "</a>";
        JspWriter out = bodyContent.getEnclosingWriter();// 获取JSPWriter对象
        try {
            out.write(newContent);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return EVAL_PAGE;
    }
    @Override
    public void setBodyContent(BodyContent b) {
        bodyContent = b;
    }}
 

 

<wangtong:bodytag>wangtong</wangtong:bodytag>
 

 

2
0
分享到:
评论

相关推荐

    jsp 自定义标签的使用

    本教程将深入探讨JSP自定义标签的使用,同时结合实例介绍分页和下拉框绑定值的封装。 一、JSP自定义标签基础 1. **定义标签库(Tag Library)**:自定义标签首先需要定义一个TLD(Tag Library Descriptor)文件,它...

    jsp 自定义标签实例

    本实例将深入探讨如何实现一个简单的JSP自定义标签。 首先,自定义标签的实现主要依赖于两个核心概念:Tag接口和TagSupport类。`Tag`接口定义了自定义标签必须实现的方法,如`doStartTag()`和`doEndTag()`,它们...

    jsp自定义标签例子,能在Tomcat下直接运行

    在JSP自定义标签的例子中,我们可以看到这个压缩包文件可能包含了一个完整的示例项目,可以在Apache Tomcat这样的Servlet容器下直接运行。Apache Tomcat是一款开源的Servlet容器,广泛用于部署和运行Java Web应用...

    JSP自定义标签学习笔记

    本篇学习笔记将深入探讨JSP自定义标签的相关概念、创建方法以及实际应用。 一、概述 1.1 使用简单标签机制 JSP自定义标签提供了类似HTML标签的语法结构,通过自定义标签,开发者可以封装复杂的Java代码,使得页面...

    jsp自定义标签报错的问题

    在使用JSP自定义标签时,开发者可能会遇到一些报错问题,这通常涉及到项目结构、类路径设置或自定义标签的编译与打包方式。在本文中,我们将深入探讨这些问题,以及如何解决“JspException”这个特定异常。 首先,...

    jsp自定义标签库实现数据列表显示

    本文将详细讲解如何利用JSP自定义标签库实现数据列表的显示,以及涉及到的相关技术。 首先,`UserListTag.java` 是自定义标签的核心类,它继承了`javax.servlet.jsp.tagext.TagSupport` 或 `javax.servlet.jsp....

    JSP自定义标签之自动完成框

    首先,我们要理解JSP自定义标签的概念。自定义标签是JSP的一种扩展机制,它允许开发者创建自己的标签库,以更加清晰和可维护的方式编写页面。自定义标签的实现通常涉及三个主要部分:标签库描述符(TLD)、标签处理...

    JSP自定义标签之日期显示

    本篇将深入探讨“JSP自定义标签之日期显示”,以及如何通过自定义标签来优雅地处理日期格式化和展示。 首先,我们要理解JSP自定义标签的基本概念。自定义标签是JSP的一种扩展,它不是Java内置的标签,而是由开发者...

    权威实用jsp自定义标签demo<select,checkbox,radio>

    综上所述,“权威实用jsp自定义标签demo,checkbox,radio&gt;”教程旨在帮助开发者掌握如何创建和使用与选择器相关的自定义标签,从而提升JSP开发的效率和质量。通过学习这个教程,你可以了解到自定义标签的核心概念、...

    JSP自定义标签JSP自定义标签

    综上所述,JSP自定义标签提供了一种强大的机制,使得JSP开发者能够创建定制的、可重用的代码片段,提升Web应用的开发效率和质量。通过理解和熟练运用自定义标签,开发者可以更好地组织和管理JSP项目,实现更高效的...

    jsp自定义标签编写的分页

    本教程将深入探讨如何利用JSP自定义标签来编写一个灵活、可扩展的分页系统,该系统不依赖于特定的数据库,具有很高的通用性。 首先,理解JSP自定义标签的工作原理至关重要。自定义标签由三部分组成:标签库描述符...

    jsp自定义标签库注意事项

    【jsp自定义标签库注意事项】 在Java服务器页面(JSP)开发中,自定义标签库是一种强大的工具,它能够帮助开发者创建可重用的代码片段,提高代码的可读性和可维护性。以下是对JSP自定义标签库的详细解释和使用注意...

    jsp权限控制,jsp自定义标签实现

    使用jsp自定义标签的功能实现权限的控制。(如果用户没有某个模块的删除权限,就不现实这个删除按钮) 在整个项目中所有的页面都可以引入自定义的标签去做到权限的控制。 自定义标签文件 删除 可以控制页面中的每...

    JSP自定义标签动态属性支持

    首先,我们需要理解JSP自定义标签的基本结构。自定义标签通常由两部分组成:标签库描述符(TLD)和标签处理类。TLD文件定义了标签的名称、属性、行为等元数据,而标签处理类则实现了这些行为,处理由JSP页面传递过来的...

    jsp自定义标签 jsp自定义标签

    jsp自定义标签jsp自定义标签jsp自定义标签jsp自定义标签

    jsp自定义标签大全.rar

    本资源“jsp自定义标签大全.rar”提供了一套全面的JSP自定义标签的实例和指南,旨在帮助开发者深入理解和应用这一特性。 **JSP自定义标签的基本概念** JSP自定义标签不同于标准动作标签(如&lt;jsp:include&gt;或&lt;jsp:...

    JSP自定义标签实例与详细讲解

    本教程将深入探讨JSP自定义标签的实例与详细讲解。 一、JSP自定义标签概述 JSP自定义标签是类似于HTML标签的自定义组件,但它们提供了更强大的功能,可以封装Java代码,提供复杂的业务逻辑。自定义标签通过TLD(Tag...

    由浅到深详细讲解JSP自定义标签

    本文将深入讲解JSP自定义标签的相关概念、格式、处理过程以及创建和使用自定义标签库的基本步骤。 1. 基本概念: - **标签**:JSP标签是XML元素,用于简化JSP页面,使其更易读且支持多语言版本。标签名和属性区分...

Global site tag (gtag.js) - Google Analytics