在用JSP的时候会把Java和HTML混在一起,这样会逻辑混乱、可维护性差等。Velocity解决了这个问题,在HTML页面和Java之间通过Context传递数据进行动态渲染,Velocity也支持简单的语法,比如循环。需要注意的是我们应该尽量保证View层的简洁。
原理
通过下面代码就能大致明白Velocity是如何工作的:
// 初始化Velocity引擎
VelocityEngine ve = new VelocityEngine();
ve.init();
// 获取模板
Template t = ve.getTemplate( "hello.vm" );
VelocityContext context = new VelocityContext();
context.put("content", "Hello World.");
// 根据上下文渲染模板
StringWriter writer = new StringWriter();
t.merge(context, writer);
System.out.println(writer.toString());
渲染的结果是页面输出,也就是String,只不过Servlet不会向标准输出流写。
配置
这里看springMVC中的Velocity配置方法,实际上是通过Resolver来实现的:
<!-- 配置信息 -->
<bean id="velocityConfig" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
<property name="resourceLoaderPath">
<value>/velocity</value>
</property>
<property name="velocityProperties">
<props>
<prop key="input.encoding">GBK</prop>
</props>
</property>
</bean>
<!-- Resolver -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.velocity.VelocityView" />
<property name="order" value="0" />
<property name="suffix" value=".vm" />
<property name="contentType" value="text/html;charset=UTF-8" />
<property name="exposeSpringMacroHelpers" value="true" />
<property name="exposeRequestAttributes" value="false" />
<property name="exposeSessionAttributes" value="false" />
<property name="redirectHttp10Compatible" value="false" />
<property name="redirectContextRelative" value="false" />
</bean>
用Resolver的原因在DispatcherServlet中看到。在上面的配置中有模板路径、编码、后缀名、contentType等。
在最近的一个项目中计划用Velocity来渲染数据,也就是说vm模板的来源不是文件了,这时候可以通过自己实现一个ResourceLoader来完成:
public class VelocityShellLoader extends ResourceLoader {
@Override
public void init(ExtendedProperties configuration) {
}
@Override
public InputStream getResourceStream(String source) throws ResourceNotFoundException {
return new ByteArrayInputStream(source.getBytes());
}
@Override
public boolean isSourceModified(Resource resource) {
return false;
}
@Override
public long getLastModified(Resource resource) {
return 0;
}
}
在使用引擎渲染的时候指定它就可以了:
public class Test {
public static void main(String[] args) throws Exception {
VelocityEngine velocityEngine = new VelocityEngine();
Properties properties = new Properties();
properties.put("resource.loader", "srl");
properties.put("srl.resource.loader.class", "com.wszt.VelocityShellLoader");
velocityEngine.init(properties);
Template template = velocityEngine.getTemplate("你好 $name !\r\n$project project.", "gbk");
VelocityContext context = new VelocityContext();
context.put("name", "张三");
context.put("project", "Jakarta");
StringWriter writer = new StringWriter();
template.merge(context, writer);
System.out.println(writer.toString());
}
}
--------- END ----------