Velocity编码式渲染模板

本文介绍了如何在Spring中配置并使用Velocity作为前端模板渲染引擎,特别是在编码式调用场景下的实践。通过调整toolbox配置解决了遇到的问题,并分享了在解决过程中的一些经验和教训。涉及到的关键点包括自定义工具类的使用、VelocityConfigurer与VelocityLayoutViewResolver的区别,以及针对Spring对最新toolbox支持不足的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


Velocity通常作为页面前端的模板渲染引擎,在spring中配置好就OK了。在某些特殊情况下也会需要使用编码式方式调用它,小试了一把。

过于简单,就直接贴代码了。

import java.io.StringWriter;
import java.util.Date;

import junit.framework.TestCase;

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;

import com.xxx.common.lang.util.DateUtil;

/**
 * 
 * 
 * @author Lucas
 * 
 */
public class VelocityProgramaticCallTest extends TestCase {
	public void testVelocity() {
		Velocity.init();
		Template template = Velocity.getTemplate("src/test/resources/vm/helloworld.vm");
		VelocityContext context = new VelocityContext();
		StringWriter writer = new StringWriter();
		context.put("username", "麦子");
		context.put("companyName", "Easylife ltd.");
		context.put("now", DateUtil.simpleDate(new Date()));
		template.merge(context, writer);
		System.out.println(writer.toString());
	}
}

helloworld.vm


<html>
<head>
	<meta charset="UTF-8" />
	<title>Document</title>
</head>
<body>
hello,dear $username
<br />
Welcome to our website.Hope you have a great time.
<br />
$companyName
$now
</body>
</html>


通常,我们会在应用中使用自定义的一些工具类来完成特殊的展示需求,比如,用DateUtil来格式化日期,用StringUtil来处理字符串等等。以下代码加入了此类功能
注意前提是系统中加载了spring并且是文本环境,并在文件中配置了velocityConfig.当然其实其他系统方式也是一致的。


import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.tools.ToolContext;
import org.apache.velocity.tools.ToolManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.view.velocity.VelocityConfig;
import org.springframework.web.servlet.view.velocity.VelocityViewResolver;

import com.xxx.common.lang.util.StringUtil;
import com.xxx.common.enums.EasylifeExceptionEnum;
import com.xxx.common.exception.BusinessException;

/**
 * 
 * 
 * @author lvchen@yiji.com
 * 
 */
@Component
public class VelocityParser {
	
	@Autowired
	private VelocityConfig velocityConfig;
	
	
	/**
	 * 使用velocity引擎解析指定路径下的文件模板
	 * @param templateFilePath 模板文件路径
	 * @param params 参数
	 * @return 解析后的结果
	 */
	public String parse(String templateFilePath, Map<String, Object> params, HttpServletRequest req) {
		
		String parsed = null;
		
		if (StringUtil.isEmpty(templateFilePath)) {
			throw new BusinessException(EasylifeExceptionEnum.INVALID_ARGUMENT_EXCEPTION, "模板路径为空");
		}
		
		try {
			
			VelocityEngine velocityEngine = velocityConfig.getVelocityEngine();
			
			ToolManager toolManager = new ToolManager();
			String realPath = req.getServletContext().getRealPath("/");
			toolManager.configure(realPath + "WEB-INF\\config\\velocity-toolbox.xml");
			ToolContext toolContext = toolManager.createContext();
			StringWriter sw = new StringWriter();
			
			VelocityContext velocityContext = new VelocityContext(params, toolContext);
			velocityEngine.mergeTemplate(templateFilePath, "UTF-8", velocityContext, sw);
			parsed = sw.toString();
			
		} catch (Exception e) {
			throw new BusinessException(e, EasylifeExceptionEnum.EXECUTE_FAIL);
		}
		
		return parsed;
	}
}

顺便说说解决这个问题中遇到的坑和感悟吧。

1.最为光火的问题是,我按照官方的方式编写了上面的代码,但是无论如何不生效。看了半天spring配置文件中配置的org.springframework.web.servlet.view.velocity.VelocityLayoutViewResolver和org.springframework.web.servlet.view.velocity.VelocityConfigurer源码都得不到任何有用信息。之后我联想到系统启动时报的warning,toolbox的配置格式已经是deprecated的了,于是就把toolbox的格式配置改了,就成功了。汗啊~

2.关于上面提到的两个组件VelocityLayoutViewResolver和VelocityConfigurer。VelocityConfigurer是一个用来配置velocity的配置器,启动时会被调用,而VelocityLayoutViewResolver推测是在resolve模板的时候才会使用到,而toolbox这个玩意儿不是在系统启动的时候初始化velocityEngine时加载的而是在resolve的时候再添加进去的。

后续:

修改了toolbox.xml之后编码式调用可以使用自定义的工具类了,但是页面渲染又不行了。google一番,发现spring竟然不支持最新的toolbox,需要自定义一个velocityview来覆盖才可以...我这里继承了VelocityLayoutView,是为了实现layout。

贴出代码:

import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.context.Context;
import org.apache.velocity.tools.config.ConfigurationUtils;
import org.apache.velocity.tools.config.FactoryConfiguration;
import org.apache.velocity.tools.view.ViewToolContext;
import org.apache.velocity.tools.view.ViewToolManager;
import org.springframework.web.servlet.view.velocity.VelocityLayoutView;

/**
 * 
 * 
 * @author lvchen@yiji.com
 * 
 */
public class VelocityUpgradedToolBoxView extends VelocityLayoutView {
	
	private static final String TOOL_MANAGER_KEY = ViewToolManager.class.getName();
	
	/**
	 * @param model
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 * @see org.springframework.web.servlet.view.velocity.VelocityToolboxView#createVelocityContext(java.util.Map,
	 * javax.servlet.http.HttpServletRequest,
	 * javax.servlet.http.HttpServletResponse)
	 */
	@Override
	protected Context createVelocityContext(Map<String, Object> model, HttpServletRequest request,
											HttpServletResponse response) throws Exception {
		ServletContext application = getServletContext();
		
		ViewToolManager toolManager = (ViewToolManager) application.getAttribute(TOOL_MANAGER_KEY);
		if (toolManager == null) {
			toolManager = createToolManager(getVelocityEngine(), getToolboxConfigLocation(),
				application);
			application.setAttribute(TOOL_MANAGER_KEY, toolManager);
		}
		
		ViewToolContext toolContext = toolManager.createContext(request, response);
		if (model != null) {
			toolContext.putAll(model);
		}
		
		return toolContext;
	}
	
	private ViewToolManager createToolManager(VelocityEngine velocity, String toolFile,
												ServletContext application) {
		ViewToolManager toolManager = new ViewToolManager(application, false, false);
		toolManager.setVelocityEngine(velocity);
		
		// generic & view tools config
		FactoryConfiguration config = ConfigurationUtils.getVelocityView();
		// user defined tools config
		if (toolFile != null) {
			FactoryConfiguration userConfig = ConfigurationUtils.load(application
				.getRealPath(toolFile));
			config.addConfiguration(userConfig);
		}
		toolManager.configure(config);
		
		return toolManager;
	}
	



网上找了一圈参考资料:

1.关于velocity代码概念,介绍的稍微详细点的:velocity官方开发者介绍(英文)

2.spring中使用获取velocityEngine

3.velocity toolbox配置

4.stackoverflow上关于调用新的velocityView的讨论



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值