现在的位置: 首页 > 综合 > 正文

用户自定义标签

2013年03月25日 ⁄ 综合 ⁄ 共 5001字 ⁄ 字号 评论关闭

J2EE项目中,JSP页面常常通过在静态页面模板中嵌入scriptlets来插入动态的内容。然而,随着复杂程序的增加,JSP页面也变得难于管理。 虽然用这种方法开发小形项目唾手可得,但是scriptlets仍然要面对下面的不利情况:

  • Scriptlet难于阅读和修改。带有ScriptletsJSP页面混合了两种语言,这使得阅读和维护变得很困难。

  • Scriptlets鼓励了将数据表现和逻辑处理的混合 。JSP页面主要功能是数据表现而不是逻辑处理。逻辑处理属于Java类的工作,他们应该由程序员维护并能够重用。

  • Scriptlets不能够被重用。当scriptlets被重用时,常常是鼓励拷贝-粘贴来达到重用的效果,这是一种危险的维护方法。每一次你拷贝-粘贴scriptlets,将有更多行多余的代码需要维护。

  • Scriptlets的参数很难进行确定传递. 无论如何,绝大数人简单的拷贝,粘贴、编辑或者类似的增加,使得大部份的多余的代码需要更多的维护。

与其创建充满了scriptlets的巨大的JSP页面,不如考虑使用用户自定义标签。用户自定义标签允许你创建、在JSP中使用你自己定义的类HTML标签。每当JSP引擎遇到用户自定义标签时,就会自动查找标签处理类,并自动调用他。页面中的自定义标签将会被票签处理类的输出所代替。这就使得JSP页面不用直接在页面写Java代码,就可以指定生成动态的内容的。

用户自定义标签为你的网页设计提供了N种好处:他提高了页面代码的可读性。页面设计人员而不是程序员,能够使用很比使用Scriptlets更容易的使用标签。维护代码的程序员也只需个性标签库面不是JSP页面,这样他就不要再冒着破坏页面美观的风险。 在使用标签的每一处,增强或者固定的标签改变了标签了的表现。标签比Scriptlets更容易确定参数,因为他会被 作为一种属性或者在标签体内被传达。最后,标签比Scriptlets高度的可重用性,因为你可以创建共享的、可重用的自定义标签库。 JSTL提供的就是这种标准的自定义标签集。

让我们通过看一个简单的JSP页面例子,来看看如何使用自定义标签。 下面这个页面使用scriptlet来得到数据:

<%@ page import="java.text.SimpleDateFormat" %>

<%@ page import="java.util.Date" %>

<HTML>

<HEAD><TITLE>Sample JSP</TITLE></HEAD>

<BODY>

<H3>

The date and time at the server are:

<%

String sformat = "EEEE, d MMMM yyyy 'at' kk:mm:ss z";

SimpleDateFormat format = new SimpleDateFormat(sformat);

Date date = new Date();

String sdate = format.format(date);

out.print(sdate);

%>

</H3>

</BODY>

</HTML>

 

这个页面非常的简单直接,尽管这个简单的函数看上去好像有许多东东。如果你想要在每一个页面上显示日期,那么你只能拷贝粘贴这段代码到项目中的每一个页面。如果你这么做,那么你要维护的不仅仅是这段代码的原始拷贝,而是你粘贴的每一个拷贝。 如果这段代码出现在多个页面,那么改变一下时间格式将会占用你的很多时间。

下面这段是一个非常清洁的JSP页面。在这里,Java代码被从scriptlet中移出放到了自定义标签中:

<%@ taglib uri="/WEB-INF/taglib.tld" prefix="mytags" %>

 

<HTML>

<HEAD><TITLE>Sample JSP using a custom tag</TITLE></HEAD>

<BODY>

<H3>

The date and time at the server are: <mytags:date/>

</H3>

</BODY>

</HTML>

在这个例子中,<@% taglib %>用来指出自定义标签描述符文件路径(标签库中的描述符或者TLD文件),并且为这个标签名定义一个名字空间(“mytags”,可是你喜欢的任何字符)JSP引擎认可<mytags:date/>作为一个用户定义标签的符号,他会调用这个标签的标签处理器,并用处理结果替换标签和内容。

创建一个用户定义标签处理器

创建一个用户定义标签处理器需要比定scriptlet多一定量的工作,因为这一个Java类,并且你不得不为他写一个TLD格式(在下一节介绍)的描述符文件。下面这个类DataTag实现了一个标签处理器:

public class DateTag extends TagSupport {

 

  protected PageContext _pageContext;

  protected String _sFormat;

  static final String _sFormatDefault =

  "EEEE, d MMMM yyyy 'at' kk:mm:ss z";

 

  public void setPageContext(PageContext pageContext) {

    _pageContext = pageContext;

    _sFormat = _sFormatDefault;

  }

 

  // Handle the tag

  public int doStartTag() throws JspException {

    SimpleDateFormat format =

      new SimpleDateFormat(getFormat());

    JspWriter out = _pageContext.getOut();

    Date date = new Date();

    String sdate = format.format(date);

    try {

      out.print(sdate);

    } catch (IOException ex) {

      throw new JspException("DateTag: can't write: " +

             ex.getMessage());

    }

    return SKIP_BODY;

  }

 

  // Handlers for "format" attribute

  public void setFormat(String sFormat) {

    _sFormat = sFormat;

  }

 

  public String getFormat() {

    return _sFormat;

  }

}

TagSupport实现了标签处理器要求的所有接口。这些方法本来没有做什么任何事,标签处理器开发人员重构了需要方法,允许基类处理调用所有的其他的方法。标签处理器每一次被调用都会调setPageContext方法。 这个类为稍后便用简单的保存了PageContext参照。

JSP引擎遇到这个标签时会调用doStartTag方法。这个方法和第1个版本JSP页面的scriptlet处理了相同的事。他将结果写回给JspWriter,结果包括了先存储的PageContext.所有写给JspWriter的内容,会被直接嵌入到响应页面。 注意doStartTag只能抛出JspException异常。如果发生写失败,那么原始IOException会被转化成一个JspException重新抛出。这个方法会返回SKIP_BODY,他告诉JSP容器抛弃标签内容。

标签处理器最后的两个方法是setFormatgetFormat。机敏的读者应该已经知道了他作用。 他被网页容器用来设置标签属性值(后面进行更详细的讨论)。在这儿他们被用来设定日期格式属性和输出日期格式属性。

标签定义:TLD文件

一个标签库描述符文件, 或者TLD文件, 是一个XML文件。他用来描述标签库中的标签。以下是DateTag标签的描述文件。

<?xml version="1.0" encoding="ISO-8859-1"?>

 

<!DOCTYPE taglib

        PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"

        "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">

 

<taglib>

   <tlib-version>1.0</tlib-version>

   <jsp-version>1.2</jsp-version>

   <short-name>first</short-name>

   <uri>http://www.elucify.com/j2eetips/sept2002/taglib</uri>

   <description>Sample tag library</description>

 

  <tag>

    <name>date</name>

    <tag-class>com.elucify.tips.sep2002.DateTag</tag-class>

    <body-content>empty</body-content>

    <description>Print the date with a compiled-in format</description>

 

    <attribute>

        <name>format</name>

        <required>false</required>

        <rtexprvalue>false</rtexprvalue>

    </attribute>

 

  </tag>        

</taglib>

这些描述符提供了这个标签库的信息。他还提供了每一个标签的如标签名、处理器的类和标签描述的信息。这个文件被用来替换WEB-INF目录下的WAR文件,为JSP页面使用这些标签提供参照。

增加属性

Notice that the TLD file shown above defines an attribute called format. This is the string passed to SimpleDateFormat to control how the date is printed. If a format attribute is present on a date tag, the JSP engine calls setFormat on the handler class. Otherwise, the handler class uses a default format. Attributes provide a great deal of customizability to custom tags. For example, the following JSP page uses the format attribute to format the date in several different ways on the same page:

注意上面这个TLD文件显示的属性调用格式 。这是一个字符串被传递给SimpleDateFormat,来控制如何显示日期。如果一个日期格式被提供给日期标签,那么JSP引擎将调用控制器类中的setFormat方法 ,否则,标签处理器将使用默认格式。属性为用户定义标签提供了大量可定制属性。例如以下这个例子,在同一个页面的, 用几种不同的格式属性来格式化时间。

<%@ taglib uri="/WEB-INF/taglib.tld" prefix="mytags" %>

 

<HTML%>

<HEAD><TITLE%>Sample JSP using a custom tag and format</TITLE%></HEAD%>

<BODY%>

<H3%>

The time zone at the server is <mytags:date format="zzzz"/%>.<br%>

The server date is <mytags:date format="M/d/yyyy"/%>.<br%>

The server time is <mytags:date format="hh:mm:ss a"/%>.<br%>

</H3%>

</BODY%>

</HTML%>

想像一下,如果使用scriptlets,做同样的事情,将会要多少行多余的代码。

抱歉!评论已关闭.