9.1 使用Velocity模板
Velocity是一种针对Java应用的易用的模板语言。Velocity模板中没有任何Java代码,这使得它能够同时被非开发人员和开发人员轻松地理解。Velocity的用户手册上是这么说的:“Velocity将Java代码从Web页面中分离出来,使用Web站点从长远看更容易维护,并且提供了一种可行的JavaServer Pages替代解决方案。”
除了JSP,Velocity可能是用于Web应用的最流行的模板语言。因此很可能你会想采用Velocity作为视图层技术开发基于Spring的应用。幸运地是,Spring支持将Velocity作为Spring MVC的视图层模板语言。
让我们通过基于Velocity重新实现Spring培训应用中的视图层来看一下如何在Spring MVC中使用Velocity。
9.1.1 定义Velocity视图
假设你已经选择使用Velocity而不是JSP来创建Spring培训应用的视图。你需要使用Velocity模板编写的页面之一是显示可用课程列表的页面。程序清单 9.1 显示了courseList.vm,一个和courseList.jsp等价的用于显示课程列表的Velocity模板。
程序清单9.1 基于Velocity的课程列表
<html>
<head>
<title>Course List</title>
</head>
<body>
<h2>COURSE LIST</h2>
<table width="600" border="1" cellspacing="1" cellpadding="1">
<tr bgcolor="#999999">
<td>Course ID</td>
<td>Name</td>
<td>Instructor</td>
<td>Start</td>
<td>End</td>
</tr>
#foreach($course in $courses)
<tr>
<td>
<a href="displayCourse.htm?id=${course.id}">
${course.id}
</a>
</td>
<td>${course.name}</td>
<td>${course.instructor.lastName}</td>
<td>${course.startDate}</td>
<td>${course.endDate}</td>
</tr>
#end // 在所有课程中循环
</table>
</body>
</html>
可能你首先注意到的是这个模板中没有任何模板标签。这是因为Velocity不是基于与JSP类似的标签的,而是采用了它自己的语言——称为Velocity模板语言(VTL)——用于流程控制和其他指令。在courseList.vm中,#foreach指令用于循环处理一个课程列表,显示每个课程的明细。除了这个Velocity和JSP的基本区别之外,你会发现Velocity的表达式语言和JSP很相似。事实上,当JSP使用${}作为它自己的表达式语言时,它不过是模仿Velocity的做法而已。这个模板仅仅演示了很少一部分你可以使用Velocity所做的事情。
如果想知道更多,可以访问Velocity位于http://jakarta.apache.org/velocity的主页。注意当完成模板之后,你需要配置Spring使它可以在MVC应用中使用Velocity模板作为视图。
9.1.2 配置Velocity引擎
首先需要配置的是Velocity引擎自己。要做到这点,可以通过以下方式在Spring配置文件中声明一个VelocityConfigurer Bean:
<bean id="velocityConfigurer" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
<property name="resourceLoaderPath">
<value>WEB-INF/velocity/</value>
</property>
</bean>
VelocityConfigurer负责在Spring中设置Velocity引擎。这里,我们通过属性resourceLoaderPath告诉Velocity到哪里寻找它的模板。我们建议将模板放到WEB-INF的某个子目录下面,这样可以保证这些模板不能被直接访问。也可以通过velocityProperties属性来设置其他Velocity的配置细节。例如下面的VelocityConfigurer配置:
<bean id="velocityConfigurer" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
<property name="resourceLoaderPath">
<value>WEB-INF/velocity/</value>
</property>
<property name="velocityProperties">
<props>
<prop key="directive.foreach.counter.name">loopCounter</prop>
<prop key="directive.foreach.counter.initial.value">0</prop>
</props>
</property>
</bean>
可以注意到velocityProperties属性使用一个<props>元素来设置多个属性。在这里可以设置的属性与一个典型的Velocity应用中通过“velocity.properties”文件设置的属性是一样的。缺省地,Velocity的#foreach循环维护一个名为$velocityCount的循环计数器,该计数器在第一轮循环开始时从1开始计数。但这里我们设置属性directive.foreach.counter.name为loopCounter,因此将使用$loopCounter来引用循环计数器。我们也通过设置属性directive.foreach.counter.initial.value为0使循环计数器由零开始计数。(想知道关于Velocity配置属性的信息,请参考Velocity开发者指南http://jakarta.apache.org/velocity/developer-guide.html。)
9.1.3 解析Velocity视图
要使用Velocity模板视图,你必须做的最后一件事情是配置一个视图解析器。具体地说,需要以如下方式在Spring上下文配置中声明一个VelocityViewResolver Bean:
<bean id="viewResolver" class="org.springframework.
web.servlet.view.velocity.VelocityViewResolver">
<property name="suffix"><value>.vm</value></property>
</bean>
VelocityViewResolver和Velocity的关系与InternalResourceViewResolver和JSP的关系相似。正如InternalResourceViewResolver,它使用prefix属性和suffix属性由视图的逻辑名构造出模板文件的路径。这里我们仅仅设置suffix属性为“.vm”扩展名。由于模板目录的路径已经通过VelocityConfigurer的resourceLoaderPath属性配置好了,因此这里不需要设置前缀。
注意:这里把Bean的ID设置为viewResolver。这一点很重要,因为我们并没有配置DispatcherServlet检测所有的视图解析器。如果要同时使用多个视图解析器,则你很可能需要将这个ID改成某个更合适的名字(并且是惟一的),比如velocityViewResolver。
现在,你的应用系统已经可以渲染基于Velocity模板的视图了。你只需要在返回的ModelAndView对象中通过逻辑名引用所需的视图。以ListCourseController为例,不需要做其他事情,因为它已经返回如下的ModelAndView对象:
return new ModelAndView("courseList", "courses", allCourses);
视图的逻辑名为“courseList”。当解析这个视图时,“courseList”加上后缀“.vm”构成了一个模板名“courseList.vm”。VelocityViewResolver会在WEB-INF/velocity路径下寻找这个模板。
至于“courses”模型对象,它会作为一个Velocity属性暴露给Velocity模板使用。在程序清单9.1中,它就是在#foreach指令中使用的集合对象。
9.1.4 格式化日期和数字
尽管应用已经配置成可以渲染Velocity视图了,但我们还有一些杂七杂八的问题需要解决。当你比较程序清单9.1中的couseList.vm和courseList.jsp时,会注意到courseList.vm没有像courseList.jsp一样对课程的ID、开始日期和结束日期进行格式化。在courseList.jsp中,课程ID显示为一个6位定长的前面以零补齐的数字,而所有的日期以完整格式显示。为了完成courseList.vm,你需要对它作进一步的调整,对ID和日期属性进行格式化。
VTL并不直接支持日期和数字的格式化,而是通过提供日期和时间的工具类来支持格式化。为了允许使用这些工具,你需要告诉VelocityViewResolver在模板中暴露它们时使用的属性名。这些属性名是通过VelocityViewResolver的dateToolAttribute和numberToolAttribute属性来规定的:
<bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
…
<property name="dateToolAttribute">
<value>dateTool</value>
</property>
<property name="numberToolAttribute">
<value>numberTool</value>
</property>
</bean>
在这里,我们规定数字工具通过numberTool属性暴露给Velocity使用。因此,要格式化课程ID,你只需要通过数字工具的format()方法来处理课程ID即可,如下:
$numberTool.format("000000", course.id)
方法format()的第一个参数是模式字符串,在这里我们规定课程ID显示为6个数字的域,必要时在前面补零。模式字符串的语法和java.text.DecimalFormat一致。请参考Velocity关于NumberTool的文档来获取更多关于该工具功能的信息。
类似地,我们分配日期工具使用dateTool属性。为了格式化课程的开始和结束日期,只需使用日期工具的format()方法:
$dateTool.format("FULL", course.startDate)
$dateTool.format("FULL", course.endDate)
与数字工具的format()方法一样,第一个参数也是模式字符串。模式字符串的语法与java.text.SimpleDateFormat一致。另外,也可以设置模式字符串为FULL、LONG、MEDIUM、SHORT或DEFAULT中的一个,以使用标准的java.text.DateFormat模式。这里我们设置模式字符串为FULL来表示完整的日期格式。请参考Velocity关于DateTool的文档来获得更多关于该工具功能的信息。
9.1.5 暴露请求和会话属性
尽管需要在Velocity模板中显示的大多数数据都可以通过ModelAndView对象的模型Map传递给视图,有时候也会需要显示servlet请求或会话中的属性。比如,当用户登录到应用系统时,用户的信息可能存放在servlet会话中。
如果在每一个控制器中都将请求或会话的属性复制到模型Map中,这会是非常笨拙的。幸运的是,VelocityViewResolver会帮你将这些属性复制到模型中。属性exposeRequestAttributes和exposeSessionAttributes告诉VelocityViewResolver是否需要将servlet请求和会话中的属性复制到模型中。比如:
<bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
…
<property name="exposeRequestAttributes">
<value>true</value>
</property>
<property name="exposeSessionAttributes">
<value>true</value>
</property>
</bean>
这两个属性的默认值都为false。但在这里我们把这两个属性都设置为true,从而请求和会话的属性都会被复制到模型中,并且在Velocity模板中可见。9.1.6 在Velocity中绑定表单域
在第8章中,我们看到如何使用Spring的<spring:bind>JSP标签将表单域绑定到一个命令对象中。这个标签在向用户显示表单域相关的错误时也是非常有用的。
幸运的是,当你使用Velocity而不是JSP时,不必放弃<spring:bind>提供的功能。Spring提供了若干个Velocity宏来模仿<spring:bind>标签的功能。
例如,假设Spring培训应用的学生注册表单是用Velocity模板编写的。程序清单9.2显示了registerStudent.vm中的一段,演示如何使用#springBind宏:
程序清单9.2 在Velocity模板中使用#springBind
#springBind("command.phone")
phone: <input type="text"
name="${status.expression}"
value="http://www.blog.edu.cn/$!status.value">
<font color="#FF0000">${status.errorMessage}</font><br>
#springBind("command.email")
email: <input type="text"
name="${status.expression}"
value="http://www.blog.edu.cn/$!status.value">
<font color="#FF0000">${status.errorMessage}</font><br>
#springBind宏的参数是被绑定表单域的引用路径。它在模板中设置了一个名为status的变量用于保存表单域的名称、值以及可能出现的任何错误信息(可能来自一个验证器)。
如果错误信息中包含在HTML中有特殊意义的字符(比如:<,>,&),你可能需要对错误信息进行转义以正确显示在Web浏览器中。在这种情况下,你需要使用宏#springBindEscaped而不是#springBind:
#springBindEscaped("command.email", true)
除了域的引用路径之外,#springBindEscaped宏接受一个boolean参数,表明是否需要对错误信息中的HTML特殊字符进行转义。如果该参数为false,则宏#springBindEscaped和#springBind的行为完全一样,HTML特殊字符不会被转义。
为了在模板中使用Spring的宏,你需要通过VelocityViewResolver的exposeSpringMacroHelpers来使用这些宏:
<bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
…
<property name="exposeSpringMacroHelpers">
<value>true</value>
</property>
</bean>
通过把exposeSpringMacroHelpers属性设为true,你就能在Velocity模板中使用#springBind和#springBindEscaped宏。
尽管Velocity是一种广泛使用的JSP的替代技术,它不是惟一可以使用的替代模板技术。FreeMarker是另一种广为人知的用于在MVC应用的视图层中替代JSP的模板语言
分享到:
相关推荐
在Spring MVC的配置文件(如`spring-mvc.xml`)中,你需要配置VelocityViewResolver,这是Spring MVC用来解析Velocity模板的类。设置其prefix和suffix属性,分别指定视图前缀和后缀,例如: ```xml ...
整合 Shiro、Spring 和 Velocity 可以创建一个强大的安全模板系统,既能确保用户的安全性,又能根据用户角色动态生成页面内容。这种灵活性和控制力使得开发者能够构建更健壮、更安全的应用程序。
标题“spring+velocity+ibatis”揭示了一个基于Java的Web应用程序开发组合,它结合了Spring框架、Velocity模板引擎和iBatis数据访问层。这个项目可能是为了演示或教学如何有效地集成这三个组件,以便构建一个完整的...
标题“spring-velocity-support-2.3”暗示了一个关于Spring框架对Velocity模板引擎支持的特定版本,即2.3版。这个版本可能包含了用于整合Spring和Velocity的各种组件、类库和配置,使得开发者能够利用Velocity的强大...
Velocity模板语言(VTL)简洁、直观,可以避免在模板中出现Java代码,提高了可读性和可维护性。开发者可以使用Velocity来生成动态内容,通过引用Java对象的属性和方法来填充模板。 在`Struts2+Spring+Velocity`项目...
《Spring Boot整合Velocity模板引擎详解》 在现代Java Web开发中,Spring Boot以其简洁的配置、强大的功能和高效的开发效率,成为了许多开发者的首选框架。而Velocity作为一款轻量级的模板引擎,能够帮助我们快速...
在Spring Boot项目中,使用Velocity模板引擎可以自定义生成代码,如Mapper、Mapper.xml、Service、Controller等。Mapper是数据库操作层,通常配合MyBatis框架使用;Mapper.xml包含SQL语句;Service是业务逻辑层,...
实例中可能包含多个Velocity模板文件,展示了如何通过Velocity模板语言来动态生成页面内容。 在这个扩展实例中,开发者可能已经完成了以下关键步骤: 1. 配置Struts2的配置文件(struts.xml),定义Action和结果...
2. **配置Spring MVC**:在Spring的配置文件中,配置Spring MVC的DispatcherServlet,并设置视图解析器为VelocityViewResolver,指定Velocity模板文件的路径。 3. **配置Sitemesh**:在web.xml中配置Sitemesh的...
其次,Spring整合Hibernate,提供数据访问层的支持,通过JPA接口,开发者可以使用面向对象的方式进行数据库操作。同时,Spring可以管理Hibernate的SessionFactory和Transaction,简化事务管理。 具体步骤可能包括...
2. **Model与View**:在Controller处理完业务逻辑后,将Model数据传递给Velocity模板,Velocity根据Model中的数据生成最终的HTML页面。 3. **配置整合**:在Spring的配置文件中,可以配置Hibernate的数据源、...
本项目主要探讨的是如何将SpringBoot与Mybatis、Velocity模板引擎进行整合,以便更高效地展示和处理数据。 首先,让我们深入了解SpringBoot的核心特性。SpringBoot的设计理念是“约定优于配置”,它内置了Tomcat...
在Java Web开发中,Spring框架和Velocity模板引擎都是常见的工具。Spring主要用于依赖注入、AOP(面向切面编程)以及企业级应用的构建,而Velocity则是一个轻量级的模板引擎,专注于视图层的渲染,提供简洁的语法来...
SpringBoot 2.x 版本对 Velocity 模板不支持的解决方案 随着 SpringBoot 的版本升级,Velocity 模板引擎不再被支持。从 SpringBoot 1.5.x 版本开始,Velocity 模板引擎的支持就被逐步删除,而在 2.x 版本中,...
4. **配置Velocity**:在Web应用的配置中设置VelocityViewResolver,指定Velocity模板文件的路径。在Velocity的配置文件velocity.properties中,可以设置模板语言的规则。 5. **编写业务逻辑**:根据需求创建服务层...
5. **创建Velocity模板**:在src/main/webapp/WEB-INF/velocity目录下创建Velocity模板文件,用于渲染视图。 6. **编写业务逻辑**:创建Java服务类,利用Spring的依赖注入获取需要的对象,如Mybatis的Mapper接口。 ...
本话题将详细讲解如何在Spring MVC框架中整合Velocity和JSP,实现多视图解析器的功能,从而根据需求返回不同的视图。 **1. Velocity模板引擎** Velocity是一个开源的Java模板引擎,它允许开发者将业务逻辑与展示...
在这个整合实例中,开发者可以学习到如何设置Maven的POM.xml文件来管理所有依赖,如何配置Spring MVC的DispatcherServlet和ApplicationContext,如何定义Mybatis的Mapper接口和XML配置文件,以及如何在Velocity模板...
本文主要介绍了如何使用Spring Boot与Velocity进行模板引擎的结合,详细地讲解了Velocity的概念、Spring Boot与Velocity的结合配置、Velocity模板的使用等。 一、Velocity简介 Velocity是一种Java模版引擎技术,...