javaweb 自定义标签

来源:互联网 发布:动态头像制作软件 编辑:程序博客网 时间:2024/06/06 12:40

我们一般以如下方式引入一个标签
<%@ 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() –开始标签和结束标签都执行次方法。

原创粉丝点击