javaweb 自定义标签

我们一般以如下方式引入一个标签
<%@ taglib prefix=”c” uri=”http://Java.sun.com/jsp/jstl/core”%>
这时再在jsp中写相对应的标签就行了,那么我们如何定义自己的标签类呢?首先我们需要来了解如下三个类
TagSupport
BodyTagSupport
SimpleTagSupport

为了更好的理解,我们先手写个示例

package com.cmh.tag;

import java.io.IOException;

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

public class MyTagTest extends TagSupport {
      private PageContext pageContext;

      @Override
      public void setPageContext(PageContext pageContext) {
            this.pageContext = pageContext;
      }

      @Override
      public int doStartTag() throws JspException {

            try {
                  pageContext.getResponse().getWriter()
                              .write("这是我写的一大段信息:ABCDEFGHIJKLMNOPQRSTUVWXYZ\n");
            } catch (IOException e) {
                  e.printStackTrace();
                  throw new RuntimeException(e);
            }
            return super.doStartTag();
      }
}

然后我们在Web-INF 文件夹下添加tld文件,如下

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE taglib
  PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
  "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
<taglib>
  <tlib-version>1.0</tlib-version><!-- 代表标签库的版本号 -->
  <jsp-version>1.2</jsp-version><!-- 代表jsp的版本 -->
  <short-name>mtt</short-name><!-- 你的标签库的简称 -->
  <uri>http://vmaxtam.com/mytag</uri><!-- 你标签库的引用uri -->

  <tag>
      <name>mytah</name><!-- 你定义的标签的名称 -->
       <tag-class>com.cmh.tag.MyTagTest</tag-class><!-- 对应的标签处理程序:包名+类名 -->
      <body-content>JSP</body-content><!-- 标签体内容的格式 -->
  </tag>
</taglib>

再在jsp页面下添加我们的标签引用

<%@taglib uri=”http://vmaxtam.com/mytag” prefix=”mytag” %>
好了大功告成
读取标签库的流程

1. 首先jsp会转换为servlet java 代码
2. 当servlet中读到了tag巷的时候,他会去内存中查找是否存在uri标签巷,不存在则抛异常
3. 根据uri地址去查询相应的tld文件是否存在,不存在则抛异常


4. 

实例化标签处理程序,利用生成的对象调用它里面的方法
这里服务器对标签处理程序里的方法也有一定的调用顺序 A)void setPageContext(PageContext pc) –传入pageContext对象
B)void setParent(Tag t) –如果有父标签,传入父标签对象,如果没有,则传入null
C)int doStartTag() –开始执行标签时调用。
D)int doEndTag() –结束标签时调用
E)void release() –释放资源

然而以上的TagSupport只是支持相对简单的包装,并不能获取标签里面的内容,所以这时为了解决这个历史版本的问题,BodyTagSupport就出现了,示package

com.cmh.timpojava.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.BodyContent;
import javax.servlet.jsp.tagext.BodyTag;
import javax.servlet.jsp.tagext.BodyTagSupport;
import javax.servlet.jsp.tagext.Tag;

public class MyTagBody extends BodyTagSupport {
      private PageContext pageContext;

    @Override
    public void setPageContext(PageContext pageContext) {
        this.pageContext = pageContext;
    }

    @Override
    public int doStartTag() throws JspException {

        //返回BodyTag.EVAL_BODY_BUFFERED,表示输出标签体内容
        //返回Tag.SKIP_BODY,表示不输出内容
        return BodyTag.EVAL_BODY_BUFFERED;
        //return Tag.SKIP_BODY;
    }

    @Override
    public int doEndTag() throws JspException {

        //得到BodyContent对象,它包装了标签体里的内容
        BodyContent bodyContent = this.getBodyContent();

        //利用getString方法得到字符串
        String content = bodyContent.getString();

        //改变字符串内容,将小写改为大写
        String change = content.toUpperCase();

        //输出到浏览器
        try {
            this.pageContext.getResponse().getWriter().write("\n"+change);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return Tag.SKIP_PAGE;
    }
}

以获取标签里的内容进行更改了,不过看到上面是不是觉得很是麻烦,写那么多干嘛,这时为了简便优化操作,就诞生了SimpleTagSupport,代码示

package com.cmh.tag;

import java.io.IOException;
import java.io.StringWriter;

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

public class SimpleTag extends SimpleTagSupport {

      private Integer num;

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

      @Override//当遇到标签时就会执行这个方法
    public void doTag() throws JspException, IOException {
            StringWriter writer = new StringWriter();

        //4.2 把标签体内容拷贝到临时的Writer流中
        JspFragment jspBody = this.getJspBody();

        jspBody.invoke(writer);

        //4.3 从临时的Writer流中取出标签体内容
        String content = writer.toString();

        //4.4 改变标签体内容
        content = content.toUpperCase();

        //4.5 把改变后的内容写出到浏览器中
        //jspBody.invoke(null);如果这样写,那么还是输出原来的内容
        this.getJspContext().getOut().write(content+num);
    }
}

文件做相应的更改

<tag>
      <name>simpletag</name>
      <tag-class>com.cmh.tag.SimpleTag</tag-class>
      <body-content>scriptless</body-content>

      <attribute>
          <name>num</name> <!-- 属性 -->
          <required>true</required><!-- 是否必填 -->
          <rtexprvalue>true</rtexprvalue><!-- 是否可以用EL表达式 -->
      </attribute>
  </tag>

记住在tld中body-content有几种类型
JSP: 表示输出的标签体内容可以包含jsp脚本,且可以执行此脚本。此值只能用在传统标签中。
scriptless: 表示输出的标签体内容不能包含jsp脚本,如果包含则报错。
empty:表示没有标签体内容。即是空标签。如果不是空标签,则报错。
tagdependent: 表示输出的标签体内容可以包含jsp脚本。但不执行jsp脚本(直接原样输出)

SimpleTagSupport的执行流程和前面两个有稍许不一样,如下
一)和传统标签一样,得到tag-class字符串,找到标签处理程序类
二)实例化标签处理程序类
三)利用对象调用方法。。。。
和传统标签相比,简单标签调用的方法不相同:
SimpleTag接口的方法执行过程:
1) void setJspContext(JspContext pc) –设置pageContext对象,传入pageContext对象。JspContext是PageContext的父类。在标签处理器类中通过this.getJspContext()方法得到PageContext对象。

2)void setParent(JspTag parent) –传入父标签对象,如果没有父标签,则不调用次方法。通过getParent方法得到父标签对象

3)void setJspBody(JspFragment jspBody) –传入标签体内容。标签体内容封装到JspFragment方法中。通过getJspBody方法得到标签体内容。如果没签体,不调用次方法。

4)void doTag() –开始标签和结束标签都执行次方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值