Struts2 官方教程:处理表单(Processing Forms)

介绍

本篇教程中,将探索使用Struts2来做更多的表单提交信息处理。我们会讲解如何使用一个Java模型类来存储表单输入,以及如何构建Struts2 表单来配合模型类。
本篇教程中提供的代码可以添加到教程《Struts2动作类代码编写》的示例,活着也可以从github网站上下载完整示例。

表单和Java模型类

在本篇教程里,我们假设需要提供一个表单,让用户为了抽奖活动而提交用于注册的信息。我们的业务规则规定,用户必须提供他/她的姓、名、电子邮箱地址,以及年龄。
为了封装这些数据,我们讲使用一个简单的Java类,遵循基础的Java Bean规范(为每个实例区都提供公开的set/get方法)。如果你一路忠诚拜读系列教程至此,可以把下面这个类添加到《Struts2动作类代码编写》示例代码中的org.apache.struts.register.model包中。

Person.java

public class Person {
    private String firstName;
    private String lastName;
    private String email;
    private int age;

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return "First Name: " + getFirstName() + " Last Name:  " + getLastName() + 
        " Email:      " + getEmail() + " Age:      " + getAge() ;
    }
}

注意上面这个类中的几个点。每个实例域(成员变量)都有一个公开的set/get方法。age属性是integer类型。定义了一个公开的toString()方法,返回一个代表对象状态的字符串。由于我们没有指定构造函数,Java回提供一个默认的构造函数,会用对应的null值设置所有的实例域。

表单结构

为了收集上述信息,我们将使用一个Struts2表单。构建这个表单时,需要引入的关键概念是:把每个表单域对应到Person类型对象的一个特定实例域。先整体地看一下表单,然后再讨论关键点。在src/main/webapp路径下创建名为register.jsp的页面。

register.jsp

<%@ taglib prefix="s" uri="/struts-tags" %>
<%@ page language="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>

<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-i" />
</head>

<body>
<h3>完成填表即可注册抽奖!</h3>

<s:form action="register">
<s:textfield name="personBean.firstName" label="名"/>
<s:textfield name="personBean.lastName" label="姓"/>
<s:textfield name="personBean.email" label="电子邮箱" /s>
<s:textfield name="personBean.age" label="年龄" />
<s:submit/>
</s:form>

</body>

</html>

由于我们使用Struts2标签,所以在页面最上方需要写Struts标签库的声明。
Struts2表单将会向一个名为register的动作提交,所以我们需要在struts.xml文件中定义这个动作。
注意四个Struts2的textfield标签。每个标签有一个name值,包括了一个Person类的属性(例如firstName)。这个name属性的值也有一个指向名为personBean对象的引用。这个对象的类型是Person。当我们创建控制这个表单提交行为的动作类,我们要在动作类中指定对象(见下方)。
完整的name值,personBean.firstName,引导Struts2使用这个textfield的输入值作为参数提供给personBean对象的setFirstName方法。这样如果用户在标签为“名”的textfield中输入了“Bruce”,那么personBean的firstName实例域,值就是“Bruce”。
注意我们对Person类的每个实例域都有了一个Struts2的textfield。记住,Person类的年龄属性是integer类型。所有表单域的输入值都是字符串。当调用personBean对象的setAge方法时,Struts2会自动地将用户为年龄表单域输入的字符串类型值(“25”)转换为25。

创建动作类来掌控表单提交

当用户点击上面表单的“提交”按钮,“register”这个动作以及表单数据会被发送到Struts2框架。我们需要一个动作类来处理这个表单。回顾一下前面的教程吧,自己编写的动作类应当继承Struts2的ActionSupport类。
这里是本示例所用的动作类。请将它打包到org.apache.struts.register.action。

Register.java Struts 2 动作类

package org.apache.struts.register.action;

import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts.register.model.Person;

public class Register extends ActionSupport{
 private static final long serialVersionUID = 1L;

    private Person personBean;


    public String execute() throws Exception {
        //call Service class to store personBean's state in database

        return SUCCESS;
    }

    public Person getPersonBean() {
        return personBean;
    }

    public void setPersonBean(Person person) {
        personBean = person;
    }
}

在Register类中,注意到我们已经声明了一个Person类型、名为personBean的属性(译者注:成员变量),并且Register对这个实例拥有公开的get和set方法。
Register类也重写了execute方法。execute是我们会在struts.xml中指定调用来响应register动作的方法。在这个例子中,execute方法只是返回了字符串常量SUCCESS(继承自ActionSupport类)。但在真正的应用里,在execute方法中我们应当调用其它类(服务实体)来执行表单的业务处理,例如存储用户的输入到数据仓库。
在Register动作类中声明的,Person类型的personBean这个实例,对应到我们在表单中name值为personBean的textfield。当表单被提交,Struts2框架将会检查动作类并且寻找名为personBean的实例;会使用Person类的默认构造函数创建这个实例。然后,对每个拥有name值为personBean.某某某(例如personBean.firstName)的表单域,将会为这个属性调用personBean的公开set方法,并且将表单域的值(即用户的输入)传递过去。这些都发生在execute方法执行之前。
当Struts2执行Register的execute方法,Register类的personBean实例的实例域(译者注:成员变量)现在拥有了对应自己这个实例的值,等于用户在对应的表单域里输入的值。
通过使用一个Java模型类来封装表单提供的数据,我们就不必在动作类(Register)中,为每个表单域都提供单独的属性(及公开的set/get方法们)。 【译者注:目前这里的“模型类”应该是指Person类。“封装对应表单域的属性和set/get方法”是一定要存在的;要么像先前示例那样在动作类中书写,要么像本例这样放在Person这个模型类里,让动作类不体现这些细节。】

在视图中添加结果

当execute方法返回了“SUCCESS”,我们希望为用户的注册显示一个简单的感谢页面。在src/main/webapp路径下添加thankyou.jsp。

thankyou.jsp

<%@ taglib prefix="s" uri="/struts-tags" %>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Registration Successful</title>
  </head>
  <body>
    <h3>Thank you for registering for a prize.</h3>

    <p>Your registration information: <s:property value="personBean" /> </p>

    <p><a href="<s:url action='index' />" >Return to home page</a>.</p>
  </body>
</html>

如果读者没想起来Struts2的property和url标签是如何工作的,回头看看《使用Struts2标签》教程。

在struts.xml中创建动作映射

为了指定表单提交页、Struts2动作类、以及success视图页面之间的关系,现在要在struts.xml中添加一个动作结点。将以下动作结点添加到struts.xml中,在hello动作之后、包封闭结点之前。

struts.xml中的action结点

<action name="register" class="org.apache.struts.register.action.Register" method="execute">
<result name="success">/thankyou.jsp</result>
</action>

以上动作告诉Struts2,当register动作被提供来调用Register类的execute方法,如果方法返回了“success”这个结果,那么把thankyou.jsp这个页面返回给浏览器。
注意,咱并不需要告诉Struts2任何关于处理表单的过程。表单域输入值传输到personBean实例会自动地发生,因为我们遵循了“将表单域命名与personBean属性名一致”的规则(例如表单域中的lastName与personBean.lastName)。

创建到Register.jsp的链接

添加以下链接到index.jsp,这样用户就可以找到注册页面咯。

到register.jsp的链接

<p>请先<a href="register.jsp">注册</a>就能抽奖咯</p>

运行示例

若万事俱备,就可以运行这个应用,并且再浏览器中打开index.action。页面里应当有一个注册的链接。点击这个链接,应能看到注册页面。
这里写图片描述
填写表单,并且点击“提交”按钮。
这里写图片描述
应当能看到thankyou.jsp页面。
这里写图片描述

猜你喜欢

转载自blog.csdn.net/u010930289/article/details/76736576