欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

JSP模板应用指南(下)

程序员文章站 2024-02-25 20:00:15
执行模板   这里所讨论的模板将在三种定制标签下执行:   template: insert   template: put   template: get   inser...
执行模板
  这里所讨论的模板将在三种定制标签下执行:

  template: insert

  template: put

  template: get

  insert 标签中包含一个模板,但是在包含之前,put 标签存储有一些信息——name, uri和boolean 值(用来指定将内容是包含还是直接显示)——关于模板所包含的内容。在template:get中包含(或显示)了指定的内容,随后将访问这些信息。

  template:put 把bean 存储在请求区域(但并不直接存储),因为如果两个模板使用了相同的内容名,一个嵌套模板就将覆盖封装模板中的内容。

  为了保证每一个模板能够只存取它自己的信息,template:insert 保留了一个hashtable堆栈。每一个insert 开始标签建立一个 hashtable并把它放入堆栈。封装的put 标签建立bean并把它们保存到最近建立的hashtable中。随后,在被包含模板中的 get 标签访问hashtable中的bean。图 4 显示了堆栈是如何被保留的。


  图 4. 在请求区域存储模板参数 点击放大(24 kb)

  在图 4中每一个模板访问正确的页脚、footer.html 和footer_2.html。如果 bean被直接存储在请求区域,图 4中的step 5将覆盖在step 2中指定的footer bean。

模板标签执行
  接下来我们将分析三个模板标签的执行: insert, put和get。我们先从图 5开始。这个图表说明了当一个模板被使用时,insert和put标签事件的执行顺序。


  图 5. put和insert 标签执行顺序 点击放大(24 kb)

  如果一个模板堆栈已经不存在,insert 开始标签就会建立一个并把它放置到请求区域。随后一个hashtable也被建立并放到堆栈中。

  每一个 put 开始标签建立一个pageparameter bean,并存储在由封装的insert标签建立的hashtable中。

  插入 end 标签包含了这个模板。这个模板使用get标签来访问由put标签建立的bean。在模板被处理以后,由insert 开始标签建立的hashtable就从堆栈中清除。

  图 6显示template:get的顺序图表。


  图 6. get标签的顺序图表 点击放大(11 kb)

模板标签列表
  标签handler很简单。在例 3.a中列出了insert标签类——标签handler。

  例 3.a. inserttag.java

  packagetags.templates;

  import java.util.hashtable;

  import java.util.stack;

  import javax.servlet.jsp.jspexception;

  import javax.servlet.jsp.pagecontext;

  import javax.servlet.jsp.tagext.tagsupport;

  public class inserttagextendstagsupport {

   private stringtemplate;

   private stack stack;

   // setter method fortemplate 属性

   public void settemplate(stringtemplate) {

     this.template =template;

   }

   public int dostarttag() throws jspexception {

     stack = getstack(); // obtain a reference to thetemplate stack

     stack.push(new hashtable()); // push new hashtable onto stack

     return eval_body_include; // pass tagbody through unchanged

   }

   public int doendtag() throws jspexception {

     try {

       pagecontext.include(template); // includetemplate

     }

     catch(exception ex) { // ioexception or servletexception

       throw new jspexception(ex.getmessage()); // recast exception

     }

     stack.pop(); // pop hashtable off stack

     return eval_page; // evaluate the rest of the page after the tag

   }

   // taghandlers should always implement release() because

   // handlers can be reused by the jsp container

   public void release() {

     template = null;

     stack = null;

   }

   public stack getstack() {

     // try to get stack from request scope

     stack s = (stack)pagecontext.get属性(

              "template-stack",

              pagecontext.request_scope);

     // if the stack's not present, create a new one和

     // put it into request scope

     if(s == null) {

       s = new stack();

       pagecontext.set属性("template-stack", s,

              pagecontext.request_scope);

     }

     return s;

   }

  }

  例 3.b 列出了 put标签类和标签handler:

  例 3.b. puttag.java

  packagetags.templates;

  import java.util.hashtable;

  import java.util.stack;

  import javax.servlet.jsp.jspexception;

  import javax.servlet.jsp.tagext.tagsupport;

  import beans.templates.pageparameter;

  public class puttagextendstagsupport {

   private string name, content, direct="false";

   // setter methods for put tag attributes

   public void setname(string s) { name = s; }

   public void setcontent(string s) {content = s; }

   public void setdirect(string s) { direct = s; }

   public int dostarttag() throws jspexception {

     // obtain a reference to enclosing insert tag

     inserttagparent = (inserttag)getancestor(

                 "tags.templates.inserttag");

     // puttags must be enclosed in an insert tag

     if(parent == null)

       throw new jspexception("puttag.dostarttag(): " +

                  "no inserttagancestor");

     // gettemplate stack from insert tag

     stacktemplate_stack = parent.getstack();

     //template stack should never be null

     if(template_stack == null)

       throw new jspexception("puttag: notemplate stack");

     // peek at hashtable on the stack

     hashtable params = (hashtable)template_stack.peek();

     // hashtable should never be null either

     if(params == null)

       throw new jspexception("puttag: no hashtable");

     // put a new pageparameter in the hashtable

     params.put(name, new pageparameter(content, direct));

     return skip_body; // not interested in tagbody, if present

   }

   // taghandlers should always implement release() because

   // handlers can be reused by the jsp container

   public void release() {

     name = content = direct = null;

   }

   // convenience method for finding ancestor names with

   // a specific class name

   privatetagsupport getancestor(string classname)

                   throws jspexception {

     class klass = null; // can't name variable "class"

     try {

       klass = class.forname(classname);

     }

     catch(classnotfoundexception ex) {

       throw new jspexception(ex.getmessage());

     }

     return (tagsupport)findancestorwithclass(this, klass);

   }

  }

  puttag.dostarttag建立了一个 pageparameter bean – 在例 3.c中列出——然后存储到请求区域。

  例 3.c. pageparameter.java

  package beans.templates;

  public class pageparameter {

   private string content, direct;

   public void setcontent(string s) {content = s; }

   public void setdirect(string s) { direct = s; }

   public string getcontent() { return content;}

   public boolean isdirect() { return boolean.valueof(direct).booleanvalue(); }

   public pageparameter(string content, string direct) {

     this.content = content;

     this.direct = direct;

   }

  }

  pageparameter将作为简单的占位符使用。我们来看一看例 3.d中的gettag类和tag handler:

  例 3.d. gettag.java

  packagetags.templates;

  import java.util.hashtable;

  import java.util.stack;

  import javax.servlet.jsp.jspexception;

  import javax.servlet.jsp.pagecontext;

  import javax.servlet.jsp.tagext.tagsupport;

  import beans.templates.pageparameter;

  public class gettagextendstagsupport {

   private string name;

   // setter method for name attribute

   public void setname(string name) {

     this.name = name;

   }

   public int dostarttag() throws jspexception {

     // obtain reference totemplate stack

     stack stack = (stack)pagecontext.get attribute (

         "template-stack", pagecontext.request_scope);

     // stack should not be null

     if(stack == null)

       throw new jspexception("gettag.dostarttag(): " +

                   "no stack");

     // peek at hashtable

     hashtable params = (hashtable)stack.peek();

     // hashtable should not be null

     if(params == null)

       throw new jspexception("gettag.dostarttag(): " +

                   "no hashtable");

     // get page parameter from hashtable

     pageparameter param = (pageparameter)params.get(name);

     if(param != null) {

       string content = param.getcontent();

       if(param.isdirect()) {

        // print content if direct attribute is true

        try {

         pagecontext.getout().print(content);

        }

        catch(java.io.ioexception ex) {

         throw new jspexception(ex.getmessage());

        }

       }

       else {

        // include content if direct attribute is false

        try {

         pagecontext.getout().flush();

         pagecontext.include(content);

        }

        catch(exception ex) {

         throw new jspexception(ex.getmessage());

        }

       }

     }

     return skip_body; // not interested in tagbody, if present

   }

   // taghandlers should always implement release() because

   // handlers can be reused by the jsp container

   public void release() {

     name = null;

   }

  }

  gettag.dostarttag从请求区域返回了页面参数bean并从bean中获得了content和direct 属性。然后,内容可以根据direct属性值选择是被包含还是显示。

结论
  模板是一种简单而有非常有用的概念。模板的封装布局能够对布局改变的影响达到最小化。而且模板能够根据用户的不同来区分不同的内容,它还能够嵌套到其他的模板和jsp页面中。

  <全文完>