zoukankan      html  css  js  c++  java
  • JSP自定义标签

      JSTL是标准规范,符合标准的web容器就可以使用JSTL。然而有些要求无法单靠JSTL的标签来完成,也许是要将既有的HTML元素封装加强,或者是为了与应用程序更紧密地结合。比如,希望有个标签,可以直接从应用程序所自定义的对象中取出信息,而不是通过属性来传递对象或信息。

    1.Tag File

      Tag File是最简单的自定义标签的方式。

      编写一个扩展名为.tag的文件(MyTag.tag),并把它放在WEB-INF/tags下:

    <%@tag description="描述信息" pageEncoding="UTF-8"%>
    <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
    //...

    然户可以在需要使用这个Tag File的JSP中使用这个自定义标签:

    <%@page contentType="text/html" pageEncoding="UTF-8" %>
    <%@taglib prefix="html" tagdir="/WEB-INF/tags" %>
    //...
    <html:MyTag />
    //...

    虽然tagdir可以指定Tag File的位置,但实际上只能指定/WEB-INF/tags或其子文件夹下。

      创建Tag File时,如同HTML中的元素都有一些属性可以设置一样设置自定义标签的属性,方法是通过attribute指令。
      有以下Tag File(header.tag)

    <%@tag description="header 內容" pageEncoding="UTF-8"%>
    <%@attribute name="title"%>
    <head>
    <title>${title}</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head>

    可以如下使用这个Tag File:

    <%@page contentType="text/html" pageEncoding="UTF-8"%>
    <%@taglib prefix="html" tagdir="/WEB-INF/tags" %>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd"
    >

    <html>
    <html:Header title="title info"/>
    <body>
    //...
    </body>
    </html>

    Tag File是可以有自己的主题内容的。比如:在JSP中,除了<body>和</body>之间的内容不同,其他都是相同的,可以编写这样一个Tag File。(Html.tag)

    <%@tag description="HTML 懒人标签" pageEncoding="UTF-8"%>
    <%@attribute name="title"%>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd"
    >

    <html>
    <head>
    <title>${title}</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head>
    <body>
    <jsp:doBody/>
    </body>
    </html>

    可以这样使用它:

    <%@page contentType="text/html" pageEncoding="UTF-8"%>
    <%@taglib prefix="html" tagdir="/WEB-INF/tags" %>
    <html:Html title="title info">
    //...
    </html:Html>

    如果Tag File的标签在使用时有主题内容,默认是不允许有Scriptlet的,因为tag指令的body-content属性默认为scriptless,也就是不可以出现<%%>、<%=%>、

    <%!%>。

    body-content还可以设置为empty或者tagdependent,empty表示一定没有主体内容,也就是说只能以<html:Html />的形式使用标签,而不能以<html:Html><html:Html />的形式。tagdependent表示将主体中的内容当作纯文本输出,不作任何运算或者转译。

    如果你要将自己编写的Tag File打包成jar文件供别人使用,有几个地方需要注意:

    tag文件必须放在jar文件的META-INF/tags下或其子文件夹下。

    需要定义TLD文件。

    TLD文件必须放在jar文件的META-INF/TLDS下。

    比如将前面的两个Tag File打包,则需要定义如下TLD文件:

    <?xml version="1.0" encoding="UTF-8"?>
    <taglib version="2.0" 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 web-jsptaglibrary_2_0.xsd">
    <tlib-version>1.0</tlib-version>
    <short-name>html</short-name>
    <uri>http://openhome.cc/html</uri>
    <tag-file>
    <name>Header</name>
    <path>/META-INF/tags/Header.tag</path>
    </tag-file>
    <tag-file>
    <name>Html</name>
    <path>/META-INF/tags/Html.tag</path>
    </tag-file>
    </taglib>

    接下来进入放置META-INF的文件夹执行如下命令

    jar cvf ../html.jar *
    将生成的html.jar放在web应用的WEB-INF/lib下就可以使用自定义标签了。

    <%@page contentType="text/html" pageEncoding="UTF-8"%>
    <%@taglib prefix="html" uri="http://openhome.cc/html" %>
    <html:Html title="title info">
    </html:Html>

    注意taglib指令的uri属性要对应至TLD文件中的<uri>所设置的名称。

    2.Simple Tag

      通过实现一个与JSTL中的<c:if>标签功能相似的标签来认识Simple Tag的开发过程。

      首先要编写一个标签处理器,这是一个Java类。通过继承javax.servlet.jsp.tagext.SimpleTagSupport来实现,要重写doTag()方法。

    import javax.servlet.jsp.JspException;
    import javax.servlet.jsp.tagext.SimpleTagSupport;

    public class IfTag extends SimpleTagSupport {
    private boolean test;

    @Override
    public void doTag() throws JspException {
    try {
    if(test) {
    getJspBody().invoke(null);
    }
    } catch (java.io.IOException ex) {
    throw new JspException("IfTag 执行错误", ex);
    }
    }

    public void setTest(boolean test) {
    this.test = test;
    }
    }

    如果test属性为true,调用getJspBody()方法,返回一个JspFragment对象,代表<f:if>与</f:if>之间的主体内容。调用JspFragment的invoke()并传入一个null,表示运行<f:if></f:if>之间的主体内容。没有调用invoke(),则主体内容不会运行。

    为了让容器了解<f:if>标签与标签处理器类之间的关系,要定义一个TLD文件。

    <?xml version="1.0" encoding="UTF-8"?>
    <taglib version="2.0" 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 web-jsptaglibrary_2_0.xsd">
    <tlib-version>1.0</tlib-version>
    <short-name>f</short-name>
    <uri>http://openhome.cc/jstl/fake</uri>
    <tag>
    <name>if</name>
    <tag-class>cc.openhome.IfTag</tag-class>
    <body-content>scriptless</body-content>
    <attribute>
    <name>test</name>
    <required>true</required>
    <rtexprvalue>true</rtexprvalue>
    <type>boolean</type>
    </attribute>
    </tag>
    </taglib>

    其中,<required>表示是否一定需要设置这个属性,<rtexprvalue>表示属性是否接受运行时期运算的结果,<type>设置属性的类型。

    使用标签时需要在JSP中使用taglib指令。

    <%@taglib prefix="f" uri="http://openhome.cc/jstl/fake" %>

    接下来将以模仿JSTL的<c:choose>、<c:when>和<c:otherwise>标签,自定义<f:choose>、<f:when>和<f:otherwise>来了解内层标签如何与外层标签沟通。

    CHooseTag.java

    import javax.servlet.jsp.JspException;
    import javax.servlet.jsp.tagext.SimpleTagSupport;

    public class ChooseTag extends SimpleTagSupport {
    private boolean matched;

    @Override
    public void doTag() throws JspException {
    try {
    this.getJspBody().invoke(null);
    } catch (java.io.IOException ex) {
    throw new JspException("ChooseTag 执行错误", ex);
    }
    }

    public boolean isMatched() {
    return matched;
    }

    public void setMatched(boolean matched) {
    this.matched = matched;
    }
    }

    WhenTag.java

    import javax.servlet.jsp.JspException;
    import javax.servlet.jsp.JspTagException;
    import javax.servlet.jsp.tagext.JspTag;
    import javax.servlet.jsp.tagext.SimpleTagSupport;

    public class WhenTag extends SimpleTagSupport {
    private boolean test;

    @Override
    public void doTag() throws JspException {
    try {
    JspTag parent = null;
    if (!((parent = getParent()) instanceof ChooseTag)) {
    throw new JspTagException("必须置于choose标签中");
    }

    if(((ChooseTag) parent).isMatched()) {
    return;
    }

    if(test) {
    ((ChooseTag) parent).setMatched(true);
    this.getJspBody().invoke(null);
    }
    } catch (java.io.IOException ex) {
    throw new JspException("WhenTag 执行错误", ex);
    }
    }

    public void setTest(boolean test) {
    this.test = test;
    }
    }

    Otherwise.java

    import javax.servlet.jsp.JspException;
    import javax.servlet.jsp.JspTagException;
    import javax.servlet.jsp.tagext.JspTag;
    import javax.servlet.jsp.tagext.SimpleTagSupport;

    public class OtherwiseTag extends SimpleTagSupport {
    @Override
    public void doTag() throws JspException {
    try { JspTag parent = null;
    if (!((parent = getParent()) instanceof ChooseTag)) {
    throw new JspTagException("WHEN_OUTSIDE_CHOOSE");
    }

    if(((ChooseTag) parent).isMatched()) {
    return;
    }

    this.getJspBody().invoke(null);
    } catch (java.io.IOException ex) {
    throw new JspException("Error in OtherwiseTag tag", ex);
    }
    }
    }

    定义TLD文件

    <?xml version="1.0" encoding="UTF-8"?>
    <taglib version="2.0" 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 web-jsptaglibrary_2_0.xsd">
    <tlib-version>1.0</tlib-version>
    <short-name>f</short-name>
    <uri>http://openhome.cc/jstl/fake</uri>
    <tag>
    <name>choose</name>
    <tag-class>cc.openhome.ChooseTag</tag-class>
    <body-content>scriptless</body-content>
    </tag>
    <tag>
    <name>when</name>
    <tag-class>cc.openhome.WhenTag</tag-class>
    <body-content>scriptless</body-content>
    <attribute>
    <name>test</name>
    <required>true</required>
    <rtexprvalue>true</rtexprvalue>
    <type>boolean</type>
    </attribute>
    </tag>
    <tag>
    <name>otherwise</name>
    <tag-class>cc.openhome.OtherwiseTag</tag-class>
    <body-content>scriptless</body-content>
    </tag>
    </taglib>

    示例JSP使用自定义标签:

    <%@page contentType="text/html" pageEncoding="UTF-8"%>
    <%@taglib prefix="f" uri="http://openhome.cc/jstl/fake"%>
    <jsp:useBean id="user" class="cc.openhome.User"/>
    <jsp:setProperty name="user" property="*"/>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd"
    >
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>登录页面</title>
    </head>
    <body>
    <f:choose>
    <f:when test="${user.valid}">
    <h1>${user.name}登录成功</h1>
    </f:when>
    <f:otherwise>
    <h1>登录失败</h1>
    </f:otherwise>
    </f:choose>
    </body>
    </html>













      

  • 相关阅读:
    window.print()分页打印
    获取输入框中光标位置
    JavaScript数据结构与算法描述-队列
    .NET中获取IP地址
    记录一次排查C#使用UI Automation获取程序元素的bug
    虚拟机为win server 2012 添加新磁盘
    为halo博客添加ssl证书(配合nginx反向代理)
    初学nginx反向代理
    公告时间轴
    hackthebox-Archetype
  • 原文地址:https://www.cnblogs.com/liuping/p/2229534.html
Copyright © 2011-2022 走看看