package com.blinkcoder.render; import com.jfinal.core.JFinal; import com.jfinal.render.Render; import org.apache.velocity.Template; import org.apache.velocity.app.Velocity; import org.apache.velocity.app.VelocityEngine; import org.apache.velocity.context.Context; import org.apache.velocity.io.VelocityWriter; import org.apache.velocity.runtime.RuntimeConstants; import org.apache.velocity.tools.view.ToolboxManager; import org.apache.velocity.tools.view.context.ChainedContext; import org.apache.velocity.tools.view.servlet.ServletToolboxManager; import org.apache.velocity.tools.view.servlet.VelocityLayoutServlet; import org.apache.velocity.util.SimplePool; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.StringWriter; import java.io.Writer; import java.util.Properties; /** * User: Michael Chen * Email: yidongnan@gmail.com * Date: 13-10-15 * Time: 上午8:18 */ public class VelocityToolboxRender extends Render { private static final String TOOL_BOX_CONF_FILE = "/WEB-INF/classes/velocity-toolbox.xml"; private transient static final String encoding = getEncoding(); private transient static final String contentType = "text/html;charset=" + encoding; private transient static final Properties properties = new Properties(); protected ToolboxManager toolboxManager = null; private static SimplePool writerPool = new SimplePool(40); private transient static boolean notInit = true; public static final String KEY_LAYOUT = "layout"; public static final String KEY_SCREEN_CONTENT = "screen_content"; private static final String layoutDir = "/WEB-INF/layout/"; private static final String defaultLayout = "default.vm"; @Override public void render() { Context context = createContext(request, response); fillContext(context, request); VelocityWriter vw = null; Template template = Velocity.getTemplate(view); response.setContentType(contentType); StringWriter sw = new StringWriter(); template.merge(context, sw); context.put(KEY_SCREEN_CONTENT, sw.toString()); Object obj = context.get(KEY_LAYOUT); String layout = (obj == null) ? null : obj.toString(); if (layout == null) { layout = layoutDir + defaultLayout; } else { layout = layoutDir + layout; } try { template = Velocity.getTemplate(layout); } catch (Exception e) { if (!layout.equals(layoutDir + defaultLayout)) { template = Velocity.getTemplate(layoutDir + defaultLayout); } } try { Writer writer = response.getWriter(); vw = (VelocityWriter) writerPool.get(); if (vw == null) { vw = new VelocityWriter(writer, 4 * 1024, true); } else { vw.recycle(writer); } template.merge(context, vw); } catch (IOException e) { } finally { if (vw != null) { try { vw.flush(); vw.recycle(null); writerPool.put(vw); } catch (Exception e) { // Velocity.debug("VelocityViewServlet: " + "Trouble releasing VelocityWriter: // " + e.getMessage()); } } } } ; static { String webPath = JFinal.me().getServletContext().getRealPath("/"); Properties properties = new Properties(); properties.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, webPath); properties.setProperty(RuntimeConstants.ENCODING_DEFAULT, encoding); properties.setProperty(RuntimeConstants.INPUT_ENCODING, encoding); properties.setProperty(RuntimeConstants.OUTPUT_ENCODING, encoding); properties.setProperty(RuntimeConstants.VM_LIBRARY, "/WEB-INF/macro/common.vm"); properties.setProperty(VelocityLayoutServlet.PROPERTY_LAYOUT_DIR, layoutDir); properties.setProperty(VelocityLayoutServlet.PROPERTY_DEFAULT_LAYOUT, defaultLayout); Velocity.init(properties); } public VelocityToolboxRender(String url) { this.url = url; int index = url.indexOf("?"); if (index != -1) this.view = url.substring(0, index); else this.view = url; initToolbox(JFinal.me().getServletContext()); } @SuppressWarnings("unchecked") protected Context createContext(HttpServletRequest req, HttpServletResponse resp) { ChainedContext ctx = new ChainedContext(new VelocityEngine(), req, resp, JFinal.me().getServletContext()); if (toolboxManager != null) { ctx.setToolbox(toolboxManager.getToolbox(ctx)); } return ctx; } protected void fillContext(Context ctx, HttpServletRequest request) { String layout = request.getParameter(KEY_LAYOUT); // also look in the request attributes if (layout == null) { layout = (String) request.getAttribute(KEY_LAYOUT); } if (layout != null) { // let the template know what its new layout is ctx.put(KEY_LAYOUT, layout); } } protected void initToolbox(ServletContext servletContext) { toolboxManager = ServletToolboxManager.getInstance(servletContext, TOOL_BOX_CONF_FILE); } }