在jsp中实现"类"的继承关系

1.介绍
使用过python django模板的应该清楚,django里面有一个激动人心的功能就是模板可以使用类的继承关系。 即模板是可以继承的,并且不限继承的层次。
1. child.html extends base.html
2. grandchild.html extends child.html
这样,我们在base.html中定义好html布局,然后在“子类”(我们这样称呼吧)重定义需要父页面内容即可
2.jsp继承示例
现在我们来看jsp中如何实现此功能(django与下面的声明类似)。
父页面: base.jsp,定义布局
Jsp代码 
  1. <%@ taglib uri="http://www.rapid-framework.org.cn/rapid" prefix="rapid" %>  
  2. <html>  
  3.    <rapid:block name="head">base_head_content</rapid:block>  
  4. <body>  
  5.    <br />  
  6.    <rapid:block name="content">base_body_content</rapid:block>  
  7. </body>  
  8. </html>  
 
子页面: child.jsp
Jsp代码 
  1. <%@ taglib uri="http://www.rapid-framework.org.cn/rapid" prefix="rapid" %>  
  2. <% //重定义父页面的内容为content的内容 %>  
  3. <rapid:override name="content">  
  4.     child_body_content  
  5. </rapid:override>  
  6.    
  7. <!-- extends from base.jsp -->  
  8. <%@ include file="base.jsp" %>  
 
如上: 我们使用了两个jsp tag: block,override,还有<@include >指令.
下面描述各个功能:
  • override tag:  会将标签里面的内容保存为pageContext的变量,变量名称为name的属性加前缀,如 __override__$name = tag内容
  • block tag:  根据name属性名称,如果发现__override__$name变量,则显示被重定义的内容,否则显示自身tag的内容.
  • <%@include >指令: 通过该指令来实现继承(extends)的功能(只能使用这个技巧),该指令必须放置在页面的最后面 

输出:

直接访问base.jsp输出:
Html代码 
  1. <html>  
  2.  base_head_content  
  3. <body>  
  4.  <br />  
  5.  base_body_content  
  6. </body>  
  7. </html>  
  访问child.jsp输出:
Html代码 
  1. <html>  
  2.  base_head_content  
  3. <body>  
  4.  <br />  
  5.  child_body_content  
  6. </body>  
  7. </html>  
  可以看到,child.jsp的的body输出内容被重定义了.
现该tag可以实现jsp的无限级的继承关系. 即 grandchild.jsp 继承 child.jsp , child.jsp继承 base.jsp 
3.具体实现方式:
Block Tag:
Java代码 
  1. public class BlockTag extends TagSupport{  
  2.    
  3.  private String name;  
  4.    
  5.  public void setName(String name) {  
  6.   this.name = name;  
  7.  }  
  8.    
  9.  @Override  
  10.  public int doStartTag() throws JspException {  
  11.   return getOverriedContent() == null ? EVAL_BODY_INCLUDE : SKIP_BODY;  
  12.  }  
  13.    
  14.  @Override  
  15.  public int doEndTag() throws JspException {  
  16.   String overriedContent = getOverriedContent();  
  17.   if(overriedContent == null) {  
  18.    return EVAL_PAGE;  
  19.   }  
  20.     
  21.   try {  
  22.    pageContext.getOut().write(overriedContent);  
  23.   } catch (IOException e) {  
  24.    throw new JspException("tag output error",e);  
  25.   }  
  26.   return EVAL_PAGE;  
  27.  }  
  28.    
  29.  private String getOverriedContent() {  
  30.   String varName = Utils.getOverrideVariableName(name);  
  31.   return (String)pageContext.getAttribute(varName);  
  32.  }  
  33. }  
  Override Tag:
Java代码 
  1. public class OverrideTag extends BodyTagSupport{  
  2.     
  3.  private String name;  
  4.    
  5.  public void setName(String name) {  
  6.   this.name = name;  
  7.  }  
  8.    
  9.  @Override  
  10.  public int doStartTag() throws JspException {  
  11.   return isOverrided() ? SKIP_BODY : EVAL_BODY_BUFFERED;  
  12.  }  
  13.    
  14.  @Override  
  15.  public int doEndTag() throws JspException {  
  16.   if(isOverrided()) {  
  17.    return EVAL_PAGE;  
  18.   }  
  19.   BodyContent b = getBodyContent();  
  20.   String varName = Utils.getOverrideVariableName(name);  
  21.   pageContext.setAttribute(varName, b.getString());  
  22.   return EVAL_PAGE;  
  23.  }  
  24.    
  25.  private boolean isOverrided() {  
  26.   String varName = Utils.getOverrideVariableName(name);  
  27.   return pageContext.getAttribute(varName) != null;  
  28.  }  
  29.     
  30. }  
  工具类:
Java代码 
  1. class Utils {  
  2.  public static String BLOCK = "__override__";  
  3.  public static String getOverrideVariableName(String name) {  
  4.   return BLOCK + name;  
  5.  }  
  6. }  
 
可以看到,实现代码不需要100行,重要是的实现技巧,由此,你从此可以放弃使用sitemesh. 并且如上实现方式具有更高性能。
并且笔者也扩展了freemarker模板,通过自定义指令,实现如上相同的功能。
 
该内容以后也会随rapid-framework一起发布

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值