谈到velocity 不得不谈freemarker,freemarker的宏是一个好东东,JSP中很多类似的代码(参数不同而已,有可能只是遍历List的数据不同,href或者onclick事件不同),那么freemarker很拿手。velocity相对freemarker的宏就显得很逊色。
喜欢上velocity 是因为他的简洁,方便。语法与freemarker及其相像。拿工作中的分页查询来说。velocity好像也有宏,没用过velocity的宏。但是可以实现宏一样的效果,放在Map里也是可以动态实现的参数的。
首先我的jsp放一个div专业存储数据和分页信息。
<div id="content"></div>
页面就写一个这样的div即可。
刚进页面应该是默认显示第一页,so onload的时候就应该加载第一页数据。
function page(clickpage, g) { var pageNo = (g == 'forward') ? clickpage- 1 : (g == "next") ? clickpage+ 1 : clickpage; // 请求后台 传递pageNo参数,传递htmlData document.getElementById("content").innerHTML = htmlDate; window.location.href = url; }
注意onload = "page(1,null)"
Action的方法处理大致如下:
String out = ""; // 要输出的HTML String pageNo = HttpUtil.getAsString(request, "pageNo"); int pagesize = 16; // 每页显示16条数据 Matcher isNum = Pattern.compile("[0-9]*").matcher(pageNo);//整数正则 int currentpage = !isNum.matches()?1:pageNo.length()>9?1:Integer.parseInt(pageNo); int allcount = sv.getXXCount();数据库中查询的所有行数; if(currentpage<1){currentpage = 1;} int allpage = allcount/pagesize==0?allcount/pagesize:allcount/pagesize+1; if(currentpage*pagesize>allcount){ currentpage = allpage;// 最后一页 } int start = (currentpage-1)*16+1;// 起始值为前几页+1 int currentpagesize = 0; if(allcount<=pagesize){ currentpagesize = allcount; }else{ currentpagesize = start+pagesize<allcount?pagesize:allcount%pagesize; } IXXXValue[] values = sv.getXXXValues(start,pagesize,currentpage,currentpagesize); Map retMap = getCacheData(values); List countList = new ArrayList(); int startpage = currentpage<10?1:currentpage-5; int end = startpage + 10; if(end>allpage)end = allpage; for (int i = startpage; i <= end; i++) { countList.add(i); } retMap.put("allcount", allcount); retMap.put("currentpage", currentpage); retMap.put("allpage", allpage); retMap.put("countList", countList); retMap.put("currentpagesize", currentpagesize); out = VelocityHelper.evaluateTemplate(retMap, "vm/XXXPage.vm");
out就是我们要得到的HTML数据,看getCacheData(ivalues) 方法主要是把查询的数据对象放入Map中,然后把所有的Map存储到ArrayList中:
public static Map getCacheData(IXXXValues[] values) throws Exception { List dataList = new ArrayList(); if(values != null){ for(int i=0; i<values.length; i++){ Map tmpMap = new HashMap(); tmpMap.put("col1", values[i].getXXX()); tmpMap.put("col2", values[i].getYYY()); dataList.add(tmpMap); } } Map retMap = new HashMap(); retMap.put("dataList", dataList); return retMap ; }
然后我们看evaluateTemplate方法:
public static String evaluateTemplate(Map context, String filepath) throws Exception { try{ Template template = Velocity.getTemplate(filepath, "GBK"); Writer writer = new StringWriter(); VelocityContext vContext = new VelocityContext(context); template.merge(vContext, writer); return writer.toString(); }catch (Exception ex) { ex.printStackTrace(); throw new Exception(ex); } }
XXX.vm是我们的模板内容,主要的有:
#if ($dataList.size()>0) <table> #foreach($datalistOne in $dataList) <tr class=""> <td> #if($datalistOne.notes.length()>=3) #if($!$datalistOne.notes) $datalistOne.notes.substring(0,3) #else #end #else $datalistOne.notes #end </td> </tr> #end </table> <div> #if ($currentpage==1) <span class="front" style = "background-color:yellow;">上一页</span> #else <a href = "#" onclick = "page($currentpage,'forward')">上一页</a> #end #foreach( $something in $countList) #if ($something== $currentpage) <span class="current" style = "background-color:red;">$something</span> #else <a href = "#" onclick = "page($something,'144');">$something</a> #end #end #if ($currentpage==$allpage) <span class="front" style = "background-color:yellow;">下一页</span> #else <a href = "#" onclick = "page($currentpage,'next')">下一页</a> #end 当前页$currentpage 总页数 $allpage 当前页条数 $currentpagesize </div> #else 没有查询到相关数据 #end
主要是功能,界面比较难看,分页模仿百度的分页效果,可以对页码进行分页,自动前进后退。
因为每次请求都替换了content ,所以不需要跳转页面。
在vm中开始用了javascript:void(0); 最开始时用页面跳转做的,分页的时候window.location.href无效了。
遇到一个非常奇怪的问题,在三元表达式中web app和直接main()入口写执行结果不一样,看来() 非常重要,更加有可读性,在稍微复杂一点的三元运算中不管是为了可读性,还是为了少出现bug,最好在计算中都加上()。