让Web项目中Velocity的#parse支持相对路径

 

下面这个宏可以让你在web项目中使用相对路径来包含其他的模板文件

#macro(invoke $page)
    #if($page.startsWith("/"))
        #parse($page)
    #else
        #set($uri = $request.getAttribute("javax.servlet.include.request_uri"))
        #if(!$uri)#set($uri = $request.getServletPath())#end
        #set($path = $uri.substring(0, $uri.lastIndexOf("/")))
        #parse("$path/$page")
    #end
#end

把这段代码加在VM_global_library.vm中,你就可以在页面模板中用#invoke("head.vm")来在页面中嵌入其他的模板文件,比起用#parse指定绝对路径省事很多。

不过这种做法有一个缺点:当子页面还欠有其他页面的时候,相对路径就有点问题,是相对于主页面而非当前页面,这也会给使用上造成一些困扰,但解决的办法还是有的,相对比较复杂而已。

首先我们需要编写一个Toolbox类,例如MyVelocityTool,该类实现接口ViewTool,代码如下:

public class MyVelocityTool implements ViewTool {

 protected HttpServletRequest request;
 protected HttpServletResponse response;
 protected ServletContext context;
 protected VelocityContext velocity;

 /*
  * Initialize toolbox
  * @see org.apache.velocity.tools.view.tools.ViewTool#init(java.lang.Object)
  */
 public void init(Object arg0) {
  if(arg0 instanceof ViewContext){
   ViewContext viewContext = (ViewContext) arg0;
   request = viewContext.getRequest();
   response = viewContext.getResponse();
   context = viewContext.getServletContext();
   velocity = (VelocityContext)viewContext.getVelocityContext();
  }
  else if(arg0 instanceof ServletContext){
   context = (ServletContext)arg0;
  }
 }

 public String current_template(){
  return velocity.getCurrentTemplateName();
 }
}

接着在velocity-toolbox.xml中定义这个Toolbox类

 
     dlog
     request
     com.liusoft.dlog4j.DLOG_VelocityTool
 

最后修改#invoke宏如下:

#macro(invoke $page)
    #if($page.startsWith("/"))
        #parse($page)
    #else
        #set($uri = $dlog.current_template())
        #set($path = $uri.substring(0, $uri.lastIndexOf("/")))
        #parse("$path/$page")
    #end
#end

这就是一个可以完全使用相对路径的方法了,包括子页面嵌入其他的子页面,而不会造成使用的困扰。

posted @ 2008-02-05 11:21  lovingprince  阅读(3405)  评论(0编辑  收藏  举报