jsp自定义标签

jsp 自定义标签

传统方式

https://www.cnblogs.com/xdouby/p/7929749.html

(1)自定义标签

传统方式:实现Tag接口 jsp1.1

int doStartTag() throws JspException;

简单方式:实现SimpleTag接口 jsp2.0

void doTag() throws JspException, IOException;

(2)步骤

  • 编写标签处理类

如果jsp在编译阶段发现了自定义标签xx:,就会交给doStartTag()或者 doTag()

  • 编写标签描述符

tld (tag library description)

建议编写:可以仿照其他标签语言(el jstl)的tld文件

<body-content>的值有下面4种:

<xsd:enumeration value="tagdependent"/>

    <xsd:enumeration value="JSP"/>

    <xsd:enumeration value="empty"/>

    <xsd:enumeration value="scriptless"/>


tagdependent:标签体内容直接被写入BodyContent,由自定义标签类来进行处理,而不被JSP容器解释,

如下:

<test:myList>

select name,age from users

</test:myList>

 
JSP:接受所有JSP语法,如定制的或内部的tag、scripts、静态HTML、脚本元素、JSP指令和动作。如:

<my:test>

    <%=request.getProtocol()%>      // ②

</my:test>

具体可参考后面附源码。

 
empty:空标记,即起始标记和结束标记之间没有内容。

下面几种写法都是有效的,

<test:mytag />

<test:mytag uname="Tom" />

<test:mytag></test:mytag>


scriptless:接受文本、EL和JSP动作。如上述②使用<body-content> scriptless </body-content>则报错,具体可参考后面附源码。除了<% %>	<%! %> <%= %>意外的的jsp元素
  • 导入并使用

tld文件应放在WEB-INF或其子目录下面

引入具体的tld文件

uri:定位文件
prefix:前缀,代表文件名
<%@taglib prefix="" uri="" %>

(3)Tag

int doStartTag() throws JspException;
该方法有两个返回值
int SKIP_BODY = 0;	标签体不会被执行
int EVAL_BODY_INCLUDE = 1;	标签体会被执行

int doEndTag() throws JspException;
int SKIP_PAGE = 5;	标签体后的jsp不会被执行
int EVAL_PAGE = 6;	标签体后的jsp会被执行

jsp—servlet:当jsp容器将jsp翻译成.servlet的时候,如果遇到jsp中有标签,就会依次执行setPageContext setParent doStartTag doEndTag release用于解析标签的执行逻辑。

IterationTag

http://tomcat.apache.org/tomcat-5.5-doc/jspapi/javax/servlet/jsp/tagext/IterationTag.html

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JJItDEL6-1624196601074)(http://tomcat.apache.org/tomcat-5.5-doc/jspapi/javax/servlet/jsp/tagext/doc-files/IterationTagProtocol.gif)]

(4)实现

遍历三次

package com.tag;

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

public class MyIteration extends TagSupport {
    //决定重复次数
    private int num;

    public void setNum(int num) {
        this.num = num;
    }

    //    执行标签
    @Override
    public int doStartTag() throws JspException {
        // 先执行标签体一次
        return EVAL_BODY_INCLUDE;
    }

    //    执行标签后
    @Override
    public int doAfterBody() throws JspException {
        num--;
        // 再重复执行一次
        return num > 0 ? EVAL_BODY_AGAIN : SKIP_BODY;
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<!--标签库的头文件-->
<taglib 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 http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
        version="2.0">
    <!--描述-->
    <description>迭代器标签库</description>
    <!--版本-->
    <tlib-version>1.0</tlib-version>
    <!--简称-->
    <short-name>mytaglib</short-name>
    <!--全称-->
    <!--<display-name>MyTagLibrary</display-name>-->
    <!--定位标签库-->
    <uri>http://www.zrm.com</uri>
    <!--自定义标签的相关信息-->
    <tag>
        <!--标签的描述-->
        <description>迭代器标签</description>
        <!--标签名-->
        <name>iteration3</name>
        <!--标签处理类-->
        <tag-class>com.tag.MyIteration</tag-class>
        <!--标签体的类型-->
        <body-content>JSP</body-content>
        <attribute>
            <name>num</name>
            <required>true</required>
        </attribute>
    </tag>
</taglib>
<%@taglib prefix="zrm" uri="http://www.zrm.com" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>循环三次</title>
</head>
<body>
<zrm:iteration3 num="3">
    hello
</zrm:iteration3>
</body>
</html>

(5)BodyTag

如果在标签体显示之前,进行一些额外的操作

查看实现类:Ctrl alt B

int EVAL_BODY_BUFFERED = 2;
是doStartTag()的第三个返回值,代表一个缓冲区
void setBodyContent(BodyContent var1);

如果返回值是EVAL_BODY_BUFFERED,则服务器会自动将标签需要显示的内容放入缓冲区(BodyContent)

BodyContent

获得缓存区数据
public abstract Reader getReader();
public abstract String getString();
输出
public abstract void writeOut(Writer var1) throws IOException;
public JspWriter getEnclosingWriter() {
    return this.enclosingWriter;
}

(6)处理流程

img

(7)转换大写

  • 编写标签类
package com.tag;

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

public class ToUpperCase extends BodyTagSupport {
//    1.告诉程序将原来的hello 变成大写(父类已完成)
//    将doStartTag()的返回值变成EVAL_BODY_BUFFERED才可修改
//    2.获取数据修改

    @Override
    public int doEndTag() throws JspException {

        try {
//        拿到缓冲区的数据
            String content = getBodyContent().getString();
//        修改
            content = content.toUpperCase();
//        输出
            bodyContent.getEnclosingWriter().write(content);
        } catch (IOException e) {
            e.printStackTrace();
        }
//        默认为6,标签执行完成后继续执行后面的jsp元素
        return super.doEndTag();
    }
}
<tag>
    <name>toUpperCase</name>
    <tag-class>com.tag.ToUpperCase</tag-class>
    <body-content>JSP</body-content>
</tag>
<zrm:toUpperCase>
    hello
</zrm:toUpperCase>

简单方式

修改文本通过流

SimpleTag
void doTag() throws JspException, IOException;
集成了传统方式的三个方法
代表一个jsp片段,但是不包含scriptless,由此简单方式的tld文件中 <body-content> 不能是JSP
package javax.servlet.jsp.tagext.JspFragment;
如果要修改显示内容,则要修改此流,调用一次invoke则执行一次标签体
public abstract void invoke(Writer var1) throws JspException, IOException;
获取对象JspFragment
    protected JspFragment getJspBody() {
        return this.jspBody;
    }
package com.tag;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;
import java.io.IOException;

public class MySimpleTagIterator extends SimpleTagSupport {
    private int num;

    public void setNum(int num) {
        this.num = num;
    }

    @Override
    public void doTag() throws JspException, IOException {
        JspFragment jspBody = getJspBody();
        for (int i = 0; i < num; i++) {
            jspBody.invoke(null);
        }
        super.doTag();
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<!--标签库的头文件-->
<taglib 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 http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
        version="2.0">
    <!--描述-->
    <description>简单迭代器标签库</description>
    <!--版本-->
    <tlib-version>1.0</tlib-version>
    <!--简称-->
    <short-name>mysimpletaglib</short-name>
    <!--全称-->
    <!--<display-name>MyTagLibrary</display-name>-->
    <!--定位标签库-->
    <uri>http://www.zrmsimple.com</uri>
    <!--自定义标签的相关信息-->
    <tag>
        <!--标签的描述-->
        <description>简单迭代器标签</description>
        <!--标签名-->
        <name>mySimpleTagIterator</name>
        <!--标签处理类-->
        <tag-class>com.tag.MySimpleTagIterator</tag-class>
        <!--标签体的类型-->
        <body-content>scriptless</body-content>
        <attribute>
            <name>num</name>
            <required>true</required>
        </attribute>
    </tag>
</taglib>
<zrmsimple:mySimpleTagIterator num="3">
    zrm
</zrmsimple:mySimpleTagIterator>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值