Velocity模版与Ajax灵活应用
一:先简单介绍一下velocity的模版页面
velocity是apache开源组织旗下的一个开源项目,可以到apache的官方网去下载并了解它的语法和用法,非常简单,既方便又易用,主要包括两个jar包,velocity-1.5.jar,velocity-dep-1.5.jar。
velocity的模版是以vm为后缀的,例如我的web应用下有一个模版:/myweb/template/test.vm,它是以$符号来引用 对象,例如我在request中设置了一个名称叫做mydata的attribute,类型为List,list的保存的对象类型为Data.java
public class Data {
private String name = "";
private String sex = "";
private String address = "";
public String getAddress() {
?? return address;
}
public void setAddress(String address) {
?? this.address = address;
}
public String getName() {
?? return name;
}
public void setName(String name) {
?? this.name = name;
}
public String getSex() {
?? return sex;
}
public void setSex(String sex) {
?? this.sex = sex;
}
}
在页面显示时的迭代用法是:
<table>
<tr>
#foreach($data in $!mydata)
<td>$!data.getName()</td>
<td>$!data.getSex()</td>
<td>$!data.getAddress()</td>
#end
</tr>
</table>
用模版犹如建一栋房子,把钢架结构搭好了,就往里边堆东西就可以了。
二:解析velocity模版的实现说明
Velocity引擎对vm模版解释是根据引擎的上下文和模版的路径来进行解析的,从以下的代码可以一览其然,非常简单明了:
首先要初始化一个vm引擎:
?? VelocityEngine engine = new VelocityEngine();
再次要初始化vm模版资源的绝对路径,以方便引擎进行解析(黑体部分的属性是必须得有的,vm模版的路径例如第一点中的:/myweb/template/test.vm:):
Properties p = new Properties();
??? final String str = vmpath.substring(0, vmpath.lastIndexOf("/"));
??? p.setProperty("file.resource.path", request.getSession()
????? .getServletContext().getRealPath("")
????? + str);
??? engine.init(p);
然后就是把request属性等设置在引擎的上下文中,当然也可以把session中的属性也设置进去。
VelocityContext context = new VelocityContext();
?? Enumeration enu = request.getAttributeNames();
?? while (enu.hasMoreElements()) {
??? final String paramName = enu.nextElement().toString();
??? context.put(paramName, request.getAttribute(paramName));
?? }
最后就是解析模版了:
??? template = engine.getTemplate(vmpath.substring(vmpath
????? .lastIndexOf("/") + 1));
??? template.merge(context, sw);
以下是解析vm模版的全部代码:
import java.io.StringWriter;
import java.util.Enumeration;
import java.util.Properties;
import javax.servlet.http.HttpServletRequest;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
public class VmUtil {
public static String getVmString(HttpServletRequest request, String vmpath) {
?? if (null == vmpath || "".equals(vmpath))
??? return "";
?? // velocity模版的解析引擎
?? VelocityEngine engine = new VelocityEngine();
?? try {
??? Properties p = new Properties();
??? final String str = vmpath.substring(0, vmpath.lastIndexOf("/"));
??? p.setProperty("file.resource.path", request.getSession()
????? .getServletContext().getRealPath("")
????? + str);
??? engine.init(p);
?? } catch (Exception e) {
??? // TODO Auto-generated catch block
??? e.printStackTrace();
?? }
?? // velocity的上下文环境变量的设置
?? VelocityContext context = new VelocityContext();
?? Enumeration enu = request.getAttributeNames();
?? while (enu.hasMoreElements()) {
??? final String paramName = enu.nextElement().toString();
??? context.put(paramName, request.getAttribute(paramName));
?? }
?? // velocity模版
?? Template template = null;
?? StringWriter sw = new StringWriter();
?? try {
??? template = engine.getTemplate(vmpath.substring(vmpath
????? .lastIndexOf("/") + 1));
??? template.merge(context, sw);
?? } catch (ResourceNotFoundException e) {
??? // TODO Auto-generated catch block
??? e.printStackTrace();
?? } catch (ParseErrorException e) {
??? // TODO Auto-generated catch block
??? e.printStackTrace();
?? } catch (Exception e) {
??? // TODO Auto-generated catch block
??? e.printStackTrace();
?? }
?? return sw.toString();
}
}
三:jsp页面可以用自定义标签的形式来引入vm模版,此做法的目的是利用ajax局部刷新时可以只刷新模版的那部分。
jsp页面中的引入自定义标签时可以将模版的路径作为一个属性进行设置,例如/test.jsp页面中引入:
<showpage:vmpage vmurl="/myweb/template/test.vm"/>
jsp自定义标签的doStateTag或者doEngTag方法都可以调用VmUtil .getVmString(request,vmurl) 来获取解析后的html字符串,然后用out将其输出到页面中去,在此就不再详细介绍jsp自定义标签的用法了。
四:prototype.js框架的应用,主要利用其的ajax框架
prototype.js是一个开源的比较流行的js框架工具包,包括ajax等应用,在此只介绍它部分的ajax用法:
页面局部刷新时用到的function, 传入的参数就是ajax请求局部刷新的url,divName就是要局部刷新的div或者td等,在页面调用时要记得到如prototype.js的脚本集:
function showPage(url,divName)
{
this.g_div_name = divName;
this.success = function (xmlRequest)
{
?? var str = xmlRequest.responseText;
?? document.getElementById(this.g_div_name).innerHTML = str;
}
this.fail = function (xmlRequest)
{
?? alert("paging error!");
}
var xmlRequest = new Ajax.Request(url,{method:"post",parameters:"×tamp="
????? + new Date.getTime(),onSuccess:this.success,onFailure:this.fail});
?????
??? if (!xmlRequest)
??? {
??? alert("paging error!");
??? }
}
五:页面功能实现的一些简单介绍
本文只是介绍模版和ajax的结合运用,故不提供具体的例子,以下简要说一下servlet。假如有个/test.jsp和一个 /myservlet路径的servlet,为了配合ajax实现局部的刷新,增加一个ajax请求的标志位ajaxFlag 参数,该servlet的servie方法中局部说明如下:
.......
request.setAttribute("mydata",mydata);
.......
String ajaxFlag = request.getParameter("ajaxFlag");
if(null != ajaxFlag &&! "true".equals(ajaxFlag ))
{
??????? response.setContentType("text/html;charset=UTF-8");
????? reponse.getWriter().println(VmUtil .getVmString(request,"/myweb/template/test.vm") );
???????? return ;//如果是ajax请求,输出后直接返回
}
reponse.sendRedirect("/test.jsp");//非ajax请求,重定向到指定的jsp页面中去。
.......
六:总结
不断追求、勇于进取是我从事该行业的方向标。
http://dev2dev.bea.com.cn/blog/neso/200711/velocity_ajax_06_624.html?