专栏首页专注 Java 基础分享Java ---自定义标签(二)

Java ---自定义标签(二)

     上篇文章的最后,我们自定义了一个带属性的标签,并使用它完成了一个简单的案例。其实到这我们已经可以看出来,前端jsp页面只需要写一个类似html语法的标签,就可以完成将集合中的数据取出来并展示这么相对复杂的操作。这就是我们使用标签的意义。接着上篇文章,我们看看怎么自定义一个带有标签体的标签。

一、开发带标签体的标签      我们可以利用标签体来简化我们上一个案例中的标签处理类。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib uri="mytid" prefix="mytag"%>
<html>
  <head>
    <title></title>
  </head>
  <body>
  <%
    HashMap<String,Integer> maps = new HashMap<String, Integer>();
    maps.put("李四",53);
    maps.put("张三",23);
    maps.put("walker",22);
    pageContext.setAttribute("map",maps);
  %>
      <table>
        <mytag:hello map="map">
            <tr>
              <td>${name}</td>
              <td>${age}</td>
            </tr>
        </mytag:hello>
      </table>
  </body>
</html>
<tag>
        <description>Outputs a colored tile</description>
        <name>hello</name>
        <tag-class>Test.MyTag</tag-class>
        <body-content>scriptless</body-content>
        <attribute>
            <name>map</name>
            <required>false</required>
            <fragment>true</fragment>
        </attribute>
    </tag>
public void doTag() throws JspException, IOException {
        HashMap<String,Integer> maps = (HashMap<String,Integer>)(getJspContext().getAttribute(map));
        for (String str : maps.keySet()){
            getJspContext().setAttribute("name",str);
            getJspContext().setAttribute("age",maps.get(str));
            getJspBody().invoke(null);

        }
    }

有些并没有改动的代码没有列出,只展示了关键的代码块。首先看jsp页面,有标签体的标签使用的时候是需要有开始标签和结束标签的,这一点是和html很像的。至于td元素中的内容,这是一个EL表达式,不知道的朋友可以快速百度下,这里的意思就是在当前页面寻找共享数据名为name和age的数据,找到就获取其值,否则为“”,非null。tld文件中的改动不多,就是将body-content的值改动成scriptless,这表示标签体可以是静态的html,但是不能是jsp脚本。而我们之前一直是empty,它指定该标签是没有标签体的。      接下来看看我们标签处理类的改动,原先冗长的输出代码,被替换成以下三条语句:

getJspContext().setAttribute("name",str);
getJspContext().setAttribute("age",maps.get(str));
getJspBody().invoke(null);

前面两条语句很简单,在jsp页面设置page范围内的共享数据,主要是提供我们的标签中EL表达式使用。getJspBody()表示获取整个标签体的所有内容,返回的是一个fragment对象,这个对象的一个方法invoke就是用于输出整个内容到jsp页面,如果参数为null表示直接输出,还可以使用Writer作为参数传入,意思是将标签体的内容全部输入到这个字符流中,然后你可以通过一些操作,再次使用write方法输出到jsp页面。也就是说,如果对于标签体中的数据内容需要做一些判断操作的话,可以传递一个writer流,处理完成之后可以再次输出到页面上。

二、开发以页面片段为属性的标签      我们的attribute可以上八种数据类型,因为jsp引擎是可以为我们自动转换并自动赋值到我们标签处理类的私有属性中,但是对于之外的类型都是不可以直接操作的,我们首先看如何以页面片段作为属性,传递。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib uri="mytid" prefix="mytag"%>
<html>
  <head>
    <title></title>
  </head>
  <body>
      <mytag:hello>
          <jsp:attribute name="map">
              <h1>hello</h1>
          </jsp:attribute>
      </mytag:hello>
  </body>
</html>

我们使用jsp:attribute这个动作指令来完成给属性赋值上页面片段,name的值对应于tld中的属性name值。

<tag>
        <description>Outputs a colored tile</description>
        <name>hello</name>
        <tag-class>Test.MyTag</tag-class>
        <body-content>empty</body-content>
        <attribute>
            <name>map</name>
            <required>false</required>
            <fragment>true</fragment>
        </attribute>
    </tag>

对于jsp页面以页面片段作为属性传入的参数,我们在标签处理类中是需要定义私有属性来接受的,在jsp中将页面片段定义为jspfregment类型,于是我们定义私有属性。

public class MyTag extends SimpleTagSupport {

    private JspFragment map;
    public JspFragment getMap(){
        return this.map;
    }
    public void setMap(JspFragment map){
        this.map = map;
    }
    @Override
    public void doTag() throws JspException, IOException {
        map.invoke(null);
    }
}

调用JspFragment 的invoke方法可以直接输出其中的内容。结果如下:

     稍微小结一下,之前我们传递属性值的时候是在标签名的后面添加属性名和属性值,但那时的属性值只限于字符串,你不能传递别的类型的内容。此处我们为了能够传递页面片段,通过jsp:attribute动作指令来给我们的属性赋值,而这个值的内容就是一个页面片段。上文中我们在介绍自定义标签体的时候,我们说可以使用getJspBody可以获得标签体的内容,其实这个方法返回的也是一个fregment,所以我们可以调用invoke方法输出标签体内容。

三、开发动态属性标签      在我们之前介绍的内容中,传递的属性个数都是固定的,但是在实际开发中往往又会遇到有些参数必须传入有些选择性的传入,这样每个人传递的属性的个数都是不一样的,服务器端该如何处理呢?我们可以使用动态属性标签,使用此标签之前,我们的标签处理类就必须要继承接口DynamicAttributes,这个接口中就只有一个方法,setDynamicAttribute这个方法就是来完成动态的给我们传递的属性赋值。这是第一点,第二点就是需要在tld文件中配置一条语句,表名这个tag是支持动态属性的。下面是demo:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib uri="mytid" prefix="mytag"%>
<html>
  <head>
    <title></title>
  </head>
  <body>
      <mytag:hello name="张三" age="23"/><hr/>
      <mytag:hello name="张三" age="23" student="ok"/><hr/>
      <mytag:hello name="张三" age="23" walker="yam"/>
  </body>
</html>
<tag>
        <description>Outputs a colored tile</description>
        <name>hello</name>
        <tag-class>Test.MyTag</tag-class>
        <body-content>scriptless</body-content>
        <dynamic-attributes>true</dynamic-attributes>
    </tag>
public class MyTag extends SimpleTagSupport implements DynamicAttributes{
    private ArrayList<String> keys = new ArrayList<String>();
    private ArrayList<Object> values = new ArrayList<Object>();

    @Override
    public void doTag() throws JspException, IOException {
        for(int i=0;i<keys.size();i++){
            getJspContext().getOut().write(""+keys.get(i)+values.get(i));
        }
    }
    @Override
    public void setDynamicAttribute(String var1, String var2, Object var3) throws JspException{
            keys.add(var2);
            values.add(var3);
    }
}

做一点解释,setDynamicAttribute这个方法中有三个参数,我们通常只使用后面两个参数,一个代表属性名,一个代表属性值。那么第一个参数表示什么意思呢?官方解释是:

uri - -the namespace of the attribute, or null if in the default namespace.

这是该属性的命名空间,如果没有显式指定就是null。我们暂时可以不用关心。

     最后还是要强调一点,属性的的只能使基本的数据类型,对于一些复杂的类型 ,例如Date,等,建议将该对象置于本页共享范围,然后标签处理类可以直接获取并做相应的处理。

     自定义标签介绍完了,如有错误,望指出!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • struts2标签库----数据标签详解

         上篇文章我们介绍struts2标签库中的控制标签的基本使用和部分原理,本篇文章接着了解下标签库中有关数据标签的使用和原理。主要涉及以下数据标签: ac...

    Single
  • Java ---自定义标签

         本篇文章介绍自定义标签,可能在工作中很少涉及到自己来定义一个标签库,因为我们基本上都是使用的大神写的标签库,基本上直接使用即可,但是从自身的发展来看,...

    Single
  • struts2标签库----控制标签详解

         前面几篇文章我们介绍了有关struts2的基本内容,简单理解了整个框架的运作流程。从本篇开始我们逐渐了解和使用struts2为我们提供的标签库技术,使...

    Single
  • struts2标签库----数据标签详解

         上篇文章我们介绍struts2标签库中的控制标签的基本使用和部分原理,本篇文章接着了解下标签库中有关数据标签的使用和原理。主要涉及以下数据标签: ac...

    Single
  • 软银领投,9300万美元豪掷CMU邢波机器学习初创公司Petuum

    【新智元导读】新智元获官方消息,专注于机器学习基础架构平台开发的初创公司Petuum日前完成金额高达9300万美元的B轮融资,由软银领投,现Petuum融资总额...

    新智元
  • 【前端词典】学习 Vue 源码的必要知识储备

    我最近在写 Vue 进阶的内容。在这个过程中,有些人问我看 Vue 源码需要有哪些准备吗?所以也就有了这篇计划之外的文章。

    小生方勤
  • [源码解析] GroupReduce,GroupCombine 和 Flink SQL group by

    本文从源码和实例入手,为大家解析 Flink 中 GroupReduce 和 GroupCombine 的用途。也涉及到了 Flink SQL group by...

    罗西的思考
  • 预学二:计算机的基础知识+python安装+pycharm安装+思维导图

    根据当前系统的选择对用的,红色的是windows32位,绿色的是windows64位

    changxin7
  • HTML标签

    白胡杨同学
  • [mini-blog][v1.6.0]体现后台管理功能的价值时刻到了——丰富文章的筛选

    这次改版,用户最直观的效果就是可以对文章进行筛选了,最早期的一版,只能通过简单的搜索框进行筛选:

    Bug生活2048

扫码关注云+社区

领取腾讯云代金券