#define指令的作用刚好是相反的,rewrite实现功能:用任意一个vm来作layout布局,或任意重写layout中的某一部分!
1、修改velocity.properties,添加要自定义的指令的类
# 配制自定义指令所指向的类
userdirective=com.wcsky.common.directive.RewriteDirective
# 配制自定义指令的默认使用参数
userdirective.rewrite.status=false
2、重载Directive的init、render方法:
/**
* 重载init方法,初始自定义指令的配制参数
*/
@Override
public void init(RuntimeServices rs, InternalContextAdapter context, Node node)
throws TemplateInitException {
super.init(rs, context, node);
//指令初始化可调用配制参数
//canRewrite= rs.getBoolean("userdirective.rewrite.status", false);
}
/**
* 重载Directive的render,实现rewrite指令
* usage:
* layout.vm:#rewrite("silder_bar") .... #end
* detail.vm: #rewrite("slider_bar",true) Rewrite Success ! #end
* 输出: Rewrite Success !
*
*/
public boolean render(InternalContextAdapter context, Writer writer,
Node node) throws IOException,
ResourceNotFoundException,ParseErrorException,
MethodInvocationException {
String rewriteKey = DirectiveUtils.getMarcoParam(context, node, 0);
Boolean rewrite = DirectiveUtils.getMarcoParam(context, node, 1);
Node nodeParent = null;
if(rewrite != null && rewrite){
nodeParent = node.jjtGetChild(2);
// 关键:使得父模版可调用子模版的节点
context.put(rewriteKey, nodeParent);
return true;
}else{
nodeParent = (Node)context.get(rewriteKey);
if(nodeParent == null){
nodeParent = node.jjtGetChild(1);
}
}
nodeParent.render(context, writer);
return true;
}
/**
* 获取指令的参数值
* @author Jimmy 2010-4-22
* @param
* @param context
* @param node
* @param paramIndx
* @return 返回参数值
*/
@SuppressWarnings("unchecked")
public static T getMarcoParam(InternalContextAdapter context,
Node node,int paramIndx){
if(node.jjtGetChild(paramIndx) != null){
Node n = node.jjtGetChild(paramIndx);
if(n==null){
return null;
}
return (T) n.value(context);
}
//log.warn("Error: Node "+paramIndx +" is Null");
return null;
}
3、使用场景:
a.在统一布局layout中,在显示详细信息,希望全屏宽显示时,可以把layout中的slider用指令rewrite 定义为可重写,
b、希望某个js脚本或meta,css样式为某个页面所特有,又希望共用同一个layout,可以在子模版rewrite
#rewrite("spec_css",true) <link media="screen" type="text/css" href='$link.themes("blog.css")' rel="stylesheet"> #end