使用Velocity模板引擎快速生成代码Word文件下载.docx
- 文档编号:16796119
- 上传时间:2022-11-26
- 格式:DOCX
- 页数:12
- 大小:45.94KB
使用Velocity模板引擎快速生成代码Word文件下载.docx
《使用Velocity模板引擎快速生成代码Word文件下载.docx》由会员分享,可在线阅读,更多相关《使用Velocity模板引擎快速生成代码Word文件下载.docx(12页珍藏版)》请在冰豆网上搜索。
引入解压包中的velocity-1.7.jar和lib文件夹下面的jar包。
这样我们就可以在项目中使用Velocity了。
在做完上面的准备工作之后,就可以新建一个叫HelloVelocity的类,代码如下:
清单1.HelloVelocity.java
publicclassHelloVelocity{
publicstaticvoidmain(String[]args){
VelocityEngineve=newVelocityEngine();
ve.setProperty(RuntimeConstants.RESOURCE_LOADER,"
classpath"
);
ve.setProperty("
classpath.resource.loader.class"
ClasspathResourceLoader.class.getName());
ve.init();
Templatet=ve.getTemplate("
hellovelocity.vm"
VelocityContextctx=newVelocityContext();
ctx.put("
name"
"
velocity"
date"
(newDate()).toString());
Listtemp=newArrayList();
temp.add("
1"
2"
list"
temp);
StringWritersw=newStringWriter();
t.merge(ctx,sw);
System.out.println(sw.toString());
}
}
在HelloVelocity的代码中,首先new了一个VelocityEngine类,这个类设置了Velocity使用的一些配置,在初始化引擎之后就可以读取hellovelocity.vm这个模板生成的Template这个类。
之后的VelocityContext类是配置Velocity模板读取的内容。
这个context可以存入任意类型的对象或者变量,让template来读取。
这个操作就像是在使用JSP开发时,往request里面放入key-value,让JSP读取一样。
接下来就是写hellovelocity.vm文件了,这个文件实际定义了Velocity的输出内容和格式。
hellovelocity.vm的内容如下:
清单2.Hellovelocity.vm
#set($iAmVariable="
good!
"
)
Welcome$nameto
todayis$date.
#foreach($iin$list)
$i
#end
$iAmVariable
输出结果如下:
Welcomevelocityto
todayisSunMar2319:
19:
04CST2014.
1
2
在输出结果中我们可以看到,$name、$date都被替换成了在HelloVelocity.java里面定义的变量,在foreach语句里面遍历了list的每一个元素,并打印出来。
而$iAmVariable则是在页面中使用#set定义的变量。
基本模板语言语法使用
在hellovelocity.vm里面可以看到很多以#和$符开头的内容,这些都是Velocity的语法。
在Velocity中所有的关键字都是以#开头的,而所有的变量则是以$开头。
Velocity的语法类似于JSP中的JSTL,甚至可以定义类似于函数的宏,下面来看看具体的语法规则。
一、变量
和我们所熟知的其他编程语言一样,Velocity也可以在模板文件中有变量的概念。
1.变量定义
#set($name=“velocity”)
等号后面的字符串Velocity引擎将重新解析,例如出现以$开始的字符串时,将做变量的替换。
#set($hello=“hello$name”)
上面的这个等式将会给$hello赋值为“hellovelocity”
2.变量的使用
在模板文件中使用$name或者${name}来使用定义的变量。
推荐使用${name}这种格式,因为在模板中同时可能定义了类似$name和$names的两个变量,如果不选用大括号的话,引擎就没有办法正确识别$names这个变量。
对于一个复杂对象类型的变量,例如$person,可以使用${person.name}来访问person的name属性。
值得注意的是,这里的${person.name}并不是直接访问person的name属性,而是访问person的getName()方法,所以${person.name}和${person.getName()}是一样的。
3.变量赋值
在第一小点中,定义了一个变量,同时给这个变量赋了值。
对于Velocity来说,变量是弱数据类型的,可以在赋了一个String给变量之后再赋一个数字或者数组给它。
可以将以下六种数据类型赋给一个Velocity变量:
变量引用,字面字符串,属性引用,方法引用,字面数字,数组列表。
#set($foo=$bar)
#set($foo=“hello”)
#set($foo.name=$bar.name)
#set($foo.name=$bar.getName($arg))
#set($foo=123)
#set($foo=[“foo”,$bar])
二、循环
在Velocity中循环语句的语法结构如下:
#foreach($elementin$list)
Thisis$element
$velocityCount
Velocity引擎会将list中的值循环赋给element变量,同时会创建一个$velocityCount的变量作为计数,从1开始,每次循环都会加1.
三、条件语句
条件语句的语法如下
#if(condition)
...
#elseif(condition)
…
#else
四、关系操作符
Velocity引擎提供了AND、OR和NOT操作符,分别对应&
&
、||和!
例如:
#if($foo&
$bar)
五、宏
Velocity中的宏可以理解为函数定义。
定义的语法如下:
#macro(macroNamearg1arg2…)
调用这个宏的语法是:
#macroName(arg1arg2…)
这里的参数之间使用空格隔开,下面是定义和使用Velocity宏的例子:
#macro(sayHello$name)
hello$name
#sayHello(“velocity”)
输出的结果为hellovelocity
六、#parse和#include
#parse和#include指令的功能都是在外部引用文件,而两者的区别是,#parse会将引用的内容当成类似于源码文件,会将内容在引入的地方进行解析,#include是将引入文件当成资源文件,会将引入内容原封不动地以文本输出。
分别看以下例子:
foo.vm文件:
parse.vm:
#parse(“foo.vm”)
输出结果为:
velocity
include.vm:
#include(“foo.vm”)
以上内容包含了部分Velocity的语法,详细的语法内容可以参考Velocity的官方文档。
自动生成代码的例子
在上个例子中我们可以生成任意的字符串并且打印出来,那为什么我们不能生成一些按照既定格式定义的代码并且写入文件呢。
在这里我们以一个实际的demo来完成这部分内容。
相关内容的源码可以参照附件。
这个demo的功能是要实现一个学生和老师的管理,实际上都是单张表的维护。
我们希望能够只定义model层,来生成MVC的所有代码。
在这个demo中,只自动生成action和JSP的内容,因为现在有很多工具都可以帮助我们自动生成这两个包的代码。
首先在eclipse中建立一个Javaweb工程,在例子中为了方便管理jar包,使用的是maven来建立和管理工程。
建立好的工程目录结构如下图所示:
图1.项目目录结构
JavaResource中放的是Java源码以及资源文件,DeployedResources中放的是web相关的文件。
在Java文件中使用了类似Spring的@Component和@Autowired的注解来实现IoC,使用@Action这样的注解实现MVC,而在JSP中则使用了JSTL来输出页面。
在上图所示的目录中,annotation、filter、framework和util这四个package是作为这个项目框架的,跟业务没有关系,类似于spring和struts的功能。
在实际的项目中我们当然希望能够一开始就编写一个通用的模板文件,然后一下子生成所有的代码,但是很多时候这样做是不可能的,或者说比较困难。
为了解决这个问题,我们可以在编写Velocity模板文件之前先按照原本的流程编写代码,暂时先忘掉Velocity。
编写的代码应该能够在一个功能上完整的调通涉及MVC中所有层次的内容。
在这个例子中,先编写好StudentAction.java文件,以及上图中webapp目录中所示的文件。
在写好以上代码,同时也能顺利运行之后,我们可以参照之前编写的代码来写模板文件。
这里我们来分别看一个Java文件和JSP的例子。
清单3.ActionTemplate.vm
#parse("
macro.vm"
)
@Action("
${classNameLowCase}Action"
publicclass${classNameUpCase}ActionextendsBaseAction{
@Autowired
public${classNameUpCase}Dao${classNameLowCase}Dao;
privateList<
${classNameUpCase}>
${classNameLowCase}s;
private${classNameUpCase}${classNameLowCase};
#foreach($attrin${attrs})
private${attr[0]}${attr[1]};
publicString${classNameLowCase}List(){
${classNameLowCase}s=${classNameLowCase}Dao.retrieveAll${classNameUpCase}s();
return"
${classNameLowCase}List.jsp"
;
...
上面的代码展示了一个Java类转换成vm模板之后的部分内容,完整内容请参考附件。
macro.vm文件中定义了一些使用的宏。
JSP的改造相对于Java文件来说稍微有点复杂,因为JSP中使用JSTL取request中的值也是使用${name}这样的语法,所以想要输出${name}这样的字符串而不是被模板引擎所替换,则需要使用转义字符,就像这样:
\${name}。
为了能够让这个文件中的table得到复用,我们将这个文件中的表格单独拿出来,使用#parse命令来包含。
下面是ListJspTemplate.vm和ListTableTemplate.vm的内容:
清单4.ListJspTemplate.vm
<
%@pagelanguage="
java"
contentType="
text/html;
charset=UTF-8"
pageEncoding="
UTF-8"
%>
%@taglibprefix="
c"
uri="
%>
!
DOCTYPEhtmlPUBLIC"
-//W3C//DTDHTML4.01Transitional//EN"
"
>
html>
head>
<
%@includefile="
includeJS.jsp"
scripttype="
text/javascript"
varpageConfig={
:
{
action"
${classNameLowCase}Action!
${classNameLowCase}List.action"
idName"
${classNameLowCase}Id"
};
/script>
src="
common.js"
metahttp-equiv="
Content-Type"
content="
title>
${classNameUpCase}List<
/title>
/head>
body>
h1>
/h1>
div>
buttonid="
addButton"
Add<
/button>
/div>
ListTableTemplate.vm"
divid="
modifyDiv"
addDiv"
/body>
/html>
清单5.ListTableTemplate.vm
#set($plus="
status.index+1"
tableborder="
style="
width:
100%"
thead>
tr>
th>
No.<
/th>
#generateTH($attrs)<
/tr>
/thead>
tbody>
c:
forEachvar="
${classNameLowCase}"
items="
${${classNameLowCase}s}"
varStatus="
status"
>
tr${classNameLowCase}Id="
${${classNameLowCase}.id}"
td>
${${plus}}<
/td>
#generateTD($classNameLowCase$attrs)<
buttonclass="
modifyButton"
Modify<
deleteButton"
Delete<
/c:
forEach>
/tbody>
/table>
在定义好所有的模板文件之后,需要做的是读取这些文件,然后根据这些文件将model的数据类型以及名称设置到context中,最后将解析出来的内容写到相应的目录中去。
这些工作我们放在了一个叫做VelocityGenerator的类中来做,它的源码如下:
清单6.TemplateGenerator.java
publicclassVelocityGenerator{
TemplateactionTpt=ve.getTemplate("
ActionTemplate.vm"
TemplatelistJspTpt=ve.getTemplate("
ListJspTemplate.vm"
TemplateaddTpt=ve.getTemplate("
AddTemplate.vm"
TemplatemodifyTpt=ve.getTemplate("
ModifyTemplate.vm"
classNameLowCase"
teacher"
classNameUpCase"
Teacher"
String[][]attrs={
{"
Integer"
"
id"
},
String"
serializeNo"
titile"
subject"
attrs"
attrs);
StringrootPath=VelocityGenerator.class.getClassLoader().getResource("
).getFile()+"
../../src/main"
merge(actionTpt,ctx,rootPath+"
/java/com/liuxiang/velocity/action/TeacherAction.java"
merge(listJspTpt,ctx,rootPath+"
/webapp/teacherList.jsp"
merge(addTpt,ctx,rootPath+"
/webapp/teacherAdd.jsp"
merge(modifyTpt,ctx,rootPath+"
/webapp/teacherModify.jsp"
System.out.println("
success..."
privatestaticvoidmerge(Templatetemplate,VelocityContextctx,Stringpath){
PrintWriterwriter=null;
try{
writer=newPrintWriter(path);
template.merge(ctx,writer);
writer.flush();
}catch(e){
e.printStackTrace();
}finally{
writer.close();
在运行以上代码之后,项目文件夹中将会出现与Teacher相关的代码文件。
在实际项目中可能不会出现很多这种单张表维护的情况,而且业务逻辑和系统架构会更加复杂,编写模板文件就更加不容易。
但是无论多复杂的系统,不同的业务逻辑之间一定或多或少会有相似的代码,特别是在JSP和JS显示端文件中,因为我们在一个系统中要求显示风格、操作方式一致的时候就免不了会有相似内容的代码出现。
在总结这些相似性之后我们还是可以使用Velocity来帮助我们生成部分内容的代码,而且即使有一些非共性的内容,我们也可以在生成的代码中继续修改。
使用Velocity的另外一个好处是生成出来的代码更好维护,风格更加统一。
结束语
Velocity可以被应用在各种各样的情景下,本文介绍的只是它的一种用途而已,它还可以被用来做MVC结构中的view层,或者动态内容静态化等。
另外,Velocity并不是唯一的模板框架,同样很优秀的Freemarker也获得了非常广泛的应用,有兴趣的读者可以去深入研究更多的功能和用途。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 使用 Velocity 模板 引擎 快速 生成 代码
![提示](https://static.bdocx.com/images/bang_tan.gif)