自定义标签库

来源:互联网 发布:让人喜欢的女生知乎 编辑:程序博客网 时间:2024/06/07 10:18

1.自定义标签

*步骤:

**编写一个实现Tag接口的Java类,把页面中的java代码移到这个java类中(标签处理器类)

**编写标签库描述符(tld)文件,在tld文件中把标签处理器描述成一个标签。

*作用:

**用于移除JSP页面中的Java代码

**实现代码的重用

**可以使jsp代码更简洁(Jsp2.0的标签扩展API中又增加了SimpleTag接口和其实现类SimpleTagSupport。)

JSP接口图

2.TLD文件元素

每个自定义标签都必须在TLD文件中声明,TLD文件也是XML文件,根元素是,它包含一个或者多个标签,该元素用来声明定制标签。元素中只有元素是必须的,其他都是可选的。

TLD的一些常用属性

这里写图片描述

3.编写第一个自定义标签

实例:编写一个DateTag标签,输出系统时间

eg://1.编写一个DateTag.java类,继承SimpleTagSupport类   public class DateTag extends SimpleTagSupport{//2.override doTag()方法,在该方法中,实现相应的处理逻辑    public void doTag() throws JspException{    PageContext ctx=getJspContext();    JspWriter out=ctx.getOut();    SimpleDateFormat sdf=nw SimpleDateForm("yyyy年MM月dd日");    out.println(sdf.format(new Date()));    }}//3.在.tld文件中描述标签<?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"><tlib-version>1.1</tlib-version><short-name>c</short-name><uri>http:www.intcast.com.cn/mytag1</uri><tag>    <name>date</name>    <tag-class>mytag.DateTag</tag-class>    <body-content>empty</body-content></tag></taglib>//4.将taglib导入标签中(JSP)<%@taglib prefix="c" uri="http:www.intcast.com.cn/mytag1"%><c:date/>

4.自定义标签扩展

自定义标签除了编写JSP页面,还需要在页面中引入一些逻辑,例如:

*控制JSP页面某一部分内容的执行;

*控制整个JSP页面是否执行;

*控制JSP页面内容是否重复执行;

*修改JSP页面内容输出;

*移除JSP页面的java代码。

tld文件中四种标签体类型:

EMPTYJSP (有标签体的情形,在JSP2.0以前使用的)|| scriptless(JSP2.0以后使用的) tagdepentend

eg:1.    jsp文件中:<body>    <itcast:demo/>ccccc</body>//2  .tld文件中配置如下:<tag>    <name>TagDemo</name>    <tag-class>com.Cecilia.ResponsewebTest.TagDemo</tag-class>    <body-content>JSP</body-content></tag><tag>    <name>TagDemo1</name>    <tag-class>com.Cecilia.ResponsewebTest.TagDemo1</tag-class>    <body-content>JSP</body-content></tag>

新建标签处理类:TagDemo.java

public class TagDemo extends TagSupport{    int x=5;    public void doStartTag() throws JSPException{    //1.使用标签控制页面内容是否输出      return Tag.Skip_BODY;//控制标签体不输出(Tag.EVAL_BODY_ZNCLUDE—显示标签内容显示出来)    //3.控制标签体执行多次,即标签重复输出    return Tag.EVAL_BODY_INCLUDE;//然后继续执行doAfterBody()进行判断}    public void doEndTag() throws JSPException{    //2.控制整个JSP是否输出(实际上控制doStartTag和doEndTag()方法的返回值)    return Tag.EVAL_PAGE;//内容可输出    resturn Tag.SKIP_PAGE;//内容不可输出}//如果要想控制某个标签体多次执行,需要继承JSPTag的子接口IteratorTag,然后重写doAfterBody()方法,控制返回值类型即可。    public void doAfterBody() throws JSPException{    x--;    if(x>0){    return IterationTag.EVAL_BODY_AGAIN;    }else{return IterationTag.SKIP_BODY;}}}

4.修改标签操作

/*1.编写一个java标签处理类,并且继承BodyTagSupport类;2.重写doStartTag(),返回值为BodyTag.EVAL_BODY_BUFFERED;3.重写doEndTag(),在执行doEndTag()时调用getBodyEontent()方法得到标签体内容,并对标签体内容进行修改,最后再输出就OK。*/
public class TagDemo1 extends BodyTagSupport{    public void doStartTag() throws JSPException{    return BodyTag.EVAL_BODY_BUFFERED;}    public void doEndTag() throws JSPException{    //得到标签内容    BodyContent bc=this.getBodyEontent();    String content=bc.getString();    content=content.toUpperCase();//将标签内容修改为大写    try{    this.pageContent.getOut().write(content);//输出修改后的内容}catch(Exception e){    throw new RuntimeException(e);//若出现运行时异常,将其抛给页面提示错误}    return Tag.EVAL_PAGE;//返回显示页面}

注意:以上使用的Tag接口、IteratorionTag接口、BodyTag接口是在JSP2.0以前使用的,在JSP2.0以后只是用一个SImpleTagSupport接口就可以完成三个标签的所有功能,在这里或许有人疑问:那我们就没必要了解和学习这三个接口啦?其实,那还是有必要的,在我们接下来要学习的框架是采用以上三个接口搭建成的,所以学习这三个接口能够有利于我们在学习框架时自己看懂源码,更好地理解框架的原理。

5.SimpleTagSupport接口及操作方法

在了解以上三个接口后,接下来,让我们重点来学习JSP2.0之后具有强大功能的SimpleTagSupport接口

*基本运行原理UML图

基本运行原理UML图

*基本的操作方法

eg://1.jsp文件中:<body>    <sitcast:demo/>cccccc</body>//.tld文件配置如下:<tag>    <name>SimpleTagdemo</name>    <tag-class>com.Cecilia.ResponsewebTest.SimpleTagdemo</tag-class>    <body-content>scriptless</body-content>//表示无脚本的jsp文件</tag>//新建标签处理类SimpleTagdemo.javapublic class SimpleTagdemo extends SimpleTagSupport{    //1.实用简单标签控制标签体是否执行    public  void doTag(){    JspFragment jf=this.getTagBody();//获得标签体对象    //输出标签内容    jf.invoke(this.getJspContext().getOut());    //2.控制标签是否执行    for(int i=0;i<5;i++){        jf.invoke(null);//重复输出5次    }    //如要控制剩余的不执行,那么添加 throw new JspPageException()就可以。    //3.修改标签体    StringWriter sw=new StringWriter();//获得输出流对象    jf.invoke(sw);    String Content=sw.toString();//转化成字符串    content=content.toUpperCase();//修改转化成大写     this.getJspContext().getOut().write(content);//输出修改后的内容    }}

6.开发带属性的标签

eg://JSP文件<body>    <sitcast:demo/>aaaa</body>//.tld文件中声明<tag>    <name>SimpleTagdemo</name>    <tag-class>com.Cecilia.ResponsewebTest.SimpleTagdemo</tag-class>    <body-content>scriptless</body-content>//添加属性    <attribute>       <name>count</name>       <required>true</required>       <rtexprvalue></rtexpravlue>(如果给false,那么只能是值,如果是true,那么除了值还可以接受一个运行时表达式<%= %>)    </attribute>//新建一个标签处理类public class SimpleTagdemo extends SimpleTagSupport{    private int count;//设置标签属性    public void setCount(int count){        thi.count=count;         }    public void doTag()throws JspException{    //获得便签内容对象    JSPFragment jf=this.getJspBody();    //输出标签内容    for(int i=0;i<count;i++){    jf.invoke(null);    }    }}

7.如何实现使用标签控制页面逻辑

*如何实现开发防盗链的标签()?

eg:

//1.在JSP文件中body体

<!-- 开发防盗链的标签referer -->    您好!XXXXXXXXXXXX    <a href="/ResponseWebTest/1.jsp">点我</a>

//2. .tld文件配置如下:

 <tag>        <name>referer</name>        <tag-class>com.Cecilia.MyJSPTest.RefererTag</tag-class>        <body-content>empty</body-content>        <attribute>            <name>site</name>            <require>true</require>            <rtexprvalue>true</rtexprvalue>        </attribute>        <attribute>            <name>page</name>            <require>true</require>            <rtexprvalue>true</rtexprvalue>        </attribute>    </tag>

//3.创建标签处理类Referer.java

/** * 需求:开发防盗链的标签 * @author 芷若初荨 * */public class RefererTag extends SimpleTagSupport{    private String site;//定义网站站点    private String page;//定义页面路径    public void setSite(String site) {        this.site = site;    }    public void setPage(String page) {        this.page = page;    }    @Override    public void doTag() throws JspException, IOException {        // TODO Auto-generated method stub        PageContext pc=(PageContext) this.getJspContext();//获取jsp页面内容        //获取当前页面资源的请求和响应对象        HttpServletRequest request=(HttpServletRequest)pc.getRequest();        HttpServletResponse response=(HttpServletResponse)pc.getResponse();        //1.得到来访问者的referer        String referer=request.getHeader("referer");        if(referer==null||!referer.startsWith(site)){            if(page.startsWith(request.getContextPath())){                response.sendRedirect(page);//跳转                return;            }else if(page.startsWith("/")){                response.sendRedirect(request.getContextPath()+page);            }else{                response.sendRedirect(request.getContextPath()+"/"+page);            }             //如果都不匹配的话,那就抛出异常            throw new SkipPageException();        }        else{            //如果不是盗链者,那么不做任何        }       super.doTag();    }

*如何实现开发标签?

标签处理类如下:

/** * 需求:开发<c:if>标签 * @author 芷若初荨 * */public class IfElseTag extends SimpleTagSupport{    //开发<c:if>标签    private boolean test;      public void setTest(boolean test){      this.test=test;      }    @Override    public void doTag() throws JspException, IOException {        // TODO Auto-generated method stub        if(test){         this.getJspBody().invoke(null);     }    }

*如何实现开发标签?

开发这个标签需要设置三个标签处理器,分别是父标签Choose标签处理器和两个子标签When标签处理器otherwise标签处理器,这三个需要配合使用,如下:

**父标签choose处理器

/** * 创建choose标签的处理器 * @author 芷若初荨 * */public class ChooseTag extends SimpleTagSupport{    private boolean isDo;    public boolean isDo() {        return isDo;    }    public void setDo(boolean isDo) {        this.isDo = isDo;    }    @Override    public void doTag() throws JspException, IOException {        // TODO Auto-generated method stub        this.getJspBody().invoke(null);//获得当前JSP页面body内容以及输出    }}

**when标签处理器

/** * 创建when标签的处理器 * @author 芷若初荨 * */public class WhenTag extends SimpleTagSupport{    private boolean test;//定义when的属性——判断条件    public void setTest(boolean test) {        this.test = test;    }    @Override    public void doTag() throws JspException, IOException {        // TODO Auto-generated method stub        ChooseTag parent=(ChooseTag) this.getParent();//得到父标签        //如果test等于true,并且父标签isDao等于false,那么        if(test&&!parent.isDo()){            this.getJspBody().invoke(null);        }else{}    }}

**otherwise标签处理器

/** * 开发otherwise标签,是when的兄弟标签 * @author 芷若初荨 * */public class OtherWiseTag extends SimpleTagSupport{    @Override    public void doTag() throws JspException, IOException {        // TODO Auto-generated method stub        ChooseTag parent=(ChooseTag) this.getParent();//获得父标签        if(!parent.isDo()){            //如果父标签不执行            this.getJspBody().invoke(null);//获得标签体并输出            parent.setDo(true);//并且将其设置为true        }    }}

*如何开发迭代标签?(foreach)

实例://实现迭代的标签处理类public class Foreach extends SimpleTagSupport{    //对应标签元素var    private String var;    //对应的标签元素items    private Object items;    //使用Collection接口    private Collection<Object> collection;    public void setVar(String var){        this.var=var;    }    public void setItems(Object items)  {        this.items=items;    }    /*    判断参数类型后赋值给collection对象    */    public void setCollection(Object items){    //如果是collection对象,在这里可以看做是子类对象中的set和List    if(items instanceof Collection(Object items)){    this.collection=(Object)items;    }//如果是一个Map对象    if(items instanceof Map){    Map map=new Map();    this.collection=map.entrySet();//将map的键值对赋值给当前的collection变量    }//如果是一个数组(不需要关注数组类型)//如果是数组,那么创建实例,以便做迭代处理    if(items.getClass().isArray()){    this.colletcion=new ArrayList();    //获取数组长度    int length=Array.getLength(items);    //循环遍历数组元素,并添加到Collection对象中    for(int i=0;i<length;i++){    Object object=Array.get(items,i);//循环遍历数组    this.collection.add(object);//并将其添加到Collection对象中    }    }    }//覆盖doTag()方法,实现迭代public void doTag() throws JSPException{    //调用set方法,设置collection对象    this.setColletion(items);    //获取Collection的迭代器     Iterator<Object> iterator=collection.iterator();    while(iterator.hasNext()){    Object value=iterator.next();/    //将对象添加到pageContext中,JSPContext是PageContext的超类getJspContext().setAttribute(var,value);//输出标签内容getJSPBody().invoke(null);    }}}

//.tld文件描述标签

<?xml version="1.0" encoding="UTF-8"?> <taglib>    <tlib-version>1.0</tlib-version>    <jsp-version>2.0</jsp-version>    <short-name>mine</short-name>    <uri>http://myTags.com/myTags</uri>    <tag>      <description>测试</description>          <name>out</name>          <tag-class>com.abc.FirstST</tag-class>      <body-content>scriptless</body-content>            <attribute>                    <name>test</name>                    <requird>true</requird>                    <rtexprvalue>true</rtexprvalue>              </attribute>    </tag><tag>      <description>Foreach遍历输出</description>      <name>foreach</name>     <tag-class>com.abc.ForeachTag</tag-class>      <body-content>scriptless</body-content>          <attribute>             <name>var</name>              <requird>true</requird>              <rtexprvalue>true</rtexprvalue>          </attribute>              <attribute>                                    <name>items</name>              <requird>true</requird>              <rtexprvalue>true</rtexprvalue>         </attribute> </tag> </taglib>

在JSP中编写测试效果

<%@ taglib prefix="myTags" tagdir="/WEB-INF/tags"%>  <%@ taglib prefix="mine" uri="/WEB-INF/tags/myTags.tld" %>  <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"  %>  <html>    <head>     <title>测试自定义标签</title>    </head>    <body>     <% Integer num[] = {1,2,3};      request.setAttribute("num", num);%>     <% Map map = new LinkedHashMap();         map.put("a", "aaa");         map.put("b","bbb");         map.put("c", "ccc");         request.setAttribute("map", map);      %>      <br>---------自定义标签mine:foreach迭代效果---------<br>       <mine:foreach var="object" items="${num}">           ${object}       </mine:foreach>        <mine:foreach var="object" items="${map}">           ${object}       </mine:foreach>        <br>---------标准标签c:foreach迭代效果---------<br>        <c:forEach var="object" items="${num}">            ${object}        </c:forEach>        <c:forEach var="object" items="${map}">            ${object}        </c:forEach>   </body> </html>

*如何实现HTML转义标签?(&lt)

标签处理类如下:

/** * 需求:开发HTML的转义标签 * @author 芷若初荨 * */public class HTMLFilterTag extends SimpleTagSupport{    @Override    public void doTag() throws JspException, IOException {        // TODO Auto-generated method stub        //1.获得标签体    JspFragment jf=this.getJspBody();    //获得输入流    StringWriter writer=new StringWriter();    //输出    jf.invoke(writer);    //获得a标签内容    String content=writer.getBuffer().toString();    content=filter(content);//调用转义方法    this.getJspContext().getOut().write(content);    }    public String filter(String message){        if(message==null){            return(null);//如果为空,返回空            }        char content[]=new char[(message.length())];        message.getChars(0, message.length(), content,0);        StringBuffer result=new StringBuffer(content.length+50);        for(int i=0;i<content.length;i++){            switch(content[i]){            case '<':                result.append("&lt");                break;            default:                break;            }        }        return message;    }}

*如何打包自己的标签库?

建一个Java工程—>复制需要打包的类—>新建一个META-IF目录,将.tld文件拷贝在其目录下—>右键点开Export,选择java目录下的.jar,选择需要打包的工程,并去掉配置文件就OK。

0 0