背景:后台开发人员和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。