Jsp学习(五)

自定义标签

1、标签类型

  • Has body

    有标签体,必须位于开始标记和结束标记之间
    内容包括:自定义标记或核心标记,HTML 文本,标签依赖的主体内容
    比如:<html:submit> OK </html:submit>

  • Has no body

    没有标签体
    比如<html:errors />

2、自定义标签的步骤

  • 创建一个类,用来对标签的行为进行控制

    这个类 继承 javax.servlet.jsp.tagext.SimpleTagSupport 并重写 doTag() 方法

  •  创建标签库描述符 ( Tag Library Descriptor ):

    标签库描述符是个 XML 文件,一般被放在 WEB-INF 目录下即可
    标签库描述符 的扩展名不是 .xml 而是 .tld

  • 在页面上使用标签

    导入标签库:uri 用于指定tld 中<uri> 中的字符串值,prefix 用于指定标签的前缀,这个名称任意取

<%@ taglib prefix = "m" uri = "http://www.ecut/tags"%>

    使用标签:其中tagPrefix 要与taglib 中的prefix 的值写一致,而tagName 就是tld 文件中<tag> 内部<name> 标签内部的字符串值

<tagPrefix:tagName />

3、测试案例

  • 不带属性、不带标签体 的自定义标签: HelloTag
package ecut.tags;

import java.io.IOException;

import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.SimpleTagSupport;
/*创建一个类,用来对标签的行为进行控制
这个类 继承 javax.servlet.jsp.tagext.SimpleTagSupport 并重写 doTag() 方法*/
public class HelloTag extends SimpleTagSupport {

    @Override
    public void doTag() throws JspException, IOException {
        
        JspContext jspContext = this.getJspContext();
        
        JspWriter out = jspContext.getOut();
        // 这个方法由容器调用。 所有标签逻辑,迭代,标签体的处理等都放在这个方法中。
        out.println( "<div style='border:1px solid blue;text-align:center;padding:5px 5px ;'>" );
        out.println( "hello" );
        out.println( "</div>" );
        
    }

}

标签库描述符m.tld

<?xml version="1.0" encoding="UTF-8"?>

<taglib xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
    version="2.1">
    <!-- short-name建议所采用的简称(prefix),具体用那个简称以jsp页面中prefix为准 -->
    <!-- uri 唯一 -->
    <tlib-version>1.0</tlib-version>
    <short-name>m</short-name>
    <uri>http://www.ecut/tags</uri>

    <!-- 定义一个标签: 没有属性、不带标签体 -->
    <tag>
        <name>hello</name>
        <tag-class>ecut.tags.HelloTag</tag-class>
        <!-- 必须有body-content元素 -->
        <body-content>empty</body-content>
    </tag>
</taglib>

<tag>各子元素的意义与作用
<description> 可选,标签的描述信息
<name> 必需,定义JSP页面引用的标签名称(标签后缀)
<tag-class> 必需,标识实现标签处理类的完全限定名(含包名的类名)
<body-content> 必需,告诉容器如何处理标签开始和结束之间的内容
<body-content> 取值可以是empty 、scriptless 、tagdependent 、JSP
  empty : 不允许任何内容出现在标签体内(用于定义没有标签体的标签)
  scriptless : 允许标签中有JSP 内容,但不能包含<% ... %> 和<%= ... %> 之类
  tagdependent : 允许此标签像其主体一样有任何类型的内容
    » 但是这些内容根本不会被处理,并会完全忽略
    » 由标签处理类开发人员来决定访问这些内容,并对其进行处理
    » 比如其中包含一个允许JSP 开发人员执行的SQL 语句
JSP : 允许在标签体中放置JSP 内容

在index.jsp上使用标签

<%@ page language = "java" pageEncoding = "UTF-8" %>
<%@ page contentType = "text/html; charset= UTF-8"%>
<!-- 导入标签库 -->
<%@ taglib prefix = "m" uri = "http://www.ecut/tags"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>自定义标签</title> </head> <body> <!--使用标签 --> <m:hello></m:hello> </body> </html>
  • 带有属性的自定义标签: TableTag
package ecut.tags;

import java.io.IOException;

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

public class TableTag extends SimpleTagSupport {
    //getXxx()方法要和标签的属性名一致
    private int rows ;
    private int columns ;
    private String className ;

    @Override
    public void doTag() throws JspException, IOException {
        System.out.println( "rows : " + rows  );
        System.out.println( "columns : " + columns  );
        System.out.println( "className : " + className  );
        
        JspContext jspContext = this.getJspContext();
        
        JspWriter out = jspContext.getOut();
        
        out.println( "<table class='" + className + "'>" );
        
        for( int i = 0 ; i < rows ; i++ ){
            out.println( "<tr>" );
            
            for( int j = 0 ; j < columns ; j++){
                out.println( "<td>" );
                out.println( i + " , " + j );
                out.println( "</td>" );
            }
            
            out.println( "</tr>" );
        }
        
        out.println( "</table>" );
        
    }

    public int getRows() {
        return rows;
    }

    public void setRows(int rows) {
        this.rows = rows;
    }

    public int getColumns() {
        return columns;
    }

    public void setColumns(int columns) {
        this.columns = columns;
    }

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

}

如果自定义标签包含属性,那么对应的标签类中也要有相应的属性,getXxx名称还要完全相同,每个属性都必须有对应的getter 和setter 方法

<?xml version="1.0" encoding="UTF-8"?>

<taglib xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
    version="2.1">
    <!-- short-name建议所采用的简称(prefix),具体用那个简称以jsp页面中prefix为准 -->
    <!-- uri 唯一 -->
    <tlib-version>1.0</tlib-version>
    <short-name>m</short-name>
    <uri>http://www.ecut/tags</uri>
  <!-- 定义一个带有属性不带标签体的标签 -->
    <tag>
        <name>table</name>
        <tag-class>ecut.tags.TableTag</tag-class>
        <body-content>empty</body-content>

        <!-- 定义标签的属性 -->
        <attribute>
            <name>rows</name>
            <!-- 是否必填 -->
            <required>true</required>
            <!--run time expression value 是否可以接受一个运行时值(动态的值) -->
            <rtexprvalue>true</rtexprvalue>
        </attribute>

        <attribute>
            <name>columns</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>

        <attribute>
            <name>className</name>
            <required>false</required>
            <rtexprvalue>false</rtexprvalue>
        </attribute>

    </tag>
</taglib>

<attribute> 标签中各个子元素的意义及作用
<name> 必需,定义属性名称
  严格区分大小写,与Tag Handler Class 里的getter 和setter 对应
<required> 可选,指定是必须始终提供该属性
  false 是默认值,表示并不是一定要提供该属性
  true 是可选值之一,表示必须始终提供该属性
<rtexprvalue> 可选,Runtime Expression Value指出属性值是一个动态确定的值还是一个固定的值
  true 表示可以接受运行时的表达式的值,表达式可以是 JSP 表达式,也可以是 EL 表达式
       false 表示不可以接受表达式的值,因此在使用时必须显式指定具体的值

<%@ page language = "java" pageEncoding = "UTF-8" %>
<%@ page contentType = "text/html; charset= UTF-8"%> <!-- 导入标签库 -->
<%@ taglib prefix = "m" uri = "http://www.ecut/tags"%>
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>自定义标签</title> <style type="text/css"> .tab { border: 1px solid blue; width: 100%; margin: 20px auto; border-spacing: 10px; } .tab td { border: 1px solid green; height: 30px; text-align: center; vertical-align: middle; } </style> </head> <body> <!--使用标签 --> <m:table rows="3" columns="4" className="tab"></m:table> <% int r = 6 ; pageContext.setAttribute( "c" , 3 ) ; // page scope 中存入一个名称是 c 的值 %> <m:table rows="<%= r %>" columns="${ c }" className="tab"></m:table>
</body>
</html>
 
  • 有属性、有身体 的标签 : ForTag
package ecut.tags;

import java.io.IOException;

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

public class ForTag extends SimpleTagSupport {
    
    private int begin ;
    private int step ;
    private int end ;
    
    private String var ;

    @Override
    public void doTag() throws JspException, IOException {
        
        JspContext jspContext = this.getJspContext();
        
        //JspWriter out = jspContext.getOut();
        
        JspFragment fragment = this.getJspBody(); // 获得 标签体 对应的 对象
        
        for( int i = begin ; i <= end ; i += step ){
            // < var , i > 
            System.out.println( var + " , " + i );
            // 将每次循环中的 i 的值 放入到 page scope ( JspContext 是 PageContext 类的父类 )
            jspContext.setAttribute( var , i ) ; // jspContext.setAttribute( "counter" , i );
            // 执行 JSP 代码片段 ( 标签体 ),如果是null,则会自动将getOut()返回的值传入invoke方法中
            fragment.invoke( null ); 
        }
        
    }

    public int getBegin() {
        return begin;
    }

    public void setBegin(int begin) {
        this.begin = begin;
    }

    public int getStep() {
        return step;
    }

    public void setStep(int step) {
        this.step = step;
    }

    public int getEnd() {
        return end;
    }

    public void setEnd(int end) {
        this.end = end;
    }

    public String getVar() {
        return var;
    }

    public void setVar(String var) {
        this.var = var;
    }

}
<?xml version="1.0" encoding="UTF-8"?>

<taglib xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
    version="2.1">
    <!-- short-name建议所采用的简称(prefix),具体用那个简称以jsp页面中prefix为准 -->
    <!-- uri 唯一 -->
    <tlib-version>1.0</tlib-version>
    <short-name>m</short-name>
    <uri>http://www.ecut/tags</uri>
   <!-- 定义一个带有属性、带有标签体的标签 -->
    <tag>
        <name>for</name>
        <tag-class>ecut.tags.ForTag</tag-class>
        <body-content>scriptless</body-content>

        <attribute>
            <name>begin</name>
            <required>true</required>
            <rtexprvalue>false</rtexprvalue>
        </attribute>

        <attribute>
            <name>step</name>
            <required>true</required>
            <rtexprvalue>false</rtexprvalue>
        </attribute>

        <attribute>
            <name>end</name>
            <required>true</required>
            <rtexprvalue>false</rtexprvalue>
        </attribute>

        <attribute>
            <name>var</name>
            <required>true</required>
            <rtexprvalue>false</rtexprvalue>
        </attribute>

    </tag>

</taglib>
<%@ page language = "java" pageEncoding = "UTF-8" %>
<%@ page contentType = "text/html; charset= UTF-8"%> <!-- 导入标签库 -->
<%@ taglib prefix = "m" uri = "http://www.ecut/tags"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>自定义标签</title> </head> <body>

  <
m:for begin="10" step="10" end="100" var="counter"> <div>${ counter }</div> </m:for>
</body>
</html>

转载请于明显处标明出处

https://www.cnblogs.com/AmyZheng/p/9187672.html

posted @ 2018-06-15 15:50  AmyZheng  阅读(206)  评论(0编辑  收藏  举报