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 条评论
登录 后参与评论

相关文章

来自专栏落花落雨不落叶

canvas画简单电路图

87411
来自专栏hbbliyong

WPF Trigger for IsSelected in a DataTemplate for ListBox items

<DataTemplate DataType="{x:Type vm:HeaderSlugViewModel}"> <vw:HeaderSlug...

4224
来自专栏张善友的专栏

LINQ via C# 系列文章

LINQ via C# Recently I am giving a series of talk on LINQ. the name “LINQ via C...

3025
来自专栏飞扬的花生

jsencrypt参数前端加密c#解密

      写程序时一般是通过form表单或者ajax方式将参数提交到服务器进行验证,如何防止提交的请求不被抓包后串改,虽然无法说绝对安全却给非法提交提高了难度...

4239
来自专栏pangguoming

Spring Boot集成JasperReports生成PDF文档

由于工作需要,要实现后端根据模板动态填充数据生成PDF文档,通过技术选型,使用Ireport5.6来设计模板,结合JasperReports5.6工具库来调用渲...

1.4K7
来自专栏跟着阿笨一起玩NET

c#实现打印功能

3782
来自专栏我和未来有约会

Kit 3D 更新

Kit3D is a 3D graphics engine written for Microsoft Silverlight. Kit3D was inita...

2936
来自专栏一个会写诗的程序员的博客

Spring Reactor 项目核心库Reactor Core

Non-Blocking Reactive Streams Foundation for the JVM both implementing a Reactiv...

2832
来自专栏闻道于事

js登录滑动验证,不滑动无法登陆

js的判断这里是根据滑块的位置进行判断,应该是用一个flag判断 <%@ page language="java" contentType="text/html...

8838
来自专栏张善友的专栏

Miguel de Icaza 细说 Mix 07大会上的Silverlight和DLR

Mono之父Miguel de Icaza 详细报道微软Mix 07大会上的Silverlight和DLR ,上面还谈到了Mono and Silverligh...

3007

扫码关注云+社区