原文名称《Web Application Guide》,副标题为基于Web的应用技术和VelocityViewServlet入门,地址为此处连接。文章分为四部分,第一部分,通览使用Velocity建立Web应用的好处,第二部分,讲述须要使用的具体框架,第三部分,主要探讨使用Velocity时的问题,第四部分,讲解一个入门实例。 html
使用Velocity建立Web应用
Velocity一般被用来生成web页面,能够直接替代JSP,如下是使用Velocity的好处: java
配合使用的具体框架 程序员
Velocity引擎的主要目的仅仅是为了生成文本,并且在模板基础上生成。所以,Velocity本身不包含任何web相关的功能,因此,咱们仍是须要一个框架来响应HTTP请求、来处理用户认证、来造成业务逻辑调用、以致造成响应,如下列出几个好的选择: web
1. Velocity工具之一:VelocityViewServlet(Velocity视图服务器小程序) - 最简单的开始使用 Velocity的方法是下载 Velocity Tools 并使用 VelocityViewServlet。这个服务器端小程序很是容易配置和安装。方法以下:服务器目录下建立模板文件夹-->编辑XML文件列上各类“工具”(放在页面中的)-->完工。 正则表达式
2. Velocity 工具之二:VelocityStruts (Velocity支撑程序)-- 咱们可能比较熟悉流行的 Struts 框架,它原来是设计为JSP提供丰富功能的。而使用 VelocityStruts,你就可让 Velocity 彻底替代 JSP啦,VelocityStruts可让你充分利用 Struts框架的优点。 数据库
3. 第三方框架 -- 在Wiki页面还列出了不少第三方框架,查看 PoweredByVelocity 页面。其中,Spring 多是最知名的一个。Apache Turbine 也有不少特点且用处不小,Turbine 将 Velocity 做为主要的页面语言,Turbine 自己就是那些开发 Velocity 的程序员建立的。更为简单的框架还包括 Click 或者 Maverick ,他们提供了简单的控制器框架,能与Velocity完美整合。 apache
4. 本身动手 -- 咱们还能够本身建立框架。咱们能够建立小程序来调度、从文件或数据库获取模板、整合业务逻辑并发送结果给用户。一般,从现有的框架开始进一步修改它是个不错的选择。特别的,你能够经过建立子类的方式向 VelocityViewServlet 添加新的功能。 小程序
最后声明,VelocityServlet 不再会被维护,而被 VelocityViewServlet 替代。
Web相关棘手问题
Web应用开发涉及到不少问题,如下列出一些最常遇到的:
使人头疼的资源载入问题
默认的 Velocity 引擎设置中使用 FileResourceLoader,这个配置对于那些不使用 servlet 引擎的应用来是很棒的。但一旦你决定使用 war 文件部署web应用,那么 FileResourceLoader 可能成为你的敌人。因此,咱们明确建议你不要使用 FileResourceLoader。
事实上,还有不少 ResourceLoader 实现,但这些 ResourceLoader 在和 Velocity引擎配合使用时将要求咱们将模板存放在标准文件系统以外(如classpath、数据库、远程服务器等)。咱们说,若是运行起来,那很好。但咱们认可对大多数来讲,这个部署方式很不方便。
最简单的替代方案实际已经存在于 VelocityTools 中,即 WebappResourceLoader,这个 ResourceLoader 是特别设计来像FileResourceLoader同样工做的,但 WebappResourceLoader 知道 servlet 上下文,容许咱们配置servlet root 相关的资源路径,而不是本地文件系统。
若是你正使用 VelocityViewServlet,那么 VelocityViewServlet 会自动被配置去使用 WebappResourceLoader。因此,若是你想改变配置路径,你须要添加一行到 velocity.properties 中。 安全
webapp.resource.loader.path=/WEB-INF/mytemplates/
若是你须要设置彻底属于本身的 WebappResourceLoader,那么你须要作以下配置: 服务器
resource.loader=webapp webapp.resource.loader.class=org.apache.velocity.tools.view.WebappResourceLoader webapp.resource.loader.path=/WEB-INF/mytemplates/
下一步在初始化引擎时,你也须要把 ServletContext 放入 Velocity引擎的应用属性中,这使得 WebappResourceLoader 知道如何找到模板。
myVelocityEngine.setApplicationAttribute("javax.servlet.ServletContext", servletContext);
改变对象状态?--不要!
Velocity 提供了以引用方式调用对象方法的能力,这在页面上显示信息时颇有用,但当对象或应用状态改变时却很危险。
例如,下面的代码安全地调用了 列表的 size() 方法,用以显示结果:
There are $users.size() currently logged in.
而不安全的例子以下面的,一个财务页面,存在一个对象,逐年计算数据。calculateNextYear()方法用于计算下一年数据,并提升内部计数器。
2005 data: $table.data $table.calculateNextYear() 2006 data: $table.data
这一方法的问题在于 此段代码不能在当前页面中重复使用。你可能也不想这样作,但你很容易忘记,特别是当你须要剪切、复制控制语句时(如 #if 或者 #foreach),这在处理应用或会话层状态时所带来不少问题。
咱们建议的实践方式是仅使用 Velocity 显示信息,方法的调用仅用于获取信息,而不要改变对象状态,由于这样改变对象或应用状态很危险。
若是你以为你确实须要改变对象状态,尝试在控制器中计算所须要的值,而后将他们放进 List或Map中,记住使用控制器。
另外,补充一点,你应该习惯将 List 或 Set 放入页面上下文,而不要使用 Iterator 或 Enumeration,这很明显,List 或 Set能够被屡次使用,而 另外两个却不行。
HTML/XML实体转义
用户输入的文本中可能包含 HTML或XML实体,如 < > &,这些须要提交时被转义。这是必须的,由于要保证文本能够被正确显示,同时为阻止跨站脚本攻击。哦。。。。不像 JSTL,Velocity默认不提供转义。。。。
而后,Velocity 提供了 ReferenceInsertionEventHandler 来处理这个问题。你能够配置 EscapeHtmlReference 处理器进到 velocity.properties 文件,以正则表达式方式指定匹配内容。下面的例子将转义 以 msg开头的HTML实体,如 $msgText。
eventhandler.referenceinsertion.class = org.apache.velocity.app.event.implement.EscapeHtmlReference eventhandler.escape.html.match = /msg.*/
注意:其余的转义有时也是必须的,好比在样式表中 @ 字符须要被转义,JS字符串中单引号也须要转义。
加强应用安全
由于 web应用运行在服务器上,拥有不少用户和须要保密的资源,所以必须增强应用安全。Velocity引入了安全机制。具体见《 Building Secure Applications with Velocity 》(涉及系统配置、跨站脚本、方法自省)。另外,你能够指定 SecureUberspector 来防止页面设计者犯错误。
runtime.introspector.uberspect = org.apache.velocity.util.introspection.SecureUberspector
日志文件
A minor point is that (in some circumstances) Velocity, in the absence of any log-related configuration, creates a log file in the current directory. When Velocity is used in a web application the "current directory" is usually the current directory from which the application server is started. If you start seeing the file "velocity.log" files in random places on your server filesystem, check the Velocity log configuration. This is due to the default use of the Avalon Log Kit when present in the classpath. Typically this occurs when Velocity is used within a web application outside of web page generation (e.g. for sending email). To solve this problem, remove any file labeled "avalon-logkit" from the classpath or properly configure the log file location.
最后一小点,Velocity 在没有任何日志配置时,会在当前文件夹建立日志文件。当前文件夹通常是应用服务器启动时的目录。
下面是使用 VelocityViewServlet 建立 web应用的入门实例。注意:咱们建议您从源代码编译 VelocityViewServlet。而实际上,这不是必须的,咱们推荐这样只是为了让咱们有机会查看源代码并随后编译例子文件。
前提包括安装 JDK 和 Apache Ant.
了解更多,请参考 Velocity Tools 文档。
ant example.simple
<html> <body> I'm a velocity template. #if( $XHTML ) #set( $br = "<br />" ) #else #set( $br = "<br>" ) #end $br $br Here we use a custom tool: $toytool.message $br $br Here we get the date from the DateTool: $date.medium </body> </html>
<tools> <data type="boolean" key="xhtml" value="true"/> <data type="boolean" key="isSimple" value="true"/> <data type="number" key="version" value="2.0"/> <data key="foo">this is foo</data> <data key="bar">this is bar.</data> <toolbox scope="request"> <tool key="toytool" class="ToyTool" restrictTo="index*"/> </toolbox> <toolbox scope="session"> <tool key="map" class="java.util.HashMap"/> </toolbox> </tools>
<web-app> <servlet> <servlet-name>velocity</servlet-name> <servlet-class>org.apache.velocity.tools.view.VelocityViewServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>velocity</servlet-name> <url-pattern>*.vm</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.vm</welcome-file> </welcome-file-list> </web-app>
http://localhost:8080/simple/index.vm