自定义JSP标签(带有属性)

1. 自定义标签运行原理

    自定义标签是用户定义的JSP语言元素。当JSP页面包含一个自定义标签时将被转化为servlet,标签转化为对被

    称为tag handler的对象的操作,即当servlet执行时Web container调用那些操作。

2. 两种标签

    可以定义两种类型的标签:
    (1) javax.servlet.jsp.tagext.Tag
    (2) javax.servlet.jsp.tagext.BodyTag

    有标签体的标签必须实现 BodyTag 接口, 无标签体的简单标签可以实现 Tag 接口。

3. 标签处理程序
    int doStartTag() throws JspException---处理开始标签
    int doEndTag() throws JspException---处理结束标签
    Tag getParent()/void setParent(Tag t)---获得/设置标签的父标签
    void setPageContext(PageContext pc)--- pageContext 属性的 setter 方法
    void release() 释放获得的所有资源

 

    doStartTag()和doEndTag()方法的返回值说明:
    SKIP_BODY      表示不用处理标签体,直接调用doEndTag()方法。
    SKIP_PAGE       忽略标签后面的jsp(SUN企业级应用的首选)内容。
    EVAL_PAGE      处理标签后,继续处理jsp(SUN企业级应用的首选)后面的内容。
    EVAL_BODY_BUFFERED   表示需要处理标签体,且需要重新创建一个缓冲(调用setBodyContent方法)。
    EVAL_BODY_INCLUDE  表示在现有的输出流对象中处理标签体,但绕过setBodyContent()和doInitBody()方法
    EVAL_BODY_AGAIN     对标签体循环处理。(存在于javax.servlet.jsp.tagext.IterationTag接口中)

 

    实现javax.servlet.jsp.tagext.Tag接口或扩展javax.servlet.jsp.tagext.TagSupport类:
    TagSupport 类定义了 get/setParent() 和 setPageContext(),这与所有标签处理程序几乎相同。get/setParent()

    方法允许标签嵌套。
    TagSupport 类还定义了一个可以被子类使用的 pageContext 实例变量 (protected PageContext pageContext),

    这个变量是由 setPageContext() 方法设置的。

 

    在创建自定义标签之前,需要创建一个 标签处理程序。标签处理程序是一个执行自定义标签操作的 Java 对象。

    在使用自定义标签时,要导入一个 标签库 —— 即一组标签/标签处理程序对。通过在 Web 部署描述符中声明库导

    入它,然后用指令 taglib 将它导入 JSP 页。

    <%@ taglib prefix="util" uri="http://org.dmwdp.pem/tag/util-1.0" %>

 

    如果 JSP 容器在转换时遇到了自定义标签,那么它就检查 标签库描述符(tag library descriptor) (TLD) 文件

    以查询相应的标签处理程序。TLD 文件对于自定义标签处理程序,就像 Web 部署描述符对于 servlet 一样。

    在运行时,JSP 页生成的 servlet 得到对应于这一页面所使用的标签的标签处理程序的一个实例。生成的 servlet 用

    传递给它的属性初始化标签处理程序。
    标签处理程序实现了 生存周期 方法。生成的 servlet 用这些方法通知标签处理程序应当启动、停止或者重复自定义

    标签操作。生成的 servlet 调用这些生存周期方法执行标签的功能。

4. TLD 文件

     TLD文件的根元素是 taglib。

     taglib 描述了一个 标签库 —— 即一组标签/标签处理程序对。
     因为使用的是 JSP 版本 1.2,所以在这个例子中需要 tlib-version 和 short-name 元素。
     tlib-version 元素对应于标签库版本。
     jsp-version 对应于标签库所依赖的 JSP 技术的版本。
     short-name 元素定义了 IDE 和其他开发工具可以使用的标签库的简单名。
     taglib 元素包含许多 tag 元素,标签库中每一个标签有一个 tag 元素。

5. 案例实战

     (1) TLD文件:utilTag.tld

     <?xml version="1.0" encoding="UTF-8"?>
     <!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.0</tlib-version>
                  <jsp-version>1.2</jsp-version>
                  <short-name>util</short-name>
                  <uri>http://com.zskx.pem/tag/util-1.0</uri>

                 <tag>
                       <name>domainUrl</name>
                       <tag-class>com.dmwdp.network.biz.commons.taglib.DomainUrlTag</tag-class>
                       <body-content>empty</body-content>
                       <attribute>
                           <name>imgUrl</name>
                           <required>true</required>
                           <rtexprvalue>true</rtexprvalue>
                      </attribute>
                 </tag>   
            </taglib>

    (2) web.xml配置

    ......

    <jsp-config>
        <taglib>
            <taglib-uri>util</taglib-uri>
            <taglib-location>/WEB-INF/taglib/utilTag.tld</taglib-location>
        </taglib>
    </jsp-config>

   ......

   (3) 标签处理类

   public class DomainUrlTag extends TagSupport {

             private static final Logger LOGGER = Logger.getLogger(DomainUrlTag.class);
             private static final long serialVersionUID = 8662373418251060423L;

             private String imgUrl;

             public void setImgUrl(String imgUrl) {
                    this.imgUrl = imgUrl;
             }

             public DomainUrlTag() {
             }

             @Override
             public int doStartTag() throws JspTagException {
                 //表示在现有的输出流对象中处理标签体,但绕过setBodyContent()和doInitBody()方法
                 return EVAL_BODY_INCLUDE;
             }

             @Override
             public int doEndTag() throws JspException {
                     if (StringUtils.isBlank(imgUrl)) {
                          return EVAL_PAGE;
             }

             String[] imgServers = ImagePropertiesReader.getImageServerURLs();
             int imgUrlCount = imgServers.length;

             int serverNum = Math.abs((imgUrl.hashCode() % imgUrlCount));

             String resultUrl = null;
             for (int i = 0; i < imgUrlCount; i++) {
                  if (serverNum == i) {
                         resultUrl = imgServers[i];
                         break;
                   }
             }
             outPutResultUrl(resultUrl);

             return EVAL_PAGE;
          }

          private void outPutResultUrl(String resultUrl) {
                  if (StringUtils.isBlank(resultUrl)) {
                       return;
           }

           try {
                    pageContext.getOut().write(resultUrl);
           } catch (IOException e) {
                  if (LOGGER.isDebugEnabled()) {
                       LOGGER.debug("Customize Tag error", e);
                  }
           }
       }
   }

   (4) 页面使用

   <%@ taglib prefix="util" uri="http://com.zskx.pem/tag/util-1.0" %>

   <link rel="shortcut icon" href="<util:domainUrl imgUrl='/pem.ico'/>/dmwdp.ico" />

   (5) ImagePropertiesReader.java

   public class ImagePropertiesReader {
        private static final Logger LOGGER = Logger.getLogger(ImagePropertiesReader.class);
        private static Properties props = new Properties();

        private ImagePropertiesReader() {

        }

        static {
               try {
                      final InputStream tempIn = ImagePropertiesReader.class.getResourceAsStream("/image.properties");
                      props.load(tempIn);
               } catch (Exception e) {
                      if (LOGGER.isDebugEnabled()) {
                          LOGGER.debug("ImagePropertiesReader error", e);
                      }
               }
         }

         public static String[] getImageServerURLs() {
                 String imgUrlStr = props.getProperty(Constant.DMWDP_IMAGE_SERVER_URLS);
                 return imgUrlStr.split(",");
         }

   }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值