• JSP自定义标签(标签处理器 tld文件)


    标签的形式如下,标签处理器就是处理JSP页面中的标签的属性和内容,定义好之后就跟使用JSTL一样

    <标签名 属性名="属性值" 属性名="属性值">
        标签的内容
        <子标签名 属性名="属性值" 属性名="属性值">
            子标签的内容
        </子标签名>
    </标签名>

    经典标签处理器(JSP2.0以前):实现接口Tag、IterationTag、BodyTag的标签处理器都叫做经典标签处理器。

    简单标签处理器(JSP2.0引入):实现接口SimpleTag或者继承类SimpleTagSupport的标签处理器叫做简单标签处理器。

    // 自定义标签的相关接口都在 javax.servlet.jsp.tagext包中
    public interface Tag extends JspTag
    public interface IterationTag extends Tag
    public interface BodyTag extends IterationTag
    public interface SimpleTag extends JspTag
    public class SimpleTagSupport extends java.lang.Object implements SimpleTag  // 提供了接口Simpletag的所有方法的默认实现
    public abstract class JspFragment extends java.lang.Object

    接口simpleTag和支持类SimpleTagSupport中的方法

    // SimpleTag中的方法
    void doTag() throws JspException, java.io.IOException
    void setParent(JspTag parent)
    JspTag getParent()
    void setJspContext(JspContext pc)
    void setJspBody(JspFragment jspBody)
    // SimpleTagSupport中的方法 在SimpleTag基础上又增加了三个
    protected JspFragment getJspBody() 
    protected JspContext getJspContext()
    public static final JspTag findAncestorWithClass(JspTag from, java.lang.Class<?> klass)

    使用自定义标签的过程如下

    (1)浏览器访问JSP页面资源。

    (2)Tomcat将JSP页面翻译成Servlet  --> 编译该Servlet --> 构造类对象 --> 调用_jspService()方法。

    (3)检查JSP文件的taglib指令,检查是否存在相应的tld文件,如果没有会报错。

    (4)根据JSP页面中的标签名<easy:firstTag>在tld文件中找到相应的<tag>标签,并定位到标签处理器如下

    <tag>
        <name>firstTag</name>
        <tag-class>app06a.MyFirstTag</tag-class>
        <body-content>empty</body-content>
     </tag>

    (5)构造标签处理器app06a.MyFirstTag对象,然后调用标签处理器中的相应方法(将标签处理器的声明周期)

    简单标签器的生命周期(即执行过程)如下: setJspContext(jspContext)和doTag()方法时一定会被JSP容器调用的

    (1)JSP容器调用简单标签处理器的无参构造器并创建它的实例,因此简单标签处理器必须有无参构造器。

    (2)JSP容器调用setJspContext(jspContext)方法,同时传入JspContext对象,该对象中最重要的方法是getOut()方法,其能够返回JspWriter对象,通过JspWriter就可以把相应返回前端了。通常情况下,要把传入的JspContext赋值给类的成员变量方便以后使用。

    public void setJspContext(JspContext jspContext)

    (3)如果标签处理器的定制标签嵌套再另一个自定义标签中,JSP容器就会调用setParent(jspTag)方法

    public void setParent(JspTag parent)

    (4)JSP容器调用该标签中所定义的每个属性的setter方法

    (5)如果需要处理页面内容,JSP容器还会调用接口SimpleTag的setJspBody(jspBody)方法,把由JspFragment封装的页面内容传过来。如果没有页面内容则不会调用该方法。

    public void setJspBody(JspFragment jspBody)

    (6)JSP容器调用doTag()方法,所有变量在doTag方法返回时进行同步。doTag()方法只会执行一次,业务逻辑、遍历及页面内容操作都是在这里实现。

    创建自定义标签的三步骤:

    第一步:编写标签处理器,标签处理器就是一个实现了标签接口的Java类。在编写标签处理器时需要servlet-api.jar和jsp-api.jar这两个文件,不过Tomcat自带了,可以在Tomcat的lib目录下找到。
    第二步:在标签库描述器中注册标签。标签库描述器是以.tld结尾的XML文件,该文件必须放在WEB-INF目录下(避免浏览器直接访问)。
    第三步:使用自定义标签。需要用到<%@ taglib uri="uri" prefix="prefix" %>指令,其uri属性时标签库描述器的绝对路径或者相对路径,如果使用jar包中的标签库,就必须使用绝对路径了。

    实例一

    编写简单标签处理器

    package app06a.customTag;
    
    import java.io.IOException;
    
    import javax.servlet.jsp.JspContext;
    import javax.servlet.jsp.JspException;
    import javax.servlet.jsp.JspWriter;
    import javax.servlet.jsp.tagext.JspFragment;
    import javax.servlet.jsp.tagext.JspTag;
    import javax.servlet.jsp.tagext.SimpleTag;
    
    public class MyFirstTag implements SimpleTag {  // 简单标签处理器必须有无参构造器,此处使用默认的无参构造器
        JspContext jspContext;
        
        @Override
        public void doTag() throws JspException, IOException {  // JSP容器一定会调用该方法 
            System.out.println("doTag");
            JspWriter out = jspContext.getOut();
            out.println("This is my first tag.");
        }
    
        @Override
        public JspTag getParent() {  
            System.out.println("getparent");
            return null;
        }
    
        @Override
        public void setJspBody(JspFragment jspFragment) {  // 如果需要处理页面内容,JSP容器会调用该方法,且在调用doTag()方法之前
            System.out.println("setJspBody");
    
        }
    
        @Override
        public void setJspContext(JspContext jspContext) {  // JSP容器一定会调用该方法, 且首先调用该方法
            this.jspContext = jspContext;
            System.out.println("setJspContext");
        }
    
        @Override
        public void setParent(JspTag arg0) {  // 如果自定义标签被另一个自定义标签所嵌套时,JSP容器调用该方法,且在调用doTag()方法之前
            System.out.println("setParent");
        }
    }

    编写标签库处理文件

    <?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>
      <description>Simple tag example</description>
      <tlib-version>1.0</tlib-version>
      <jsp-version>1.0</jsp-version>
      <short-name>My First taglib Example</short-name>
      <tag>
        <name>firstTag</name>
        <tag-class>app06a.customTag.MyFirstTag</tag-class>
        <body-content>empty</body-content>
      </tag>
    </taglib>

    JSP页面中使用自定义标签

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    <%@ taglib uri="/WEB-INF/firstTag.tld" prefix="easy" %> <%-- 引入自定义标签描述库文件 --%>
    
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>Test my first tag</title>
    </head>
    <body>
        Hello <br />
        <easy:firstTag></easy:firstTag>  <!-- 使用自定义标签 -->
    </body>
    </html>

    测试结果

    实例二 处理属性 继承类SimpletagSupport  

    编写简单标签处理器

    package app06a.customTag;
    
    import java.io.IOException;
    import java.util.StringTokenizer;
    
    import javax.servlet.jsp.JspContext;
    import javax.servlet.jsp.JspException;
    import javax.servlet.jsp.JspWriter;
    import javax.servlet.jsp.tagext.SimpleTagSupport;
    
    public class DataFormatterTag extends SimpleTagSupport {
        private String header;
        private String items;
        
        public void setHeader(String header) {  //JSP容器调用,并且在调用doTag()之前
            this.header = header;
        }
        public void setItems(String items) {
            this.items = items;
        }
        
        @Override
        public void doTag() throws IOException, JspException {  // JSP容器调用,
            JspContext jspContext = getJspContext();
            JspWriter out = jspContext.getOut();
            out.println("<table style='border:1px solid green'>");
            out.println("<tr><td><span style='font-weight:bold'>" + header + "</span></td><tr>");
            StringTokenizer tonkenizer = new StringTokenizer(items, ",");
            while (tonkenizer.hasMoreTokens()) {
                String token = tonkenizer.nextToken();
                out.println("<tr><td>" + token + "</td></tr>");
            }
            out.println("</table>");
        }
    }

    编写标签库处理文件

    <?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>
      <description>Simple tag example</description>
      <tlib-version>1.0</tlib-version>
      <jsp-version>1.0</jsp-version>
      <short-name>My First taglib Example</short-name>
      
      <tag>
        <name>firstTag</name>
        <tag-class>app06a.customTag.MyFirstTag</tag-class>
        <body-content>empty</body-content>
      </tag>
      
      <tag>
        <name>dataFormatter</name>
        <tag-class>app06a.customTag.DataFormatterTag</tag-class>
        <body-content>empty</body-content>
        <attribute>  <!-- 属性 -->
          <name>header</name>    
          <required>true</required>
        </attribute>
        <attribute>
          <name>items</name>
          <required>true</required>
        </attribute>
      </tag>
    </taglib>

    JSP页面中使用自定义标签

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    <%@ taglib uri="/WEB-INF/firstTag.tld" prefix="easy" %>  <%-- 指定标签库描述文件 --%>
    
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>Testing DataFormatterTag</title>
    </head>
    <body>
      <easy:dataFormatter header="States" items="Alabama,Alaska,Georgia,Florida" /> <!-- 该标签中有两个属性 -->
      <br />
      <easy:dataFormatter header="Country" >
        <jsp:attribute name="items">  <!-- 使用JSP动作给标签中的属性赋值 -->
          IS,UK,Canada,Korea
        </jsp:attribute>
      </easy:dataFormatter>
    </body>
    </html>

    测试

     实例三 访问标签内容

    在SimpleTag中,可以通过JSP容器传入的JspFragment对象来访问标签内容。JSP片段的定义不能包含脚本或者脚本表达式,只能是文本模板或者JSP标准节点。

    JspFragment类中有两个方法

    public abstract JspContext getJspContext()  // 返回这个JspFragment关联的JspContext对象
    public abstract void invoke(java.io.Writer out) throws JspException,  java.io.IOException  
    // 执行标签的内容,然后通过指定的Writer对象将其直接输出,
    // 如果把null传入invoke()方法中,那么这个Writer将会被JspFragment关联的JspContext对象中的getOut()方法返回的JspWriter对象所接管。

    编写简单标签处理器

    package app06a.customTag;
    
    import java.io.IOException;
    
    import javax.servlet.jsp.JspContext;
    import javax.servlet.jsp.JspException;
    import javax.servlet.jsp.JspWriter;
    import javax.servlet.jsp.tagext.JspFragment;
    import javax.servlet.jsp.tagext.SimpleTagSupport;
    
    public class SelectElementTag extends SimpleTagSupport {
        private String[] countries = {"Australia", "Brazil", "China", "Japan" };
        
        @Override
        public void doTag() throws IOException, JspException {
            JspContext jspContext = getJspContext();
            JspWriter out = jspContext.getOut();
            JspFragment fragment = getJspBody();
            
            out.println("<select>");
            for (int i = 0; i < 4; i++) {
                jspContext.setAttribute("value", countries[i]);
                jspContext.setAttribute("text", countries[i]);
                fragment.invoke(null);
            }
            out.println("</select>");
        }
    }

    编写标签库处理文件

    <?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>
      <description>Simple tag example</description>
      <tlib-version>1.0</tlib-version>
      <jsp-version>1.0</jsp-version>
      <short-name>My First Taglib Example</short-name>
      
      <tag>
        <name>select</name>
        <tag-class>app06a.customTag.SelectElementTag</tag-class>
        <body-content>scriptless</body-content>
      </tag>
    </taglib>

    JSP页面中使用自定义标签

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    <%@ taglib uri="/WEB-INF/mytags.tld" prefix="easy" %>
    
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>Testing SelectElementFormatTag</title>
    </head>
    <body>
        <easy:select>
            <option value="${value }">${text }</option>  <!-- 使用EL表达式 -->
        </easy:select>
    </body>
    </html>

    测试结果

    发布自定义标签

    在tld文件中添加<uri>元素

    将自定义的标签处理器和标签库描述文件打包到JAR包中

    使用时,将JAR包放到应用的WEB/lib目录下,在使用的时候,任何使用自定义标签的JSP页面都要使用这个标签库描述器中定义的uri

     

    可以将整个应用打包,使用时放到应用的WEB/lib目录下

  • 相关阅读:
    数据结构_线性结构
    多线程01_基础
    操作系统05_文件管理
    解析静态内部类的使用目的与限制(转)
    mysql去除重复记录案例
    mysql 索引使用策略及优化
    mysql 索引数据结构及原理
    mysql 索引的简单使用
    当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法
    14 线程间协作的两种方式:wait、notify、notifyAll和Condition
  • 原文地址:https://www.cnblogs.com/0820LL/p/9880374.html
Copyright © 2020-2023  润新知