Struts 2.x权威指南
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

3.7.2 使用模型驱动

下面以一个简单的登录应用为例,介绍如何利用模型驱动模式来开发Struts 2应用。本应用的登录页面与前面的登录页面并没有太多不同,一样提供了两个文本框,分别用于输入用户名和密码,当用户单击“登录”按钮时,请求将提交到login.action。

login Action采用模型驱动模式实现,采用模型驱动模式时必须提供对应的模型,该模型类就是一个普通JavaBean。模型代码如下。

程序清单:codes\03\3.7\ModelDriven\WEB-INF\src\lee\UserBean.java

public class UserBean
{
    // 下面是用于封装用户请求参数的两个属性
    private String username;
    private String password;
    // 封装提示信息的tip属性
    private String tip;
    // username属性的getter和setter方法
    public String getUsername()
    {
          return username;
    }
    public void setUsername(String username)
    {
          this.username = username;
    }
    // password属性的getter和setter方法
    public String getPassword()
    {
          return password;
    }
    public void setPassword(String password)
    {
          this.password = password;
    }
    // tip属性的setter和getter方法
    public void setTip(String tip)
    {
          this.tip = tip;
    }
    public String getTip()
    {
          return this.tip;
    }
}

上面的Model类完全是一个POJO(普通的Java对象),仅仅提供了两个用于封装请求参数的属性,提供了一个封装处理结果的属性,并为三个属性提供了对应的getter和setter方法。

对于采用模型驱动的Action而言,该Action必须实现ModelDriven接口,下面是本应用所使用的Action的代码。

程序清单:codes\03\3.7\ModelDriven\WEB-INF\src\org\crazyit\struts2\action\LoginAction.java

// 采用模型驱动的Action必须实现ModelDriven接口
public class LoginAction implements Action
    , ModelDriven<UserBean>
{
    // 定义用于封装请求参数和处理结果的模型
    private UserBean model = new UserBean();
    // 处理用户请求的execute方法
    public String execute() throws Exception
    {
          // 当用户请求参数的username等于crazyit,密码请求参数为leegang时
          // 返回success字符串,否则返回error字符串
          if (getModel().getUsername().equals("crazyit")
                && getModel().getPassword().equals("leegang"))
          {
                getModel().setTip("哈哈,服务器提示!");
                return SUCCESS;
          }
          else
          {
                return ERROR;
          }
    }
    //实现ModelDriven接口必须实现的方法
    public UserBean getModel()
    {
          return model;
    }
}

使用模型驱动模式时,Action 必须实现 ModelDriven 接口,实现该接口则必须实现getModel()方法,该方法用于把Action和与之对应的Model实例关联起来。

配置模型驱动的Action与配置属性驱动的Action没有任何区别,Struts 2不要求配置模型对象,即不需要配置UserBean实例。

比较难以理解的是,系统是如何将请求参数封装到LoginAction的model属性中的呢?查看struts-default.xml文件,看到如下配置片段。

<!-- 定义Struts 2默认的包 -->
<package name="struts-default">
    <!-- 该元素里定义该框架所有的拦截器和拦截器栈 -->
    <interceptors>
          ...
          <!-- 定义属性驱动的拦截器 -->
          <interceptor name="params"
                class="com.opensymphony.xwork2.interceptor.Parameters Interceptor"/>
          <!-- 定义模型驱动的拦截器 -->
          <interceptor name="modelDriven"
                class="com.opensymphony.xwork2.interceptor.ModelDriven Interceptor"/>
          ...
          <!-- 定义一个模型驱动的拦截器栈 -->
          <interceptor-stack name="modelDrivenStack">
                <interceptor-ref name="modelDriven"/>
                <interceptor-ref name="basicStack"/>
          </interceptor-stack>
          ...
          <!-- 定义一个默认的拦截器栈 -->
          <interceptor-stack name="defaultStack">
                ...
                <!-- 定义模型驱动模式的拦截器 -->
                <interceptor-ref name="modelDriven"/>
                <!-- 定义属性驱动模式的拦截器 -->
                <interceptor-ref name="params">
                ...
          </interceptor-stack>
    </interceptors>
    <!-- 定义Struts 2系统默认的拦截器栈 -->
    <default-interceptor-ref name="defaultStack"/>
</package>

上面的配置片段中配置了系统默认的拦截器栈,它包含了两个拦截器引用:modelDriven和params,这两个拦截器引用又对应系统中的modelDriven和params拦截器。其中params拦截器负责提取请求参数,如果使用属性驱动模式,则还负责将请求参数传给 Action 实例的属性;而modelDriven拦截器则负责将请求参数传给模型的属性。

采用了上面的模型驱动模式后,Action 类里没有直接封装处理结果,而是封装在 model属性的tip属性中。因此,如果想在JSP页面上输出服务器处理结果,则应该采用如下形式的标签。

<!-- 使用表达式输出Action实例中model属性的tip属性 -->
<s:property value="model.tip"/>

如果在登录页面中输入 crazyit、leegang,然后提交登录请求,将看到如图3.28所示的页面。

图3.28 成功登录的页面

当然,Struts 2是一个非常“智能”的系统,当采用模型驱动模式时,也可以采用如下形式来输出Action属性。

<!-- 直接输出Action的tip属性 -->
<s:property value="tip"/>

因为 Action 实例中没有 tip 属性,并且采用了模型驱动模式,系统将自动输出该 Action关联的model的tip属性值。

通过上面的应用可以看出,模型驱动和属性驱动各有利弊,模型驱动结构清晰,但编程烦琐(需要额外提供一个JavaBean来作为模型);属性驱动则编程简洁,但结构不够清晰。

通常,笔者更愿意选择属性驱动作为Struts 2的应用模式,毕竟,大量定义烦琐的JavaBean不是一件让人感兴趣的事情;而即使采用属性驱动,Struts 2一样提供了非常清晰的处理流程。