背景:后台开发人员和web设计都在HTML5页面撸各自的代码,要区分开来,JSP自己的<c:foreach>等标签,容易看花眼。当然Velocity的强大的其他方面,我就不说的,实现【后台开发人员】和【web设计人员】的工作是我的主要目的。
1、思路:
研究Jfinal自己的VelocityRender,加以改造。写个Veloticity的工具类,替换自带的renderVelocity(String view) 的方法体。
2、具体实现:
(1)、写个类似VelocityRender的实体类VelocityLayoutRender(网友也这么叫,直接复制了)(在官方VelocityRender做修改,把这个当成工具类,不需要继承Render类,没必要);
package com.bluemobi.config;
import java.io.PrintWriter;
import java.util.Enumeration;
import java.util.Properties;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.velocity.Template;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.tools.Scope;
import org.apache.velocity.tools.ToolManager;
import org.apache.velocity.tools.view.ViewToolContext;
import com.jfinal.core.Const;
import com.jfinal.core.JFinal;
import com.jfinal.render.RenderException;
public class VelocityLayoutRender {
private static final String contentType = "text/html; charset=" + Const.DEFAULT_ENCODING;
private static final Properties properties = new Properties();
private static VelocityEngine velocityEngine = new VelocityEngine();
private static ToolManager tm = new ToolManager(true, true);
private static boolean notInit = true;
static {
String webPath = JFinal.me().getServletContext().getRealPath("/");
properties.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, webPath);
properties.setProperty(Velocity.ENCODING_DEFAULT, Const.DEFAULT_ENCODING);
properties.setProperty(Velocity.INPUT_ENCODING, Const.DEFAULT_ENCODING);
properties.setProperty(Velocity.OUTPUT_ENCODING, Const.DEFAULT_ENCODING);
properties.setProperty(Velocity.VM_LIBRARY_AUTORELOAD, "true");
// 切记把tools.xml放到资源文件包下,也就是生成后会在classes文件夹下能看到
ToolManager toolManager = new ToolManager(true, true);// 默认把官方带的所有工具类都加入进入
toolManager.setVelocityEngine(velocityEngine);
// 绑定工具类
tm.setVelocityEngine(velocityEngine);
}
// 使用有工具类视图的上下文 (其实是VelocityContext的子类)
public static ViewToolContext getViewToolContext(HttpServletRequest request, HttpServletResponse response) {
ServletContext servletContext = request.getServletContext();
ViewToolContext ctx = new ViewToolContext(velocityEngine, request, response, servletContext);
if (tm.getToolboxFactory().hasTools(Scope.REQUEST)) {
ctx.addToolbox(tm.getToolboxFactory().createToolbox(Scope.REQUEST));
}
if (tm.getToolboxFactory().hasTools(Scope.APPLICATION)) {
ctx.addToolbox(tm.getToolboxFactory().createToolbox(Scope.APPLICATION));
}
if (tm.getToolboxFactory().hasTools(Scope.SESSION)) {
ctx.addToolbox(tm.getToolboxFactory().createToolbox(Scope.SESSION));
}
return ctx;
}
// 生成模板并打印
public static void render(String view, HttpServletRequest request, HttpServletResponse response) {
if (notInit) {
velocityEngine.init(properties);
notInit = false;
}
PrintWriter writer = null;
try {
ViewToolContext context = getViewToolContext(request, response);
for (Enumeration<String> attrs = request.getAttributeNames(); attrs.hasMoreElements();) {
String attrName = attrs.nextElement();
context.put(attrName, request.getAttribute(attrName));
}
Template template = velocityEngine.getTemplate(view);
response.setContentType(contentType);
writer = response.getWriter();
template.merge(context, writer);
writer.flush(); // flush and cleanup
} catch (ResourceNotFoundException e) {
throw new RenderException("Example : error : cannot find template " + view, e);
} catch (ParseErrorException e) {
throw new RenderException("Example : Syntax error in template " + view + ":" + e, e);
} catch (Exception e) {
throw new RenderException(e);
} finally {
if (writer != null)
writer.close();
}
}
}(2),替换renderVelocity得写个BaseController类(拓展自Controller类),以后所有的类,都集成这个类,一般项目都会自己写个BaseController基类。
切记别忘了写this.renderNull();(不在返回数据),否则会报错,
this.renderNull();
public class BaseController extends Controller {
/**
* Render with velocity view
*/
public void renderVelocity(String view) {
VelocityLayoutRender.render(view,this.getRequest(),this.getResponse());
this.renderNull();
}
}
(3),直接在项目中使用,在WebRoot下的admin文件夹创建个文件,index.vm
public class WxOtherController extends BaseController {
@ActionKey("/wx")
public void toLogin() {
this.renderVelocity("admin/index.vm");
}
}(4),index.vm的内容
<html>
<body>
#set( $foo = "Velocity" )
Hello $foo World!
$myTool.out()
</body>
</html>
(5),打印结果;在浏览器输入地址就可以看到结果
Hello Velocity World!
加入toolx.xml,请把这个文件,放到,资源文件夹,也就是到时会生成到classess下,
demo工具类如下:
@DefaultKey("myTool")
public class MyTool {
public String out() {
return "velocityTool";
}
public static String XX() {
return "韦甩甩";
}
}
toolx.xml的写法如下,我用的velocity2.0
<?xml version="1.0" encoding="UTF-8"?>
<tools>
<toolbox scope="application">
<tool class="com.bluemobi.utils.MyTool"/>
</toolbox>
</tools>
在index.vm页面,直接使用, $myTool.out()就打印出韦甩甩。
其实,这个后缀,叫不叫vm,都无所谓,哪怕叫index没后缀,或者叫index.html都可以。
ps:编辑velocity模板,可以用一个eclipse插件,veloeclipse,前提是得升级一个功能
不然装不上,时间会比较慢,要等好久。
Help -> Install New Software... -> Work with
-> 选择“The Eclipse Project Updates - http://download.eclipse.org/eclipse/updates/4.4”
-> 勾选"Eclipse Tests, Examples, and Extras" 下的 "Eclipse 2.0 Style Plugin Support"
安装完成后,
在输入
http://veloeclipse.googlecode.com/svn/trunk/update/
即可成功运行veloeclipse。