自定义标签

自定义标签

第一个自定义标签

实现步骤:
 1)继承SimpleTagSupport
 2)覆盖doTag方法
 3)自定义 tld 文件配置
  • 案例 :显示当前客户的ip

    • java

      /**
       * 标签处理器类
       * 
       * 1)继承SimpleTagSupport
       *
       */
      public class ShowIpTag extends SimpleTagSupport{
      
          /**
           * 2)覆盖doTag方法
           */
          @Override
          public void doTag() throws JspException, IOException {
              //向浏览器输出客户的ip地址
              PageContext pageContext = (PageContext)this.getJspContext();
      
              HttpServletRequest request = (HttpServletRequest)pageContext.getRequest();
      
              String ip = request.getRemoteHost();
      
              JspWriter out = pageContext.getOut();
      
              out.write("使用自定义标签输出客户的IP地址:"+ip);
      
          }
      }
      
    • 自定义 tld 文件配置
    •   <!-- 标签库的版本 -->
        <tlib-version>1.1</tlib-version>
        <!-- 标签库前缀 -->
        <short-name>albin</short-name>
        <!-- tld文件的唯一标记 -->
        <uri>http://gz.albin.cn</uri>
      
        <!-- 一个标签的声明 -->
        <tag>
          <!-- 标签名称 -->
          <name>showIp</name>
          <!-- 标签处理器类的全名 -->
          <tag-class>gz.albin.a_tag.ShowIpTag</tag-class>
          <!-- 输出标签体内容格式 -->
          <body-content>scriptless</body-content>
        </tag>
      
    • JSP

        <body>
          <%
              //获取当前客户的IP地址
              //String ip = request.getRemoteHost();
              //输出到浏览器
              //out.write("当前客户的IP地址是:"+ip);
           %>
           <%--使用标签库中的标签--%>
           <albin:showIp>xxxxx</albin:showIp>
      
        </body>
      

自定义标签的执行过程

问题: http://localhost:8080/jstl/01.hellotag.jsp  如何访问到自定义标签?

前提: tomcat服务器启动时,加载到每个web应用,加载每个web应用的WEB-INF目录下的所有文件!!!例如。web.xml, tld文件!!!
            1)访问01.hellotag.jsp资源
            2)tomcat服务器把jsp文件翻译成java源文件->编译class->构造类对象->调用_jspService()方法
            3)检查jsp文件的taglib指令,是否存在一个名为http://gz.albin.cn的tld文件。如果没有,则报错
            4)上一步已经读到albin.tld文件
            5)读到<albin:showIp> 到albin.tld文件中查询是否存在<name>为showIp的<tag>标签
            6)找到对应的<tag>标签,则读到<tag-class>内容
            7)得到 gz.albin.a_tag.ShowIpTag

            构造ShowIpTag对象,然后调用ShowIpTag里面的方法

自定义标签处理器类的生命周期

SimpleTag接口: 
void    setJspContext(JspContext pc)  --设置pageContext对象,传入pageContext(一定调用)
                                        通过getJspCotext()方法得到pageContext对象
                void    setParent(JspTag parent)  --设置父标签对象,传入父标签对象,如果没有父标签,则不                                                      调用此方法。通过getParent()方法得到父标签对象。
                void     setXXX(值)               --设置属性值。
                void    setJspBody(JspFragment jspBody) --设置标签体内容。标签体内容封装到JspFragment对象                                                 中,然后传入JspFragment对象。通过getJspBody()方法                                                        得到标签体内容。如果没有标签体内容,则不会调                                                      用此方法
                void    doTag()                     --执行标签时调用的方法。(一定调用)

* 案例

        public class DemoTag extends SimpleTagSupport{
            //1.声明属性的成员变量
            private Integer num;

            //2.关键点: 必须提供公开的setter方法,用于给属性赋值
            public void setNum(Integer num) {
                this.num = num;
            }


            @Override
            public void doTag() throws JspException, IOException {
                System.out.println("执行了标签");

                /**
                 * 1)控制标签内容是否输出
                 *    输出: 调用jspFrament.invoke();
                 *    不输出: 不调用jspFrament.invoke();
                 */
                //1.1 得到标签体内容
                JspFragment jspBody = this.getJspBody();

                /**
                 * 执行invoke方法: 把标签体内容输出到指定的Writer对象中
                 */
                //1.2 往浏览器输出内容,writer为null就是默认往浏览器输出
                //JspWriter out = this.getJspContext().getOut();
                //jspBody.invoke(out);
                jspBody.invoke(null);//等价于上面的代码

                /**
                 * 3)控制重复输出标签体内容
                 *     方法: 执行多次jspBody.invoke()方法
                 */
                /*for(int i=1;i<=num;i++){
                    jspBody.invoke(null);
                }*/

                /**
                 * 4)改变标签体内容
                 */
                //4.1 创建StringWriter临时容器
                StringWriter sw = new StringWriter();
                //4.2 把标签体拷贝到临时容器
                jspBody.invoke(sw);
                //4.3 从临时容器中得到标签体内容
                String content = sw.toString();
                //4.4 改变内容
                content = content.toLowerCase();
                //System.out.println(content);
                //4.5 把改变的内容输出到浏览器
                //jspBody.invoke(null); 不能使用此方式输出,因为jsbBody没有改变过
                this.getJspContext().getOut().write(content);


                /**
                 * 2)控制标签余下内容是否输出
                 *   输出: 什么都不干!
                 *   不输出: 抛出SkipPageException异常
                 */
                throw new SkipPageException();

            }

* tld

          <tag>
            <name>demoTag</name>
            <tag-class>gz.albin.a_tag.DemoTag</tag-class>
            <body-content>scriptless</body-content>
            <!-- 属性声明 -->
            <attribute>
                <!-- 属性名称 -->
                <name>num</name>
                <!-- 是否必填 -->
                <required>true</required>
                <!-- 是否支持EL表达式 -->
                <rtexprvalue>false</rtexprvalue>
            </attribute>
          </tag>
  • jsp

          <body>
            <albin:demoTag num="2">xxxx${10+5}</albin:demoTag>
                  标签余下内容
          </body>
    

自定义标签的作用

        1)控制标签体内容是否输出
        2)控制标签余下内容是否输出
        3)控制重复输出标签体内容
        4)改变标签体内容
        5)带属性的标签

输出标签体内容格式

            JSP:   在传统标签中使用的。可以写和执行jsp的java代码。
            scriptless:  标签体不可以写jsp的java代码
            empty:    必须是空标签。
            tagdependent : 标签体内容可以写jsp的java代码,但不会执行。

自定义 IfTag

  • 案例

    • jsp

        <body>
          <albin:if test="${10>5}">
              条件成立
          </albin:if>
        </body>
      
    • tld

        <tag>
          <name>if</name>
          <tag-class>gz.albin.b_cases.IfTag</tag-class>
          <body-content>scriptless</body-content>
          <attribute>
              <name>test</name>
              <required>true</required>
              <rtexprvalue>true</rtexprvalue>
          </attribute>
        </tag>
      
    • java

      public class IfTag extends SimpleTagSupport {
          private boolean test;
      
          public void setTest(boolean test) {
              this.test = test;
          }
      
          @Override
          public void doTag() throws JspException, IOException {
              //根据test的返回值决定是否输出标签体内容
              if(test){
                  this.getJspBody().invoke(null);
              }
          }
      }
      

自定义ForEach标签

  • 案例

    • jsp

       <albin:forEach items="${list}" var="student">
              姓名:${student.name } - 年龄:${student.age }<br/>
       </albin:forEach>
      
       <hr/>
      
       <albin:forEach items="${map}" var="entry">
            编号:${entry.key} - 姓名:${entry.value.name} - 年龄:${entry.value.age }<br/>
       </albin:forEach>
      
    • tld

       <tag>
          <name>forEach</name>
          <tag-class>gz.albin.b_cases.ForEachTag</tag-class>
          <body-content>scriptless</body-content>
          <attribute>
              <name>items</name>
              <required>true</required>
              <rtexprvalue>true</rtexprvalue>
          </attribute>
          <attribute>
              <name>var</name>
              <required>true</required>
              <rtexprvalue>false</rtexprvalue>
          </attribute>
        </tag>
      
    • java

      public class ForEachTag extends SimpleTagSupport {
          private Object items;//需要遍历的数据.List和map
          private String var;//每个元素的名称
      
          public void setItems(Object items) {
              this.items = items;
          }
      
          public void setVar(String var) {
              this.var = var;
          }
      
          @Override
          public void doTag() throws JspException, IOException {
              //遍历items数据
              //List
              /*PageContext pageContext = (PageContext)this.getJspContext();
              if(items instanceof List){
                  List list = (List)items;
                  for (Object object : list) {
                      //把每个对象放入域对象中(pageContext)
                      pageContext.setAttribute(var, object);
                      //显示标签体内容
                      this.getJspBody().invoke(null);
                  }
              }
      
              //Map
              if(items instanceof Map){
                  Map map = (Map)items;
                  Set<Entry> entrySet = map.entrySet();
                  for(Entry entry :entrySet){
                      //把每个对象放入域对象中(pageContext)
                      pageContext.setAttribute(var, entry);
                      //显示标签体内容
                      this.getJspBody().invoke(null);
                  }
              }*/
      
      
              //简化代码
              //思路: 
                  //1)list         -> Collection
                  //2) map.entrySet -> Collection
              PageContext pageContext = (PageContext)this.getJspContext();
              Collection colls = null;
              if(items instanceof List){
                  colls = (List)items;
              }
              if(items instanceof Map){
                  Map map = (Map)items;
                  colls = map.entrySet();
              }
      
              for(Object object:colls){
                  //把每个对象放入域对象中(pageContext)
                  pageContext.setAttribute(var, object);
                  //显示标签体内容
                  this.getJspBody().invoke(null);
              }
          }
      }
      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值