自定义标签库

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.java
public 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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值