JSP JSTL入门 - 自定义标签

1、一个普通的JSP标签如下图所示:

 

2、简单标签

1)定义:

无正文无属性无正文有属性的JSP标签

2)简单标签和正文标签的区别:

3)一个无正文无属性标签的示例:

<mytag:helloworld /> 或 <mytag:helloworld></mytag:helloworld>

4)制作无正文无属性标签

首先要在对应的 java 文件中实现标签处理类

①扩展javax.servlet.jsp.tagext.TagSupport

②重写public int doEndTag()方法(需要抛出JspException异常)

5)无正文无属性标签使用示例

index.jsp(在web/目录下)

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="myfn" uri="/WEB-INF/tld/myfn.tld" %>
<html>
  <head>
    <title>JSTL-自定义无正文标签</title>
  </head>
  <body>
    <myfn:HelloWorld/>
  </body>
</html>

myfn.tld(在web/WEB-INF/tld/目录下)

<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee" version="2.0">
    <tlib-version>1.0</tlib-version>
    <short-name>Myfu</short-name>
<!--        直接输出Hello World!-->
        <tag>
            <name>HelloWorld</name>
            <tag-class>cn.qi.Myfu.MyFunctions</tag-class>
<!--            标签正文为空时为empty-->
            <body-content>empty</body-content>
        </tag>
</taglib>

MyFunctions.java(在src/cn.qi.Myfu/目录下)

package cn.qi.Myfu;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;
import java.io.IOException;

public class MyFunctions extends TagSupport {
    @Override
    public int doEndTag() throws JspException {
        try {
            pageContext.getOut().print("hello");
        } catch (IOException e) {
            // 捕获异常并输出在控制台中
            throw new JspException(e.getMessage());
        }
        return super.doEndTag();
    }
}

 

6)制作无正文有属性标签

①扩展javax.servlet.jsp.tagext.TagSupport

②重写public int doEndTag()并抛出JspException异常

增加类属性 text 及其 Getter 和 Setter 方法

7)无正文有属性标签使用示例

index.jsp(在web/目录下)

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="myfn" uri="/WEB-INF/tld/myfn.tld" %>
<html>
  <head>
    <title>JSTL-自定义无正文标签</title>
  </head>
  <body>
      <myfn:printString text="hehe"/>
  </body>
</html>

myfn.tld(在web/WEB-INF/tld/目录下)

<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee" version="2.0">
    <tlib-version>1.0</tlib-version>
    <short-name>Myfu</short-name>
    <tag>
        <name>printString</name>
        <tag-class>cn.qi.Myfu.MyFunctions</tag-class>
        <body-content>empty</body-content>
        <attribute>
            <name>text</name>
            <required>true</required>
<!--            从页面里进行传递-->
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>
</taglib>

MyFunctions.java(在src/cn.qi.Myfu/目录下)

package cn.qi.Myfu;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;
import java.io.IOException;

public class MyFunctions extends TagSupport {
    private String text;

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    @Override
    public int doEndTag() throws JspException {
        try {
            pageContext.getOut().print(text);
        } catch (IOException e) {
            // 捕获异常并输出在控制台中
            throw new JspException(e.getMessage());
        }
        return super.doEndTag();
    }
}

 

3、正文标签

1)定义

正文标签可以对标签的正文进行读取和处理

2)使用示例

定义一个Repeat标签,功能是将正文内容全部转换为大写字母并重复输出count次

①首先在项目目录的src文件夹下创建一个包,包里包含一个java类文件Repeat,例如:

②正文标签处理类需要扩展javax.servlet.jsp.tagext.BodyTagSupport类并重载doAfterBody()方法,例如:

package cn.qi.Repeat;

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

public class Repeat extends BodyTagSupport {
    public int doAfterBody() throws JspException {}
}

③当标签内的正文被系统处理完之后,会调用doAfterBody()方法。如果方法返回EVAL_BODY_AGAIN则系统会循环再处理正文一次,直到该方法返回SKIP_BODY为止。

正文标签状态图:

④在标签处理类中定义属性并填写doAfterBody()方法

⑤在web/WEB-INF(或web/WEB-INF/tld)目录下新建一个tld(标签库描述)文件,标签库描述文件的名称为标签库的前缀,例如在上述目录下新建一个myTag.tld文件:

<?xml version="1.0" encoding="utf-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee" version="2.0">
    <tlib-version>1.0</tlib-version>
    <short-name>myTag</short-name>

    <tag>
        <name>Repeat</name>
        <tag-class>cn.qi.Repeat.Repeat</tag-class>
        <body-content>JSP</body-content>
        <attribute>
            <name>count</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>
</taglib>

<tag>标签内的属性值描述:

name:标签名

tag-class:标签处理类所在的位置

body-content:标签内容的处理方式,其标签体内可以有四种值,分别是:

  • tagdependent:标签体内容直接被写入BodyContent,不被JSP容器解释。
  • JSP:接受所有JSP语法,如定制的或内部的tag、scripts、静态HTML、脚本元素、JSP指令和动作。
  • empty:空标记,即起始标记和结束标记之间没有内容。
  • scriptless:接受文本、EL和JSP动作。

<attribute>标签内是自定义标签的属性

例如上面的tld文件中只有一个属性count,对应着Repeat类中的私有属性count。

<name>标签定义属性名称,<required>标签定义该属性是否必须在标签内使用,<rtexprvalue>标签定义该属性是否能使用表达式。

⑥在JSP页面中使用taglib指令指定自定义标签的前缀和描述文件的位置,例如:

<%@ taglib prefix="myTag" uri="/WEB-INF/tld/myTag.tld" %>

3)完整代码:

index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="myTag" uri="/WEB-INF/tld/myTag.tld" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  <myTag:Repeat count="3">
    This is a test!
  </myTag:Repeat>
  </body>
</html>

myTag.tld

<?xml version="1.0" encoding="utf-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee" version="2.0">
    <tlib-version>1.0</tlib-version>
    <short-name>myTag</short-name>

    <tag>
        <name>Repeat</name>
        <tag-class>cn.qi.Repeat.Repeat</tag-class>
        <body-content>JSP</body-content>
        <attribute>
            <name>count</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>
</taglib>

Repeat.java

package cn.qi.Repeat;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyContent;
import javax.servlet.jsp.tagext.BodyTagSupport;
import java.io.IOException;

public class Repeat extends BodyTagSupport {
    private int count;

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }

    public int doAfterBody() throws JspException {
        try {
            if (count > 0) {
                BodyContent body = getBodyContent();
                JspWriter writer = body.getEnclosingWriter();
                // 从正文中获取字符串
                writer.print(body.getString().toUpperCase());
                body.clearBody();
                count--;
                return EVAL_BODY_AGAIN;
            } else {
                return SKIP_BODY;
            }
        } catch (IOException e) {
            throw new JspException(e.getMessage());
        }
    }
}

 

posted @ 2019-10-16 19:49  Qi-BJ  阅读(253)  评论(0编辑  收藏  举报