4.4 动态方法调用以及校验动态方法
Struts 2允许在一个Action中包含多个处理逻辑,从而通过调用Action中不同的方法来处理请求。同样对于每个处理逻辑,都可以提供相应的校验方法。下面介绍如何添加动态方法调用以及校验动态方法的使用。
4.4.1 动态方法调用
Struts 2允许在一个Action中包含多个处理逻辑。例如在同一个表单中,用户通过不同的按钮提交表单时,在Action中调用不同的方法来处理请求。
下面来看一个简单示例。首先新建如下的JSP页面。该页面同前面的用户注册页非常类似,不同的是增加了一个“删除”按钮,代码如下所示。
<%@ page language="java" import="java.util.*" pageEncoding="gb2312"%> <%@ taglib prefix="s" uri="/struts-tags" %> <! DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>注册页面</title> </head> <body> <! -- 注册表单 --> <center> <h2>注册页面</h2> <s:form action="register"> <s:textfield name="username" label="用户名"></s:textfield> <s:password name="password" label="密码"></s:password> <s:password name="repassword" label="确认密码"></s:password> <s:textfield name="age" label="年龄"></s:textfield> <s:textfield name="birth" label="出生日期"></s:textfield> <s:textfield name="email" label="邮箱地址"></s:textfield> <s:submit value="注册"></s:submit> <s:submit value="删除" action="register! deleteUser"></s:submit> </s:form> </center> </body> </html>
“删除”按钮中指定action属性值为register! deleteUser,表示将表单提交给配置名为regist的Action的deleteUser方法来处理。
下面再增加一个Action。该Action与前面的RegisterAction类似,只是添加deleteUser方法。在deleteUser方法中简单地添加一句语句打印到控制台上,方便查看运行结果,代码如下所示。
package net.hncu.action; import java.util.Calendar; import java.util.Date; import java.util.regex.Pattern; import com.opensymphony.xwork2.ActionSupport; public class RegisterAction extends ActionSupport{ private String username; private String password; private String repassword; private int age; private Date birth; private String email; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getRepassword() { return repassword; } public void setRepassword(String repassword) { this.repassword = repassword; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Date getBirth() { return birth; } public void setBirth(Date birth) { this.birth = birth; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public void validate() { } public String deleteUser() throws Exception { System.out.println("delete method"); return SUCCESS; } public String execute() throws Exception { System.out.println("execute method"); return SUCCESS; } }
接下来在“struts.xml”文件中配置该Action,代码如下所示。
<struts> <package name="struts2" extends="struts-default"> <! -- 定义register的Action,其实现类为net.hncu.action.RegisterAction--> <action name="register" class="net.hncu.action.RegisterAction"> <! -- 定义处理结果与视图资源之间的关系--> <result name="success">/result.jsp</result> <result name="input">/register.jsp</result> </action> </package> </struts>
运行用户注册页,如图4.18所示。该注册页中包含两个按钮,分别对应着不同的处理逻辑。
这里为了简单测试,并不输入任何的用户信息。直接单击“注册”按钮,在控制台将打印如下语句。
execute method
这表示在Action中执行的是execute方法。如果单击“删除”按钮,在控制台将打印如下语句。
delete method
这表示在Action中执行的是deleteUser方法。通过这种方式可以在一个Action中设置多个处理逻辑,并通过为表单元素指定不同action属性来提交给Action中不同的方法。
如果一个Action中包含多个处理逻辑,那是不是可以把所有的处理逻辑都放到一个Action中呢?其实不是这样的。一般来说,只有当两个Action中接受的用户参数相同时,才可以考虑将两个Action放到一个Action中,这样可以不用重新创建Action,因此可以节省时间和资源。
4.4.2 为action元素指定method属性
上次通过在“删除”按钮中指定其action属性值为register! deleteUser,从而将表单提交给配置名为regist的Action的deleteUser方法来处理。发现指定action属性值为register! deleteUser这样的方式比较麻烦。如果能够像“注册”按钮那样直接提交给一个register应该会比较好一点。
图4.18 用户注册页
这个时候要借助于“struts.xml”配置文件了。在<action>元素中指定action的method属性,则可以让Action类调用指定的方法,代码如下所示。
<action name="deleteUser" class="net.hncu.action.RegisterAction" method=" deleteUser "> </action>
通过这种方法,就好比将一个Action定义成了多个逻辑上的Action, Action类的每个处理方法被映射成一个逻辑Action。
现在添加一个<action>元素,配置其name属性为“deleteUser”,实现类为“net.hncu. action. RegisterAction”, method属性为“deleteUser”,代码如下所示。
<struts> <package name="struts2" extends="struts-default"> <! -- 定义register的Actin,其实现类为net.hncu.action.RegisterAction--> <action name="register" class="net.hncu.action.RegisterAction"> <! -- 定义处理结果与视图资源之间的关系--> <result name="success">/result.jsp</result> <result name="input">/register.jsp</result> </action> <! -- 定义deleteUser的Action,其实现类为net.hncu.action.RegisterAction,采用 deleteUser方法来处理--> <action name="deleteUser" class="net.hncu.action.RegisterAction" method="deleteUser"> <result name="success">/result.jsp</result> <result name="input">/register.jsp</result> </action> </package> </struts>
这时只要将用户注册页的“删除”按钮中对应的method属性值修改为deleteUser就行了。
那是不是说如果没有指定method属性值,就会调用execute方法呢?答案是肯定的,如果配置了method属性,那么在Action中将调用该method指定的方法。如果没有配置method属性,那么就调用默认的execute()方法。
4.4.3 校验动态方法
前面介绍的在一个Action中包含多个处理逻辑,不同处理逻辑对应不同的方法。那如何定义输入校验来校验这些处理逻辑呢?
下面来看一个简单示例,首先在上一示例的Action中添加一个validate()方法,该方法将在控制台上简单地打印一句话,代码如下所示。
public void validate() { System.out.println("validate method"); }
这里为了简单测试,并不输入任何的用户信息。直接单击“注册”按钮,在控制台中将打印如下语句。
validate method execute method
从控制台打印的语句可以看出,在Action中首先执行了validate()校验方法,然后再执行execute()处理逻辑方法。如果单击“删除”按钮,在控制台中将打印如下语句。
validate method delete method
从控制台打印的语句可以看出,在Action中首先执行了validate()校验方法,然后再执行deleteUser()处理逻辑方法。从上可以看出,不管执行调用哪个处理逻辑,都会执行validate方法。
Sturts 2允许为执行的处理逻辑提供校验方法。通过增加一个validate×××()方法来完成,其中×××对应处理逻辑方法名。下面来为deleteUser()方法添加校验方法,该方法也是在控制台简单的打印一句话,代码如下所示。
public void validateDeleteUser(){ System.out.println("validateDeleteUser method"); }
这时直接单击“删除”按钮,在控制台中将打印如下语句。
validateDeleteUser method validate method delete method
从控制台打印的语句可以看出,在Action中首先执行了对应deleteUser()方法的校验方法,然后再执行了validate()方法,最后再执行处理逻辑deleteUser()方法。
因为不管用户向Action的哪个处理方法发送请求,Action内的validate()方法都会被调用。所以可以将对应处理逻辑的校验代码放到validate×××()方法中,而validate()方法中可以不用添加任何的校验代码。同样可以添加validateExecute()方法来校验默认处理逻辑方法,代码如下所示。
public void validateExecute(){ System.out.println("validateExecute method"); }
这时直接单击“注册”按钮,在控制台中将打印如下语句。
validateExecute method validate method execute method
为了不使校验代码出现混乱,可以将处理逻辑中相同的校验代码放到validate()方法中。不同的校验代码则放到对应的validate×××()方法中。
4.4.4 Struts 2输入校验流程
为了能够更加了解输入校验的流程,下面来看输入校验的程序流程图,如图4.19所示。
图4.19 Sturts 2输入校验流程图
(1)类型转化器负责将用户提交的参数进行类型转换,并将类型转换后的值赋值到Action的相应属性中。
(2)如果类型转换出错的话,Struts 2将自动调用conversionError拦截器将错误提示信息保存到fieldError中。
(3)不管类型转换失败与否都会调用validate×××()方法。
(4)调用Action中的validate()方法。
(5)自动判断fieldError中是否为空,如果为空则表示有错误提示信息。页面跳转到input对应的逻辑视图。如果不为空则表示没有错误提示信息,执行Action中的处理逻辑方法(如execute方法)并进行业务逻辑处理。处理完成后根据处理结果返回值跳转到相应的视图资源。