skatou@zju 2009-04-27 02:38:42
最近刚开始学习用这两个东西做点东西,既然要做网站很自然就会想到要实现一个可以不同页面共用的layout,于是去google,发现讨论这个东西的都是“进一步提升Struts 2 对Velocity 的支持力度”这篇文章。
文章里面讲了两个方法,一个是直接用VelocityLayoutServlet替换VelocityViewServlet,另一个是自己增加一个VelocityLayoutResult。
不过用这个方法,页面里面往context里面加东西之类的内容#set($var = $value)和对应$screen_content的东西混来,感觉不是很舒服。
看apache的velocity文档的时候记得有两个参数,文档里面提示了下可以利用来做点东西:
velocimacro.permissions.allow.inline.to.replace.global = true
velocimacro.permissions.allow.inline.local.scope = true
其中第一个是说inline macro是否覆盖预加载的macro也就是global macro,另一个是说inline macro只在模板内有效。在一个模板内把一个global macro覆盖了,是不是可以实现类似回调函数?于是利用这两设置,我们可以实现一些类似layout的东西。
首先还要指定global macro的位置,默认值是从VM_global_library.vm里面加载的
velocimacro.library = WEB-INF/layout/default.vm
然后编辑WEB-INF/layout/default.vm
#macro (default_layout)
<html>
<head><title>#page_title()</title></head>
<body>
#screen_main()
#screen_footer()
</body>
</html>
#end
#macro (page_title) Welcome#end
#macro (screen_main) #end
#macro (screen_footer) #end
然后我们加入一个模板,应用上面的layout:
#default_layout()
#macro (screen_main)
<h1>Here is screen_main</h1>
#end
#macro (screen_footer)
screen_footer here!
#end
这样出来的东西,标题是"Welcome",这个是在layout里面定义的,因为模板里面没有覆盖,所以用layout里面的。screen_main和screen_footer就用模板里定义那个罗,所以最后的结果会大概是:
<html>
<head><title>Welcome</title></head>
<body>
<h1>Here is screen_main</h1>
screen_footer here!
</body>
</html>
看上去还不错,嗯。
这个方法默认情况下,修改global macro要重启serve,想要不重启,把velocimacro.library.autoreload设成true,然后把ResourceLoader的cache关掉,比如file.resource.loader.cache=false。