Jfinal整合Velocity模板(加入工具类tools.xml,可以加入自定义)

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



评论区

JFinal

2016-09-30 19:44

这个有很多 jfinal 用户都找我要过,现在终于有了,超赞的分享

多喝水

2017-08-30 15:03

不好意思,代码根本无法运行

热门分享

扫码入社