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

2.5.3 添加处理信息

到目前为止,Action仅仅控制转发用户请求,JSP页面并未获得Action的处理结果。对于大部分Web应用而言,用户需要获得请求Action的处理结果。例如,在线购物系统需要查询某个种类下的商品,则 Action 调用业务逻辑组件的业务逻辑方法得到该种类下的全部商品,而JSP页面则获取该Action的处理结果,并将全部结果迭代输出。

下面为应用增加一个Action,该Action负责获取某个系列的全部书籍。为了让该Action可以获取这系列的书籍,我们增加一个业务逻辑组件,它包含一个业务逻辑方法,该方法可以获取某个系列的全部书籍。

下面是系统所用的业务逻辑组件的代码。

程序清单:codes\02\struts2qs2\WEB-INF\src\org\crazyit\struts2qs\service\BookService.java

public class BookService
{
    //以数组模拟从持久存储设备(数据库)中取出的数据
    private String[] books = new String[] {
                "疯狂Java讲义" ,
                "疯狂Android讲义" ,
                "轻量级Java EE企业应用实战",
                "疯狂Ajax讲义",
                "疯狂XML讲义",
          };
    //业务逻辑方法,该方法返回全部图书
    public String[] getLeeBooks()
    {
          return books;
    }
}

上面的业务逻辑组件实际上就是MVC模式中的Model,它负责实现系统业务逻辑方法。理论上,业务逻辑组件实现业务逻辑方法时,必须依赖于底层的持久层组件,但此处的业务逻辑组件则只是返回一个静态的字符串数组——因为这只是一种模拟。

注意

此处的业务逻辑组件只是模拟实现业务逻辑方法,并未真正调用持久层组件来获取数据库信息。

在系统中增加如下Action类,该Action类先判断HTTP Session中的user属性是否存在且等于 crazyit 字符串——这要求在查看图书之前,用户必须已经登录本系统。如果用户已经登录本系统,则获取系统中的全部书籍,否则返回登录页面。新增的Action类的代码如下。

程序清单:codes\02\struts2qs2\WEB-INF\src\org\crazyit\struts2qs2\action\GetBooksAction.java

public class GetBooksAction implements Action
{
    // 该属性并不用于封装用户请求参数
    // 而用于封装Action需要输出到JSP页面的信息
    private String[] books;
    // books属性的setter、getter方法
    public void setBooks(String[] books)
    {
          this.books = books;
    }
    public String[] getBooks()
    {
          return books;
    }
    // 处理用户请求的execute方法
    public String execute() throws Exception
    {
          // 获取Session中的user属性
          String user = (String)ActionContext.getContext()
                .getSession().get("user");
          // 如果user属性不为空,且该属性值为crazyit
          if (user != null && user.equals("crazyit"))
          {
                // 创建BookService实例
                BookService bs = new BookService();
                // 将业务逻辑组件的返回值设置成该Action的属性
                setBooks(bs.getLeeBooks());
                return SUCCESS;
          }
          else
          {
                return LOGIN;
          }
    }
}

通过上面的Action类,我们发现Action类中的成员属性,并不一定用于封装用户请求参数,也可能是封装了Action需要传入下一个JSP页面中显示的属性。

提示:

Action中的成员属性,不一定用于封装用户请求参数,也可能是封装了Action需要传递到页面中显示的值。实际上,这些值将被封装在ValueStack对象中。

当控制器需要调用业务逻辑方法时,程序直接创建了一个业务逻辑组件实例,这并不是一种好的做法,因为控制器不应该关心业务逻辑组件的实例化过程。比较成熟的做法是可以利用工厂模式来管理业务逻辑组件;当然,目前最流行的方式是利用依赖注入——这将在与Spring整合的章节里介绍。

注意

在实际项目中,不会在控制器中直接创建业务逻辑组件实例,而是通过工厂模式管理业务逻辑组件实例,或者通过依赖注入将业务逻辑组件实例注入控制器组件。

该Action处理用户请求时,无须获得用户的任何请求参数。将该Action配置在struts.xml文件中,配置该Action的配置片段如下。

程序清单:codes\02\struts2qs2\WEB-INF\src\struts.xml

<!-- 定义获取图书的Action,对应实现类为org.crazyit.struts2qs.action.GetBooksAction-->
<action name="getBooks" class="org.crazyit.struts2qs.action.GetBooksAction">
    <!-- 如果处理结果返回login,则进入loginForm.jsp页面 -->
    <result name="login">/loginForm.jsp</result>
    <!-- 如果处理结果返回success,则进入showBook.jsp页面 -->
    <result name="success">/showBook.jsp</result>
</action>

当用户向getBooks.action发送请求时,该请求将被转发给lee.GetBooksAction处理。