JSP模板应用指南(下)
程序员文章站
2023-12-18 10:34:04
执行模板 这里所讨论的模板将在三种定制标签下执行: 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页面中。
<全文完>
这里所讨论的模板将在三种定制标签下执行:
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页面中。
<全文完>