让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类
最后修改#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
这就是一个可以完全使用相对路径的方法了,包括子页面嵌入其他的子页面,而不会造成使用的困扰。