精华内容
下载资源
问答
  • 文章标题: 使用jsp自定义标签库实现数据列表显示模拟cms4j中的标签库效果   作者: javaboy2012 Email:yanek@163.com qq: 1046011462     cms4j中调用方式:     下面例子实现类似效果:   运行...


    文章标题: 使用jsp自定义标签库实现数据列表显示模拟cms4j中的标签库效果

     

    作者: javaboy2012
    Email:yanek@163.com
    qq:    1046011462

     

     

    cms4j中调用方式:

     

     

    下面例子实现类似效果:

     

    运行效果:

     

    具体如下:


    jsp调用代码:


    <%@ page language="java" import="java.util.*,com.yanek.cms.vo.*" pageEncoding="UTF-8"%>
    <%@ taglib uri="/tags/my-cms" prefix="myTag" %>
    <body>
    <myTag:articleListTag  cateid="1">
     
        <%=article_info.getId() %>------
                <%=article_info.getTitle() %> <br>
               
                ${article_info.id }---- ${article_info.title }<br>

    </myTag:articleListTag>
    <hr>

    <myTag:articleListTag  cateid="2">
     
        <%=article_info.getId() %>------
                <%=article_info.getTitle() %> <br>
               
                ${article_info.id }---- ${article_info.title }<br>

    </myTag:articleListTag>
     </body>
    </html>

     

    标签库定义


    <!-- articleListTag start -->

        <tag>

           <name>articleListTag</name>

           <tag-class>com.yanek.cms.tag.ArticleTag</tag-class>

       
           <body-content>jsp</body-content>
       
          <variable>
            <name-given>article_info</name-given>
            <!--<name-from-attribute>name</name-from-attribute>-->
            <variable-class>com.yanek.cms.tag.Article</variable-class>
            <declare>true</declare>
            <scope>NESTED</scope>
          </variable>

           <attribute>
            <name>cateid</name>
            <required>true</required>
           </attribute>
     
    </tag>

    <!-- articleListTag end -->

     


    标签库类

    package com.yanek.cms.tag;

    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;

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

    public class ArticleTag extends BodyTagSupport {

     private Iterator it;// 要迭代的对象
     private int cateid; // 文章类别id
     
     public final static String name = "article_info";

     @Override
     public int doEndTag() throws JspException {
      try {
       if (bodyContent != null) {
        bodyContent.writeOut(bodyContent.getEnclosingWriter());
       }
      } catch (IOException e) {
       e.printStackTrace();

      }
      return EVAL_PAGE;
     }

     @Override
     public int doStartTag() throws JspException {

      //这里根据文章分类,构造不同的列表数据,实际可以根据数据库获取
      List<Article> articles = new ArrayList<Article>();
      if (cateid == 1) {
       articles.add(new Article(1, "asp"));

       articles.add(new Article(2, "jsp"));
      } else {
       articles.add(new Article(3, "php"));

       articles.add(new Article(4, "java"));
      }
      it = articles.iterator();

      if (it == null) {
       return SKIP_BODY;

      } else {
       return continueNext();
      }
     }

     private int continueNext() {
      if (it.hasNext()) {
       pageContext.setAttribute(name, it.next(), pageContext.PAGE_SCOPE);
       return EVAL_BODY_TAG;
      } else {

       return SKIP_BODY;
      }
     }

     @Override
     public int doAfterBody() {
      return continueNext();
     }


     public int getCateid() {
      return cateid;
     }

     public void setCateid(int cateid) {
      this.cateid = cateid;
     }

    }

     

    标签库引用实体类

    package com.yanek.cms.tag;

    public class Article {
     
     private int id;
     private String title;
     public int getId() {
      return id;
     }
     public void setId(int id) {
      this.id = id;
     }
     public String getTitle() {
      return title;
     }
     public void setTitle(String title) {
      this.title = title;
     }
     public Article(int id, String title) {
      super();
      this.id = id;
      this.title = title;
     }
     
     public Article() {
      super();
      this.id = id;
      this.title = title;
     }
     
     
     

    }

     

    几点说明:标签调用是显示list中对象时采用的脚本变量名字article_info 是在标签库定义文件和标签库类中定义的,如下

        <variable>
            <name-given>article_info</name-given>
            <!--<name-from-attribute>name</name-from-attribute>-->
            <variable-class>com.yanek.cms.tag.Article</variable-class>
            <declare>true</declare>
            <scope>NESTED</scope>
          </variable>

    标签库类中
    public final static String name = "article_info";
    pageContext.setAttribute(name, it.next(), pageContext.PAGE_SCOPE);

     

    显示列表中对象的方式有2种方式:

    调用类的方法:  在eclipse中可以方法提示。

            <%=article_info.getId() %>---- <%=article_info.getTitle() %>

    jstl显示:

           ${article_info.id }---- ${article_info.title }

     

     

    展开全文
  • Taglib指令,其实就是定义一个标签库以及自定义标签的前缀。 比如struts中支持的标签库,html标签库、bean标签库、logic标签库。 其中的具体的实现方式,我们不过多介绍,我们给大家从宏观的角度以及解决其中的疑难...
  • TLD文件实现自定义标签之前我们使用的标签库都是JSTL为我们提供的,大部分的数据操作和控制都可以使用它来完成,但是如果我们项目中有特殊需求或者为了统一开发规范,那么我们也可以自己定义一套标签库供自己的团队...

    TLD文件实现自定义标签

    之前我们使用的标签库都是JSTL为我们提供的,大部分的数据操作和控制都可以使用它来完成,但是如果我们项目中有特殊需求或者为了统一开发规范,那么我们也可以自己定义一套标签库供自己的团队使用。通过实现java提供的JspTag的子接口编写标签处理类,完成自定义标签的定义。

    实现步骤:

    • 创建标签处理程序 (Tag Handler Class)
    • 创建标签库描述文件(Tag Library Descrptor File)
    • 在web.xml文件中配置元素(可选,如果标签库描述文件不放在WEB-INF下则需要配置)

      <jsp-config>
          <taglib>
              <!-- tld描述文件中的uri -->
              <taglib-uri></taglib-uri>
              <!-- 存放路径 -->
              <taglib-location></taglib-location>
          </taglib>
        </jsp-config>
      
    • 在JSP文件中使用taglib指令引入标签库

    • 使用标准格式调用自定义标签

    JspTag标签分为简单的标签和传统的标签,树形图如下:

    这里写图片描述

    简单示例

    示例

    标签实现类

    package com.yt.tag
    public class IpTag implements Tag {
        private PageContext pageContext;
        /**
         * 设置pageContext
         */
        @Override
        public void setPageContext(PageContext pc) {
            this.pageContext = pc;
        }
        /**
         * 设置父类标签
         */
        @Override
        public void setParent(Tag t) {
    
        }
        /**
         * 获取父类标签
         */
        @Override
        public Tag getParent() {
            return null;
        }
        /**
         * 开始标签,一定会被调用
         */
        @Override
        public int doStartTag() throws JspException {
            HttpServletRequest request = (HttpServletRequest)pageContext.getRequest(); //获取request  
            JspWriter out = pageContext.getOut(); //获取out</span>  
    
            String ip = request.getRemoteAddr(); //通过request获取客户机的ip  
            try {  
                out.write(ip); //写到浏览器  
            } catch (IOException e) {  
                throw new RuntimeException(e);  
            }         
            return 0;  
        }
        /**
         * 结束标签
         */
        @Override
        public int doEndTag() throws JspException {
            return 0;
        }
        /**
         * 释放标签
         */
        @Override
        public void release() {
    
        }
    }

    创建标签库描述文件(TLD) myTag.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">
        <description>A tag library exercising SimpleTag handlers</description>
        <tlib-version>1.0</tlib-version>
        <short-name>my</short-name> <!-- 定义一个短名 -->
        <uri>/WEB-INF/static/tld</uri>  <!-- 定义被jsp页面引用的uri -->
        <tag>
            <name>ip</name>
            <tag-class>com.yt.tag.IpTag</tag-class> <!-- 标签实现类 -->
            <body-content>empty</body-content>  <!--标签体为空-->
        </tag>
    </taglib>

    jsp页面使用自定义标签

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@ taglib prefix="m" uri="/WEB-INF/static/tld" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>MyTag</title>
    </head>
    <body>
        <m:ip/>
    </body>
    </html>

    上述自定义标签执行过程:

    1. tomcat服务器启动时,加载到每个web应用,加载每个web应用的WEB-INF目录下的所有文件;
    2. JSP引擎首先通过uri和ip标签名去找tld文件,在tld中通过ip找到IpTag类;
    3. IpTag类首先调用 setPageContext 方法把页面的 pageContext 传递进来;
    4. 再调用setParent把父标签传递进来(没有则不执行),至此完成了标签的初始化工作;
    5. 然后调用doStartTag和doEndTag方法,开始和结束标签;
    6. 最后调用release方法释放标签,运行时所占的资源。

    标签体

    上述简单示例中标签体设置为empty,<body-content>元素的可选值有:

    • empty:无标签体。
    • JSP:传统标签支持它,SimpleTag已经不再支持使用<body-content>JSP</body-content>;标签体内容可以是任何东西:EL、JSTL、<%=%>、<%%>,以及html;
    • scriptless:标签体内容不能是Java脚本,但可以是EL、JSTL等。SimpleTag中需要标签体时使用它。
    • tagdependent:标签体内容不做运算,由标签处理类自行处理,无论标签体内容是EL、JSP、JSTL,都不会做运算。这个选项几乎没有人会使用。

    传统标签

    Tag接口

    public interface Tag extends JspTag {
         public final static int SKIP_BODY = 0;
         public final static int EVAL_BODY_INCLUDE = 1;
         public final static int SKIP_PAGE = 5;
         public final static int EVAL_PAGE = 6;
         void setPageContext(PageContext pc);
         void setParent(Tag t);
         Tag getParent();
         int doStartTag() throws JspException;
         int doEndTag() throws JspException;
         void release();
    }

    tag接口的执行过程:

    这里写图片描述

    验证上述执行过程:

    public class TimeTag implements Tag{
        private PageContext pageContext;
        private Tag parent;
        //标签属性
        private String color;
    
        public TimeTag() {
            super();
            System.out.println("实例化TimeTag");
        }
    
        @Override
        public void setPageContext(PageContext pc) {
            this.pageContext = pc;
            System.out.println("设置pageContext....");
        }
    
        @Override
        public void setParent(Tag t) {
            this.parent = t;
            System.out.println("设置parent.....");
        }
    
        @Override
        public Tag getParent() {
            return this.parent;
        }
    
        @Override
        public int doStartTag() throws JspException {
            System.out.println("doStartTag............");
            return Tag.SKIP_BODY;
        }
    
        @Override
        public int doEndTag() throws JspException {
            System.out.println("doEndTag................");
    
            Date date=new Date();
            SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String re=df.format(date);
    
            try {
                //这里用PageContext的对象的getOut()方法(这样就能在页面中输出了)。
            pageContext.getOut().println("<h1 style='color:"+this.color+";'>"+re+"</h1>");
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
            return Tag.EVAL_PAGE;
        }
    
        @Override
        public void release() {
            System.out.println("release..........");    
        }
    
        public String getColor() {
            return color;
        }
    
        public void setColor(String color) {
            System.out.println("setColor");
            this.color = color;
        }
    }
    <tag>
        <name>time</name>
        <tag-class>com.yt.tag.TimeTag</tag-class>
        <body-content>empty</body-content>
        <!--标签属性的信息 如果有属性,在标签实现类中set/get-->
        <attribute>
            <name>color</name>
            <required>true</required>
            <!--表示可以出来JSP表达式-->
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>
    <m:time color="red"/>

    Tag接口定义了4个静态常量:

    • SKIP_BODY:忽略标签体中的内容(作用在doStartTag方法中)
    • EVAL_BODY_INCLUDE:将标签体的内容进行输出,等同于SimpleTag中JspFragment的invoke(null)(但是获取不了)
    • SKIP_PAGE:等同于new SkipPageException(),不执行JSP页面标签后面的内容(作用在doEndTag方法中)
    • EVAL_PAGE:执行JSP页面标签后面的内容

    带标签体的Tag

    tld描述文件中的body-content可以是scriptless或JSP

    <body-content>scriptless</body-content> <!--可以是JSP-->

    TimeTag类中改变doStartTag的返回值

    @Override
    public int doStartTag() throws JspException {
        System.out.println("doStartTag............");
           return Tag.EVAL_BODY_INCLUDE;
    }
    <m:time color="red">${param.name}</m:time>

    标签体内容可以是El、JSTL、HTML标签和纯文本等,标签实现类会自动解析内容输出到浏览器。如上述可以在请求url后加上?name=红色。

    IterationTag接口

    这个接口是Tag接口的子接口,它可以实现body的循环。

    public interface IterationTag extends Tag {
        public final static int EVAL_BODY_AGAIN = 2;
        int doAfterBody() throws JspException;
    }

    上述接口定义了一个新的静态常量EVAL_BODY_AGAIN和方法doAfterBody。
    EVAL_BODY_AGAIN:重新执行 (作用在doAfterBody方法中)

    IterationTag接口的执行过程:

    IterationTag

    以下模拟一个类似于<c:forEache>的循环迭代

    <%
            List list = new ArrayList();
            list.add("a");
            list.add("b");
            list.add("c");
            list.add("d");
            pageContext.setAttribute("list", list);
        %>
        <m:for item="${list}" var="i">
            ${i}
        </m:for>
    <tag>
        <name>for</name>
        <tag-class>com.yt.tag.ForTag</tag-class>
        <body-content>scriptless</body-content>
        <attribute>
            <name>item</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
        <attribute>
            <name>var</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>
    public class ForTag implements IterationTag{
        private PageContext pageContext;
        private Tag parent;
        private List item;          //需要迭代的List集合
        private String var;         //List集合元素值的变量
    
        private int index=0;        //索引
    
        public List getItem() {
            return item;
        }
    
        public void setItem(List item) {
            this.item = item;
        }
    
        public String getVar() {
            return var;
        }
    
        public void setVar(String var) {
            this.var = var;
        }
    
        public PageContext getPageContext() {
            return pageContext;
        }
    
        @Override
        public void setPageContext(PageContext pc) {
            this.pageContext = pc;
        }
    
        @Override
        public void setParent(Tag t) {
            this.parent = t;
        }
    
        @Override
        public Tag getParent() {
            return this.parent;
        }
    
        @Override
        public int doStartTag() throws JspException {
            pageContext.setAttribute(var, item.get(index));//这里设置的属性只会执行一次,被输出到浏览器
            return Tag.EVAL_BODY_INCLUDE;
        }
    
        @Override
        public int doEndTag() throws JspException {
            return Tag.EVAL_PAGE;
        }
    
        @Override
        public void release() {
    
        }
    
        @Override
        public int doAfterBody() throws JspException {
            if(++index<item.size()){
                pageContext.setAttribute(var, item.get(index)); //循环执行
                return IterationTag.EVAL_BODY_AGAIN;   //循环输出标签体到当前输出流
            }
            return Tag.SKIP_BODY;
        }
    }

    BodyTag接口

    这个接口是IterationTag的子接口,上述标签都不可以读body的值,该标签实现了对body部分的读写。

    public interface BodyTag extends IterationTag {
        public final static int EVAL_BODY_TAG = 2; //已过时
        public final static int EVAL_BODY_BUFFERED = 2;
        void setBodyContent(BodyContent b);
        void doInitBody() throws JspException;

    EVAL_BODY_BUFFERED :把标签主体内容放入缓存器中不要输出(作用在主体标签中),让BodyTag调用setBodyContent获取BodyContent。

    BodyTag接口的执行过程:

    BodyTag

    <m:body>
        我是一名java程序员
    </m:body>
    <tag>
        <name>body</name>
        <tag-class>com.yt.tag.BodyContentTag</tag-class>
        <body-content>scriptless</body-content>
    </tag>
    public class BodyContentTag implements BodyTag{
    
        private BodyContent bodyContent;
        private PageContext pageContext;
        private Tag parent;
    
        @Override
        public int doAfterBody() throws JspException {
    
            return Tag.SKIP_BODY;
        }
        @Override
        public void setPageContext(PageContext pc) {
            this.pageContext = pc;
        }
        @Override
        public void setParent(Tag t) {
            this.parent = t;
        }
        @Override
        public Tag getParent() {
            return this.parent;
        }
        @Override
        public int doStartTag() throws JspException {
            return BodyTag.EVAL_BODY_BUFFERED; //接下来会依次执行setBodyContent、doInitBody()和doAfterBody()
        }
    
        @Override
        public int doEndTag() throws JspException {
            StringBuilder sb = new StringBuilder();
            String msg = bodyContent.getString();
            String newmsg = msg.replace("java", "C#");
            sb.append("<div style='width:200px;height:200px;border:1px #ccc solid; line-height:200px;text-align:center;'>");
            sb.append(newmsg);
            sb.append("<div");
            try {
                pageContext.getOut().print(sb.toString());
            } catch (IOException e) {
                e.printStackTrace();
            }
            return Tag.EVAL_PAGE;
        }
        @Override
        public void release() {
    
        }
        @Override
        public void setBodyContent(BodyContent b) {
            this.bodyContent = b;
        }
        @Override
        public void doInitBody() throws JspException {
    
        }
    }

    BodyTagSupport类

    该类实现了BodyTag, IterationTag, JspTag, Tag这些接口,并且有一个常量:bodyContent,是BodyContent类实例化的对象,已经实例化好的,可以直接用。
    这个类的实现和我们上述自定义的实现类BodyContentTag 基本一致。

    TagSupport类

    这个类是IterationTag的实现类,和BodyTagSupport比较类似。里面封装的常量不同。区别在于二者定义的属性不同:
    BodyTagSupport定义的属性

        protected BodyContent   bodyContent;

    TagSupport定义的属性

        private   Tag         parent;
        private   Hashtable<String, Object> values;
        protected String      id;
        protected PageContext pageContext;

    简单标签

    SimpleTag接口:

    在jsp2.0中也新增加的接口,可以实现它来做制作标签处理类,而不用处理一些TagSupport、BodyTagSupport类中来回传值的问题。

    public interface SimpleTag extends JspTag {
        //标签执行方法
        public void doTag() throws javax.servlet.jsp.JspException, java.io.IOException;
        //设置父标签
        public void setParent( JspTag parent );
        //获取父标签
        public JspTag getParent();
        //设置pageContext
        public void setJspContext( JspContext pc );
        //设置标签体对象
        public void setJspBody( JspFragment jspBody );
    }

    下面同样实现与<c:forEach>类似的迭代功能,与前面实现IterationTag的类ForTag做比较,进而看出实现SimpleTag接口的简便

    public class SimpleForTag implements SimpleTag{
        private JspContext jspContext;  //pageContext父类,都是抽象类,因此基本没区别
        private JspTag parent;
        private JspFragment jspBody;
    
        private List item;
        private String var;
    
        @Override
        public void doTag() throws JspException, IOException {
            JspWriter out = this.getJspContext().getOut();
            //循环遍历标签体
            for(Iterator it = item.iterator();it.hasNext();){
                String name = (String) it.next();
                this.getJspContext().setAttribute(var, name);
                this.getJspBody().invoke(null); //body-content为scriptless
            }
        }
    
        public List getItem() {
            return item;
        }
    
        public void setItem(List item) {
            this.item = item;
        }
    
        public String getVar() {
            return var;
        }
    
        public void setVar(String var) {
            this.var = var;
        }
    
        public JspContext getJspContext() {
            return jspContext;
        }
    
        public JspFragment getJspBody() {
            return jspBody;
        }
    
        @Override
        public void setParent(JspTag parent) {
            this.parent = parent;
        }
    
        @Override
        public JspTag getParent() {
            return this.parent;
        }
    
        @Override
        public void setJspContext(JspContext pc) {
            this.jspContext = pc;
        }
    
        @Override
        public void setJspBody(JspFragment jspBody) {
            this.jspBody = jspBody;
        }
    }

    Tag标签的生命周期:
    1. 当容器(Tomcat)第一次执行到某个标签时,会创建标签处理类的实例;
    2. 然后调用setJspContext(JspContext)方法,把当前JSP页面的pageContext对象传递给这个方法;
    3. 如果当前标签有父标签,那么使用父标签的标签处理类对象调用setParent(JspTag)方法;
    4. 如果标签有标签体,那么把标签体转换成JspFragment对象,然后调用setJspBody()方法;
    5. 每次执行标签时,都调用doTag()方法,它是标签处理方法。

    SimpleTagSupport类:

    继承SimpleTagSuppport要比实现SimpleTag接口方便太多了,现在你只需要重写doTag()方法和添加自己需要的属性即可,其他方法都已经被SimpleTagSuppport完成了。

    WEB容器在处理简单标签的标签体时,会把标签体内容用一个JspFragment对象表示,并调用标签处理器对象的setJspBody方法把JspFragment对象传递给标签处理器对象,JspFragment对象有二个方法:

    public abstract class JspFragment {
         public abstract void invoke( Writer out ) throws JspException, IOException;
         public abstract JspContext getJspContext();
    }

    public abstract void invoke(Java.io.Writer out)用于执行JspFragment对象所代表的JSP代码片段,参数out用于指定将JspFragment对象的执行结果写入到哪个输出流对象中,如果传递给参数out的值为null,则将执行结果写入到JspContext.getOut()方法返回的输出流对象中。

    自定义输出流

        @Override
        public void doTag() throws JspException, IOException {
            System.out.println("doTag");
            JspWriter out = this.getJspContext().getOut();
            //循环遍历标签体
            for(Iterator it = item.iterator();it.hasNext();){
                String name = (String) it.next();
                this.getJspContext().setAttribute(var, name);
                StringWriter sw = new StringWriter();
                this.getJspBody().invoke(sw); //body-content为scriptless
                String body = sw.toString().toUpperCase();
                out.print(body);
            }
        }

    不执行标签下面的页面内容

    public class SkipTag extends SimpleTagSupport{
        @Override
        public void doTag() throws JspException, IOException {
            PageContext pageContext = (PageContext) this.getJspContext();
            pageContext.getOut().print("<h1>呵呵</h1>");
            throw new SkipPageException();
        }
    }
    展开全文
  • 一般我们说自定义标签是指JSP...标签库是按照功能或实现进行分组的自定义标签的集合。 网络上常见的CMS内容管理系统都是采用模板的形式来实现,基本上所有的CMS系统都有一套自己的模板标签书写方法,简称自定义标签...

    一般我们说自定义标签是指JSP自定义标签。自定义标签在功能上逻辑上与javaBean 类似,都封装Java 代码。自定义标签是可重用的组件代码,并且允许开发人员为复杂的操作提供逻辑名称。
    JSP开发人员使用标签库创建标签.标签库是按照功能或实现进行分组的自定义标签的集合。
    网络上常见的CMS内容管理系统都是采用模板的形式来实现,基本上所有的CMS系统都有一套自己的模板标签书写方法,简称自定义标签。

    传统方式

    在这里插入图片描述

    自定义标签
            传统方式(jsp1.1):实现Tag接口
            简单方式(jsp2.0):实现SimpleTag接口
    步骤: a编写标签处理类     b编写标签描述符        c导入并使用
    
    编写标签处理类
            传统方法:实现javax.servlet.jsp.tagext.Tag接口: doStartTag()
            简单方法:实现javax.servlet.jsp.tagext.SimpleTag接口:    doTag()
    如果jsp在编译时发现了自定义标签,就会交给doStartTag()或doTag()
    
    编写标签描述符t(Tag)l(library)d(descriptor)
    
        编写建议:可以仿照 一个其他标签语言(el jstl) 的tld文件
    
    <!--标签库的头文件-->
    <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>
        
        
        <display-name>全称</display-name>
        <short-name>简称</short-name>
        <uri>标签库的uri</uri>
        <!--自定义标签的相关信息-->
        <tag>
            <description>标签描述</description>
            <name>标签名</name>
            <tag-class>标签库的实现类</tag-class>
            <body-content>标签体的类型</body-content>
        </tag>
    </taglib>
    

    在这里插入图片描述
    scriptlet:<% … %>(小脚本) <%! … %> <%= … %>,即scriptless为除了这3个外的元素

    导入并使用:
                myTag。tld导入WEB-INF或子目录下(非lib和classes)
                使用:引入具体要使用的tld文件 
                           <%@ taglib uri="xxx", prefix = "x"%>
                uri:每个tld文件的 唯一描述符
                prefix:使用tld标签时的前缀
    
                具体使用:
                        空标签(没有标签体的标签):<d:foreach></d:foreach>    <d:foreach/>
            
                        带标签体:<d:foreach>xxx</d:foreach>
    
                        带属性:<d:foreach collection = "${students}">xxx</d:foreach> <d:foreach 属性名= "属性值">xxx</d:foreach>
    

    实际开发步骤:

    编写标签处理类
    先确保项目有tomcat环境

    在这里插入图片描述

    Tag接口
            doStartTag:标签处理类得到核心方法(标签体的执行逻辑)
            该方法有以下两个返回值即(01int EVAL_BODY_INCLUDE = 1;  表示该标签体会被执行
            int SKIP_BODY = 0;表示该标签体不会被执行
            doEndTag:标签执行完毕之后的方法,例如可以让标签在执行完毕之后,再执行一次
            int SKIP_PAGE = 5;后面jsp页面内容不被执行
            int EVAL_PAGE = 6;后面jsp页面内容继续执行
    

    在这里插入图片描述

    Tag接口中所有方法的执行顺序:
    再运行时(jsp会被翻译成servlet(java))当jsp容器(Tomcat,jetty)在将jsp翻译成servlet的时候,
    如果遇到jsp中有标签,就会依次执行serPageContext-setParent-doStartTag-doEndTag-release
    

    javax.servlet.jap.tagext.IterationTag接口:(时Tag的子接口)
    如果有循环:IterationTag 没有循环:Tag
    在这里插入图片描述

    doAfterBody:当标签体执行完毕后的操作,通过返回值决定:
                (EVAL_BODY_AGAIN= 2)重复执行
                (SKIP_BODY=0)不再执行
    

    BobyTag接口:如果在标签体被显示之前,进行一些其他的“额外”操作 例如:输出前把小写改为大写

    在这里插入图片描述
    在这里插入图片描述

    int EVAL_BODY_BUFFERED = 2, doStartTag的第三个返回值代表一个缓冲区(Body Content)

    BodyContext是abstract 具体使用时需要使用实现类BodyContentImpl(要引入jasper.jar,在配置comcat的comfige中添加)

    如果 doStartTag 的返回值 是 EVAL_BODY_BUFFFERED,则服务器会自动将标签体需要显示的内容放入缓冲区中(BodyContent)
    因此,如果要更改最终显示结果,只需要从缓冲区中获取原来的数据,进行修改即可
    如何获取修改;详见BodyContent中的方法(通过getxxx获取原来的数据,修改后,输出getEncloseingWriter)
    在这里插入图片描述

    目标:遍历3<xXX>hello<xxx>执行一次,重复两次
    
    编写标签描述符(mytag.tld)
    
    导入并使用
    <%@ taglib uri="http://www.yuanqi.com" prefix="c"%>
    <c:mytag num="4">hello</c:mytag>
    

    在这里插入图片描述
    mytag.tld

    <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>
        <uri>http://www.yuanqi.com</uri>
    	<!--自定义标签的相关信息-->
        <tag>
            <description>这是我的迭代器标签</description>
            <name>mytag</name>
            <tag-class>tag.MyIteration</tag-class>
            <body-content>JSP</body-content>
    		<attribute>
    			<name>num</name>
    			<required>true</required><!--是否必须赋值-->
    		</attribute>
        </tag>
    
        <tag>
            <name>toupper</name>
            <tag-class>tag.ToUpperCast</tag-class>
            <body-content>JSP</body-content>
        </tag>
        <tag>
            <name>s-tag</name>
            <tag-class>tag.SimpleTagIteration</tag-class>
            <body-content>scriptless</body-content>
            <attribute>
                <name>num</name>
                <required>true</required>
            </attribute>
        </tag>
        <tag>
            <name>s-login</name>
            <tag-class>tag.LoginTag</tag-class>
            <body-content>scriptless</body-content>
        </tag>
    </taglib>
    

    jsp

    <%@ taglib uri="http://www.yuanqi.com" prefix="c"%>
    <html>
      <head>
        <title>$Title$</title>
      </head>
      <body>
      <c:mytag num="4">hello</c:mytag>
      <c:toupper>hello</c:toupper>
      $END$
      <c:s-tag num="3">simple<br/></c:s-tag>
    

    myiteration.java

    package 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?SKIP_BODY:EVAL_BODY_AGAIN;
        }
    }
    
    

    touppercast,java

    import javax.servlet.jsp.JspException;
    import javax.servlet.jsp.tagext.BodyTagSupport;
    import java.io.IOException;
    
    public class ToUpperCast extends BodyTagSupport {
        @Override
        public int doStartTag() throws JspException {
            return EVAL_BODY_BUFFERED;
        }//该父类默认返回EVAL_BODY_BUFFERED,故该方法可不重写
    
        @Override
        public int doEndTag() throws JspException {
            try {
                String content = getBodyContent().getString();
    
                content = content.toUpperCase();
    
                bodyContent.getEnclosingWriter().write(content);
    
            } catch (IOException e) {
                e.printStackTrace();
            }
            return super.doEndTag();
        }
    }
    
    展开全文
  • Taglib指令,其实就是定义一个标签库以及自定义标签的前缀。 比如struts中支持的标签库,html标签库、bean标签库、logic标签库。 其中的具体的实现方式,我们不过多介绍,我们给大家从宏观的角度以及解决其中的...

    Taglib指令介绍

    Taglib指令,其实就是定义一个标签库以及自定义标签的前缀。

    比如struts中支持的标签库,html标签库、bean标签库、logic标签库。

    其中的具体的实现方式,我们不过多介绍,我们给大家从宏观的角度以及解决其中的疑难点,后面会大家介绍相应的学习资料。

    除了struts的标签库,我们常见还有jstl标签库。

    这样在界面jsp中引入其中的标签库或者标签库文件,然后才可以正常使用其中定义的标签。


    复制代码 代码如下:
    <%@ taglib prefix ="bean" uri= "http://struts.apache.org/tags-bean" %>
    <%@ taglib prefix ="logic" uri= "http://struts.apache.org/tags-logic" %>
    <%@ taglib prefix ="html" uri= "http://struts.apache.org/tags-html" %>
    <%@ taglib prefix ="c" uri="http://java.sun.com/jsp/jstl/core" %>

     


    自定义标签库优点

    在jsp1.1版本中就增加了自定义标签库。自定义标签库可以看作一种优秀的组件。在自定义标签库中,我们可以把复杂的业务逻辑功能都封装在标签库中了。而不必在jsp中写具体的代码。这样,jsp代码与java编码能力不必强制耦合在一起。

    提到jsp版本的问题,我们首先应该确定我们jsp版本,因为版本不同,标签库文件引入的头文件不同,并且其中的标签也有差异。

    如何查看我们使用的jsp版本或servlet版本

    打开tomcat下lib文件下的jsp-api.jar下的/META-INF/MANIFEST.MF文件,查看jsp版本。

    因为我已经导入eclispe中,图如下:

     

     


     

    lib文件下的servlet-api.jar下的/META-INF/MANIFEST.MF文件,查看servlet版本

    因为我已经导入eclispe中,图如下:

     

     

    Jsp2新增的特性

    上述图中jsp版本是2.2,servlet版本是3.0。目前servlet3.0对应的是jsp2.2规范,但是一般情况下,我们把jsp2.0与jsp2.2都统称为jsp2.

    如果我们使用jsp2,则web.xml使用的是servlet2.4以上的版本。那我们看一下web.xml对应的头文件:

    新增的特性是:


    复制代码 代码如下:
    <web-app version= "4"
    xmlns="http://javasuncom/xml/ns/j2ee"
    xmlns:xsi="http://wwwworg/2001/XMLSchema-instance"
    xsi:schemaLocation="http://javasuncom/xml/ns/j2ee
    http://javasuncom/xml/ns/j2ee/web-app_2_xsd" >
    </web-app>

    1.直接配置jsp的属性

    比如在web.xml中配置:


    复制代码 代码如下:
    < jsp-config>
    <jsp-property-group >
    <!--  对那些文件进行应用 -->
    <url-pattern >* jsp</ url-pattern>
    <!-- 忽略el表达式 -->
    <el-ignored >true </el-ignored >
    </jsp-property-group >
    </ jsp-config>

    当然还有很多功能:

     

    2.表达式语言

    表达式语言,就是使用el表达式。

    3.使用TagFile

    使用TagFile可以代替标签处理类和库文件。

    jsp1和jsp2的标签库文件中的头文件

    jsp1的标签文件的头文件:


    复制代码 代码如下:
    <?xml version="0" encoding= "UTF-8"?>
    <!DOCTYPE taglib
    PUBLIC "-//Sun Microsystems, Inc//DTD JSP Tag Library 1//EN"
    "http://javasuncom/j2ee/dtds/web-jsptaglibrary_1_dtd">

    根据后缀dtd,知道这是引入dtd文件,但是这具体表示什么意思呢?

    若是引入dtd文件,则使用DOCTYPE 这种形式。但是 PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"是什么意思呢?

    根据xml中,如何引入dtd文件?引入dtd文件有以下形式:

    1.在xml文档内部引入dtd


    复制代码 代码如下:
    <?xml version="0"?>
    <!DOCTYPE note [
    <!ELEMENT note (to,from,heading,body)>
    <!ELEMENT to (#PCDATA)>
    <!ELEMENT from (#PCDATA)>
    <!ELEMENT heading (#PCDATA)>
    <!ELEMENT body (#PCDATA)>
    ]>
    <note>
    <to>George</to>
    <from>John</from>
    <heading>Reminder</heading>
    <body>Don't forget the meeting!</body>
    </note>

    2.在xml文档引入外部dtd文件
    复制代码 代码如下:
    <?xml version="0"?>
    <!DOCTYPE note SYSTEM "notedtd">
    <note>
    <to>George</to>
    <from>John</from>
    <heading>Reminder</heading>
    <body>Don't forget the meeting!</body>
    </note>

    <!ELEMENT note (to,from,heading,body)>
    <!ELEMENT to (#PCDATA)>
    <!ELEMENT from (#PCDATA)>
    <!ELEMENT heading (#PCDATA)>
    <!ELEMENT body (#PCDATA)>

    在文档类型声明时,用管间质SYSTEM或PUBLIC来指出外部DTD文件的位置

    用system关键字,如下:<!DOCTYPE 根元素的名字 SYSTEM "外部DTD文件的URI">

    用public如下:<!DOCTYPE 根元素的名字 PUBLIC "DTD的名字" "外部DTD文件的URI">

    一般用system关键字来形容是私有的dtd文件。

    而public关键字来形容的是公共的dtd文件。public形式,首先默认的根据dtd的名字来寻找dtd文件,找不到,则会根据dtd文件的uri寻找文件。

    jsp2中标签文件的头文件如下:其中是使用的schema形式而不是dtd文件。


    复制代码 代码如下:
    <?xml version="0" encoding="UTF-8" ?>
    <taglib xmlns="http://javasuncom/xml/ns/j2ee"
    xmlns:xsi="http://wwwworg/2001/XMLSchema-instance"
    xsi:schemaLocation="http://javasuncom/xml/ns/j2ee http://javasuncom/xml/ns/j2ee/web-jsptaglibrary_2_xsd"
    version="0"></taglib>

    标签库文件位置

    把tld文件放在WebContent目录下或其子目录下。这样的话,web.xml不用配置其位置即可。tomcat直接读取webcontent下的tld文件。
    详细出处参考:http://www.jb51.net/article/33788.htm

    展开全文
  • 自定义标签简介

    2019-02-15 13:35:00
    JSTL标签库只提供了简单的输出等功能,没有实现任何的HTML代码封装,并且某些复杂类型转换,或者逻辑处理的时候,JSTL标签库完成不了,需要自定义标签! 我们可以有两种方式实现自定义标签: 传统方式,...
  • Taglib指令,其实就是定义一个标签库以及自定义标签的前缀。 比如struts中支持的标签库,html标签库、bean标签库、logic标签库。 其中的具体的实现方式,我们不过多介绍,我们给大家从宏观的角度以及解决...
  • JavaEE自定义标签技术

    2013-11-21 09:34:00
    我们经常用到的JSTL(JSP标签标准)是典型的自定义标签的案例。 自定义标签,即是在JSP页面的标签中自定义它们的功能,因为在MVC和三层架构中,JSP页面作为视图(view)是不允许出现...自定义标签有两种实现方式...
  • 一、什么是Taglib?如果你曾使用JSP页面来作为渲染视图的话,我相信你对JSTL标签库一定不会感到陌生。比如:1.forEach代码片段Item 1232....它们分别是核心标签格式化标签JSTL函数JSTL标签库可通过以下方式进...
  • Structs架构包含有自定义标签库

    千次阅读 2005-07-20 15:05:00
    Structs架构包含有自定义标签库,可以通过各种不同的方式使用。虽然就使用该架构来说,这些库并不是必须的,不过它们包含的标签在你的应用的许多地方都很有用。Structs的一些标签库包括有: . structs-html标签库...
  • 来源https://blog.csdn.net/yutao_Struggle/article/details/78857368自定义标签实现方式之前我们使用的标签库都是JSTL为我们提供的,大部分的数据操作和控制都可以使用它来完成,但是如果我们项目中有特殊需求或者...
  • 自定义JSTL标签

    2015-06-18 23:34:29
    步骤2:创建TLD标签库描述文件   使用步骤: 配置TLD文件 修改JSP文件,使用自定义标签   步骤: 1、实现Tag接口或SimpleTag接口或者继承TagSupport类 使用接口方式则要实现6个方法  setPageContext...
  • 第二:java标准标签库(sun之前自己开发的一系列的标签的集合)jstl,以及表达式语言EL。 2、自定义标签 (1)理解: 可以允许用户自己根据自己的需要,去开发自己的标签的技术规范。 通俗:在Jsp页面上,以...
  • feilong-taglib,是 JSP常用自定义标签集 主要由两部分组成 Common 包含所有自定义标签的base类,以及常用的自定义标签 和el function  taglib  说明 isContains  判断一个值,...
  • 第二:java标准标签库(sun之前自己开发的一系列的标签的集合)jstl,以及表达式语言EL。 2、自定义标签 (1)理解: 可以允许用户自己根据自己的需要,去开发自己的标签的技术规范。 通俗:在Jsp页面上,以简单...
  • 自定义拦截器 1 在struts2里面有很多的拦截器,这些拦截器是struts2封装的功能,但是在实际开发中,struts2里面的拦截器中可能没有要使用的功能,这个时候需要自己写拦截器实现功能 2 拦截器结构 (1)...
  • 如果有更多更好的方式,希望可以留言给我扩充知识。 效果图: 1 . 添加Gradle implementation 'com.xenione.libs:tab-digit:1.0.2' 2 . xml文件 可以直接在xml文件中设置属性,如背景或文本颜色,文本大小和...
  • vue 自定义指令

    2020-02-15 18:08:38
    自定义指令: 全局指令: ... 通过js的方式来操作标签 }) 补充js样式: 获取焦点搭配input使用,在钩子函数中,el形参.focus(),可实现页面锁定光标的作用 其中钩子函数: (1)bind:...
  • JSTL详细标签库介绍

    2010-11-01 16:37:44
    以下这些情况都可以引发异常:您的代码或调用的代码(如共享)中有错误,操作系统资源不可用,公共语言运行遇到意外情况(如无法验证代码),等等<BR><BR>《Exception Handling for C++》关于异常处理论文,向...
  • 实现方式 import 'package:oktoast/oktoast.dart'; 在屏幕中间展示加载标签 _showLoading() { showToastWidget( Container( width: 150, height: 100, color: Colors.black54, child: Center( child: ...
  • 支持使用伪彩色标签进行训练/评估/预测,提升训练体验,并提供将灰度标注图转为伪彩色标注图的脚本 新增学习率warmup功能,支持与不同的学习率Decay策略配合使用 新增图像归一化操作的GPU化实现,进一步提升预测速度...
  • 也可以通过自定义函数库和标签库达到目的,这里介绍另外一种方法,使用spel Spring3中引入了Spring表达式语言SpringEL,SpEL是一种强大,简洁的装配Bean的方式,他可以通过运行期间执行的表达式将值装配到我们的属性...
  • 自定义标签。 x和y轴的标签是自动生成的。 但是您可以设置自己的标签,可以使用字符串。 处理不完整的数据。 可以以不同的频率提供数据。 视口。 您可以限制视口,以便仅显示部分数据。 手动Y轴限制 还有更多......
  • 标签栏TabLayout与ViewPager的那些事

    千次阅读 2017-05-26 16:54:53
    一,引言上图是简书Android端的主页Tab,在其他的App中Tab也是很常见的,它的实现方式也有很多:TabHost,自定义控件(第三方),RadioGroup等等。这里主要介绍Android Design中的TabLayout的使用。TabLayout和...

空空如也

空空如也

1 2 3 4 5 ... 13
收藏数 256
精华内容 102
关键字:

自定义标签库实现方式