6.7 在Struts中使用Velocity

的模板语言。在WebWork早期版本中是默认的模板编写语言,不过升级Struts2后更加推荐使用FreeMarker,因为它有比Velocity更好的错误报告,支持JSP Tag,还有其他一些细微优点。当然,它们都是JSP很好的替代品。由Velocity编写的文件后缀名为“.vm”。(请参考第5章中关于Velocity Result的介绍)。

本节介绍Velocity在Struts2中是如何应用的,Velocity的详细使用方法请参考Velocity文档。Velocity是apache基金会支持的一个项目,可以访问它的网站http://velocity.apache.org/来学习它。

6.7.1 最简单的应用

开始使用velocity,首先需要保证所有的依赖都已经被加入到工程的CLASSPATH。其次,struts-default.xml中要配置好VelocityResult,它将映射action和模板。这里给出的例子功能与6.6节给出的基本一样,只是把登录功能改成注册功能。具体步骤如下:

1)在web.xml文件配置关于Struts2和velocity,具体内容如实例6-23所示。

【实例6-23】web.xml配置文件:web.xml

01          <filter>
02                <filter-name>struts2</filter-name>
03                <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
04          </filter>
05          <!--FilterDispatcher用来初始化Struts2并且处理所有的Web请求-->
06          <filter-mapping>
07                <filter-name>struts2</filter-name>
08                <url-pattern>/*</url-pattern>
09          </filter-mapping>
10          <servlet>
11                <servlet-name>velocity</servlet-name>
12                <servlet-class>org.apache.velocity.tools.view.VelocityViewServlet</servlet-
13     class>
14          </servlet>
15          <servlet-mapping>
16                <servlet-name>velocity</servlet-name>
17                <url-pattern>*.vm</url-pattern>
18          </servlet-mapping>
19          <welcome-file-list>
20                <welcome-file>index.jsp</welcome-file>
21          </welcome-file-list>
22     </web-app>

【代码剖析】上述代码的第6行到第9行实现对Struts2核心过滤器的配置,接着配置类velocity,该类支持在velocity中进行一些配置。

2)利用velocity模板创建出关于注册、注册成功和注册失败页面,具体内容如实例6-24、实例6-25和实例6-26所示。

【实例6-24】关于注册页面:register.vm

01     <html>
02          <head>
03                <title>register</title>
04          </head>
05          <body>
06                <form action="userRegister.action" method="post">
07                     <table align="center">
08                          <tr>
09                                <td>
10                                    注册页面
11                                </td>
12                                <td>
13                                </td>
14                          </tr>
15                          <tr>
16                               <td>         <!--关于用户名输入框-->
17                                    用户名:
18                                     <input type="text" name="username">
19                                </td>
20                          </tr>
21                          <tr>
22                               <td>         <!--关于密码输入框-->
23                                    密码:
24                                     <input type="password"
25     name="password">
26
27                                </td>
28                          </tr>
29                          <tr>
30                               <td>         <!--关于年龄输入框-->
31                                    年龄:
32                                     <input type="text" name="age">
33
34                                </td>
35                          </tr>
36                          <tr>
37                               <td>         <!--关于提交按钮-->
38                                     <input type="submit" name="submit"
39     value="提交" />
40                                </td>
41                          </tr>
42                     </table>
43                </form>
44          </body>
45     </html>

【运行程序】浏览该页面,结果如图6.19所示。

【代码剖析】上述代码只是普通的HTML代码,不过该文件的后缀名.vm。

【实例6-25】关于注册成功页面:success.vm

01     <html>
02          <head>
03                <title>success</title>
04          </head>
05          <body>
06               以下是您注册的信息:
07                <br>
08               用户名:$username                        <!--显示用户名-->
09                <br>
10               密码:$password                          <!--显示密码-->
11                <br>
12               年龄:$age                              <!--显示年龄-->
13                <br>
14          </body>
15     </html>

【运行程序】注册成功,结果如图6.20所示。

图6.19 注册页面

图6.20 注册成功

【代码剖析】上述代码中通过$属性名,来输出保存在Session中user对象相应属性的值。

【实例6-26】关于登录失败页面:error.vm

01     <html>
02          <head>
03                <title>error</title>
04          </head>
05          <body>
06               $state                                               <!--显示相应的信息-->
07          </body>
08     </html>

【运行程序】注册失败,结果如图6.21所示。

图6.21 注册失败

【代码剖析】上述代码中第6行$state表示输出保存在ActionContext中的值。

3)建立Action类,该类主要通过获取HTTP请求、参数等,然后实现该项目的逻辑功能,具体内容如实例6-27所示。

【实例6-27】关于Action类:RegiserAction.java

01     public class RegiserAction implements Action {
02          private String username;                               //关于用户名变量
03          private String password;                               //关于密码变量
04          private int age;                                     //关于年龄变量
05          public String getUsername() {                           //设置用户名的getter和setter方法
06                return username;
07          }
08          public void setUsername(String username) {
09                this.username = username;
10          }
11          public String getPassword() {                           //设置密码的getter和setter方法
12                return password;
13          }
14          public void setPassword(String password) {
15                this.password = password;
16          }
17          public int getAge() {                                 //设置年龄的getter和setter方法
18                return age;
19          }
20          public void setAge(int age) {
21                this.age = age;
22          }
23          public String execute() throws Exception {                //重写执行方法
24               // 判断注册的用户名是否存在
25                ActionContext ctx = ActionContext.getContext();
26                if (this.getUsername().equals("cjgong")) {
27                    ctx.put("state", "该用户名已经存在, 请重新注册");
28                    return "error";                          //返回出错字符串
29                } else {
30                     ctx.put("username", this.getUsername());
31                     ctx.put("password", this.getPassword());
32                     ctx.put("age", this.getUsername());
33                    return "success";                        //返回成功字符串
34                }
35          }
36     }

【代码剖析】上述代码首先创建了关于用户名字和密码的属性,然后为这些属性创建方法,最后在execute()方法中实现了该项目的逻辑功能。

如果想让该项目正常运行,还必须在struts.xml文件中配置上述代码,具体内容如实例6-28所示。

【实例6-28】关于struts配置文件:struts.xml

01     <struts>
02          <package name="com" extends="struts-default">
03                <action name="*">
04                     <result type="velocity">/userRegister/{1}.vm</result>
05                </action>
06                <action name="userRegister" class="com.cjg.RegiserAction">
07                    <!--指定result的type为velocity-->
08                     <result name="success" type="velocity">
09                          /userRegister/success.vm
10                     </result>
11                     <result name="error" type="velocity">
12                          /userRegister/error.vm
13                     </result>
14                </action>
15          </package>
16     </struts>

【代码剖析】上述代码中将标签<result>的type设为velocity,当注册成功则会转向success.vm,当注册失败则会转向error.vm。

6.7.2 变量解析

在Velocity中,将从几个不同的位置查找变量。顺序如下:

1)值栈(value stack)。

2)action上下文(context)。

3)内置对象。

Velocity中内置对象如表6.27所示。

表6.27 Velocity内置对象表

6.7.3 配置Velocity

有时可能希望扩展Struts2提供的Velocity支持。最常见的原因是希望加入自己的标签,就像从Struts2内建的标签中扩展一样。

想要这样做,写一个新的扩展自com.opensymphony.webwork. views.velocity.VelocityManager的类或者也可以覆盖它,然后增加如下内容到webwork.properties:

webwork.velocity.manager.classname = com.yourcompany.YourVelocityManager

可以通过替换velocity.properties中的配置项来配置Velocity。

6.7.4 在VM文件中使用标签

Velocity标签是WebWork提供的一般Tag的扩展,只要简单地了解这些标签的访问方式: #sxxx (...) ... #end (),就可以马上开始使用了。

注意

“#s”后面是没有空格的,它与标签名称直接连在一起(虽然不会发生什么混乱,但在阅读上实在很不舒服,而且Velocity没有采用主流的XML格式)。

还是那个例子,在JSP中可能这样创建一个form:

<s:form action="updatePerson">
    <s:textfield label="First name" name="firstName"/>
    <s:submit value="Update"/>
</s:form>

在Velocity中同样的form这样创建:

#sform ("action=updatePerson")
    #stextfield ("label=First name" "name=firstName")
    #ssubmit ("value=Update")
#end

在上面的例子中注意到,一些标签需要“#end”声明,而其他的却不需要。这是由于Velocity中的限制,如果有块(block)或者内联(inline)标签在前面,标签必须声明#end。而默认情况下所有的标签都是内联(inline)的,除了很少的几个,例如form标签。