Struts 学习之02(验证)
上一次简单的做了一个Struts,今天再来进步一点!做一个简单的登录验证程序,不过在这里我们偏向视图部份,也就是看看Struts做视图!在这里面顺便写写一些基本的标签的作用
Step 1: 我们还是一样 首先创建一个工程WebProject! 并添加Struts 1.2,过程完全与 Struts 学习之01 一样
这次我们看看在src/下多了什么!有一个包fengyan.struts ApplicationResources.properties 这是一个属性文件,我们后面会用到!以及在WebRoot/WEB-INF下多了一些.tlb文件,如果对自定义标签熟习的话,那么自然就知道它们是什么了!
Step2: 我们还是打开配置文件struts-config.xml 添加form,action and jsp,在use case中输入Login;
同时添加二个属性 userName,userPwd,并创建一个登录页面Login.jsp.(具体步骤可参看
Struts 学习之01 )
现在我们看看产生的login.jsp页面代码
<%@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean"%>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html"%>
<html>
<head>
<title>JSP for LoginForm form</title>
</head>
<body>
<html:form action="/login">
userName : <html:text property="userName"/><html:errors property="userName"/><br/>
userPwd : <html:password property="userPwd"/><html:errors property="userPwd"/><br/>
<html:submit/><html:cancel/>
</html:form>
</body>
</html>
可看到产生了一些<html:***>之类的标记,这些就都是Struts里面的标签,它也就在刚刚 WebRoot/WEB-INF下产生的一些tld文件中定义了!那么上面这些都是什么意思呢,我们一个个来看;
a: 首先说说<html:form>,这个标记用于生成一个HTML<form>标记,该标记与Action对象,以及 struts-config.xml文件中的相应的formbean相关联,当其内部有其他标记时,对应的frombean用 属性来填充 对应的标记内容(通过struts-config.xml可知本例中其与LoginForm对应) 常见属性:action用来对应struts-config.xml中定义的action的逻辑名 method提交数据的方法 focus指定初始光标对应哪个表单元素
b:而<html:text>则用于产生一个<input type="text"value=""/>标记,此标记的property属性用来查找与 form对应的formbean,并调用对应的property属性指定的字段值来填充此标记的控件内容!本例子中的<html:text property="userName"/>,最后产生的文本框是直接与LoginFrom.java中的userName属 性相对应!而<html:password>就也自然明白了,产生一个密码文本框!
c:<html:errors property="userName"/> 大家看到errors就知道是错误的意思,那么它主要是用来显示一 些错误信息!如果没有property属性则它会显示所有错误信息,而这里则只显示与userName相关的错误信息!
d:最后二个<html:submit><html:reset>用于产生提交表单和重置表单的input标记!
Step3: 好了,上面这些介绍完后,我们现在来做一个简单的验证!我们打开LoginForm.java
import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
public class LoginForm extends ActionForm {
/*
* Author:楚旋 2006-12-22 20:50
*/
private String userName;
private String userPwd;
public ActionErrors validate(ActionMapping mapping,
HttpServletRequest request) {
return null;
}
public void reset(ActionMapping mapping, HttpServletRequest request) {
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserPwd() {
return userPwd;
}
public void setUserPwd(String userPwd) {
this.userPwd = userPwd;
}
}
我们可以看到除了二个属性外,还有二个方法,一个是reset 一个是validate!reset方法我们在Struts 学习之01中已经用过,是用来初始化的!而validate则是用来验证,现在我们主要在它里面写验证的方法!
我们现在在validate方法中写入验证方法 如下:
HttpServletRequest request) {
//添加验证 禁止 用户 fengyan 登录
ActionErrors error = new ActionErrors();
if(userName.equals("fengyan"))
error.add(("userName"),new ActionError("first.validateError"));
//userName与login.jsp中<html:errors property="userName"/>对应
//而first.validateError是在属性文件ApplicationResources.properties中定义
return error;
//如果返回 null 则表明是通过验证
}
public void reset(ActionMapping mapping, HttpServletRequest request) {
//初始化表单bean 用户名和密码均为 fengyan
userName = "fengyan";
userPwd = "fengyan";
}
因为有注释我就不再多解释,现在看看我们在开头提到的一个文件!ApplicationResources.properties 里面内容如下
# Project StrutsStep02
first.validateError="抱歉!用户名fengyan无法通过验证"
可以看到有类似键值对 forst.validateError=“抱歉!用户名fengyan无法通过验证”,现在知道我们在validate方法中使用的 new ActionError("first.validateError")就是与这里的对应了!
一切完成后,我们可以看到效果
说明:之所以我这里可以显示为中文,是因为我使用了一个插件!没有的朋友可以参看 解决Struts中ApplicationResources.properties文件不支持中文问题 一文!另外将login.jsp的 pageEncoding设为"GBK"即OK!
总结:现在我们来用一张图来总结
上图显示出了Struts的运行流程!
上面我们是使用方法来进行验证,下面再提供另外一种较常用的验证方式!
Step1:我们添加一个JSP页面 Template 为 standard JSP using struts1.2 with a form!
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>
<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html:html lang="true">
<head>
<html:base />
<title>login2.jsp</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<html:form action="" method="post" focus="login">
<table border="0">
<tr>
<td>Login:</td>
<td><html:text property="login" /></td>
</tr>
<tr>
<td>Password:</td>
<td><html:password property="password" /></td>
</tr>
<tr>
<td colspan="2" align="center"><html:submit /></td>
</tr>
</table>
</html:form>
</body>
</html:html>
这里面出现了一些新的标记, 首先是<html:html>:此标记是用来生成一个把语言环境设置为当前用户环境的html<html>标记,而且通过设置此标记的属性可以把其他的标记以xhtml或其它非html标记格式输出;如:<html:html xhtml="true">而<html:base>标记是用来通过将href属性设置为成对形式出现的jsp绝对url来生成一个html<base>标记; 注意点,此标记必须嵌套在head标记中,觉形式即为<html:base/>因现在我们要使用另外一种方式验证,所以我们加一个标记<html:javascript>此标记用于为validator框 架的validation.xml中设置的验证方法生成客户端js脚本 我们在这里加后的代码如下
<table border="0">
<tr>
<td>Login:</td>
<td><html:text property="login" /></td>
</tr>
<tr>
<td>Password:</td>
<td><html:password property="password" /></td>
</tr>
<tr>
<td colspan="2" align="center"><html:submit /></td>
</tr>
</table>
</html:form>
<html:javascript formName="loginForm"/>
Step2: 为form增加action后,我们打开struts-config.xml 新加一个formBean.切换到视图。选择 form-beans 右键-->add new form 我们创建动态的FormBean选择 Dynamic FormBean, 为了使其带有验证功能,我们在Dynamic Type中选择org.apache.struts.validator.DynaValidatorForm use case中输入名字userLogin,最后同样为其添加二个属性,userName and userPwd 因为前面已经创建了login2.jsp所以这里就不创建了!我们看下其源码
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" "http://struts.apache.org/dtds/struts-config_1_2.dtd">
<struts-config>
<data-sources />
<form-beans >
<form-bean name="loginForm" type="fengyan.struts.form.LoginForm" />
<form-bean name="userLoginForm" type="org.apache.struts.validator.DynaValidatorForm">
<form-property name="userName" type="java.lang.String" />
<form-property name="userPwd" type="java.lang.String" />
</form-bean>
</form-beans>
<global-exceptions />
<global-forwards />
<action-mappings >
<action
attribute="loginForm"
input="/login.jsp"
name="loginForm"
path="/login"
scope="request"
type="fengyan.struts.action.LoginAction" />
</action-mappings>
<message-resources parameter="fengyan.struts.ApplicationResources" />
</struts-config>
我们看到多了如下内容
<form-property name="userName" type="java.lang.String" />
<form-property name="userPwd" type="java.lang.String" />
</form-bean>
而这时我们去src下面却并没有发现生成了userLoginForm.java这个类!我们前面的方法是有一个实际 的javabean存在,而现在这个并没有实际的javabean存在,所以这个就是动态FormBean的与其差别, 因为它实际并不存在,所以它的属性呢自然也就在我们的struts-config.xml配置文件中指定,也就是为什么多了如下内容
<form-property name="userPwd" type="java.lang.String" />
指定了动态formbean的属性!那么如何将这个动态的formbean与我们前面创建的login2.jsp相关联起来 呢?接着看!
Step3:我们回到struts-config.xml视图 选择action-mapping 右键 new ->new Action 在Action Impl中我们选择 Create new Action class ,在下面Optional Details 中我们单击Browse...在弹出的对话框中我们选择刚刚创建的动态userLoginForm如下图:
我们可以在src/fengyan.struts.action中发现多了一个UserLoginAction.java类,而并没有相应的FormBean.
Step4:我们在struts-config.xml文件中增加一个input输入元素input="login2.jsp".然后让它拥有强制验证增加 validate="true" 设为真!这个时候有朋友可能会想到,既然是动态的FormBean那么不是实际存在 那从哪里来的validate方法呢!就像我们前面的一种验证方法,而前面的一种方法并不推荐的!因为当有很多数据的时候,我们要写很多方法进行验证!那么我们现在就来使用一种简便的!
Step5:我们将光标移到</action-mapping>后面,file-->new-->other,我们创建一个Struts1.2 Plugin如下图
在接着的窗口中我们选择Plugin class 为 ValidatorPlugIn,我们将验证功能交给它来做!
在set properties中 我们添加一个pathnames 其value暂时为空,如下图
Step6:接着我们在WEB-INF中 新建立一XML文件如下:
单击下一步: 我们通过一个DTD来创建,下一步:名字为validation.xml 下一步我们选择一个
xml DTD的脚本如下图:
最后 单击下一步,完成即可!
Step7: 然后我们在这个新建立的validtion.xml中写验证 代码如下:
<!DOCTYPE form-validation PUBLIC "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.1.3//EN" "validator_1_1_3.dtd" >
<form-validation>
<formset>
<form name="userLoginForm">
<field property="userName" depends="required,mask">
<arg key="validateParam.userName"/>
<var>
<var-name>mask</var-name>
<var-value>^[a-zA-Z]*$</var-value>
</var>
</field>
</form>
</formset>
</form-validation>
在上面我们指定了一个表单userLoginForm,以及指定对userName属性进行验证!然后验证的方法是怎样的呢?在这里我们先验证required (必须),后验证 mask(掩码) ,这些都是在validator-rules.xml中写明的,其里面还有 一些常用的其他验证,如最大长度,最小长度,有兴趣的可以自己看看!那么验证的规则是怎样的呢?我们可以在validator-rules.xml中找到required,mask对应的的msg信息分别为errors.required以及errors.invalid,这个时候我们就又需要在资源文件中这加入这样的键值对!
在 ApplicationResources.properties 加入如下:
# Project StrutsStep02
validateParam.userName=用户名
first.validateError="抱歉!用户名fengyan无法通过验证"
errors.required={0}为必须填写
errors.invalid={0}必须为字母
可以看到我们对应的加入了这样的二个键值对!{0}为占位符!表第一个参数,而参数我们在开头的 第一行 ,也即为 validateParam.userName=用户名。这些只是信息,至于具体的验证方法,我们还是先 回到validation.xml文件,
<!DOCTYPE form-validation PUBLIC "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.1.3//EN" "validator_1_1_3.dtd" >
<form-validation>
<formset>
<form name="userLoginForm">
<field property="userName" depends="required,mask">
<arg key="validateParam.userName"/>
<var>
<var-name>mask</var-name>
<var-value>^[a-zA-Z]*$</var-value>
</var>
</field>
</form>
</formset>
</form-validation>
继续在<fired>节点中添加第一个参数 validateParam.userName,也就是刚刚我们在资源文件中添加的参数 键值对,接下来是掩码使用什么方式,我们添加一个变量var 名字为mask,值(也即为排码的类型)为^[a-zA-Z]*$,熟习的朋友一 眼即可看出这是正则表达式了!OK,这步完成,我们将这些验证规则的配置文件在
struts-config.xml中注册!最后的struts-config.xml文件代码如下
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" "http://struts.apache.org/dtds/struts-config_1_2.dtd">
<struts-config>
<data-sources />
<form-beans >
<form-bean name="loginForm" type="fengyan.struts.form.LoginForm" />
<form-bean name="userLoginForm" type="org.apache.struts.validator.DynaValidatorForm">
<form-property name="userName" type="java.lang.String" />
<form-property name="userPwd" type="java.lang.String" />
</form-bean>
</form-beans>
<global-exceptions />
<global-forwards />
<action-mappings >
<action
attribute="loginForm"
input="/login.jsp"
name="loginForm"
path="/login"
scope="request"
type="fengyan.struts.action.LoginAction" />
<action
attribute="userLoginForm"
input="login2.jsp"
name="userLoginForm"
path="/userLogin"
scope="request"
validate="true"
type="fengyan.struts.action.UserLoginAction" />
</action-mappings>
<message-resources parameter="fengyan.struts.ApplicationResources" />
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property property="pathnames" value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml" />
</plug-in>
</struts-config>
也就是我们刚才添加的一个struts1.2 ValidatorPlugIn插件 我们添加了一个属性pathnames,当时没写值, 现在就将其值补上也就是我们的验证规则xml文件的地址!
Step8: 大功告成,最后我们修改一下先前的login2.jsp文件,加入表单的action 以及onsubmit,另外加入<html:errors/>标记~和一个<html:javascript>标记用于产生 JS脚本!完整代码如下!
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>
<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html:html lang="true">
<head>
<html:base />
<title>login2.jsp</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<html:form action="/userLogin" method="post" focus="login" onsubmit="return validateUserLoginForm(this)">
<table border="0">
<tr>
<td>Login:</td>
<td><html:text property="userName" /></td><html:errors property="userName"/>
</tr>
<tr>
<td>Password:</td>
<td><html:password property="userPwd" /></td>
</tr>
<tr>
<td colspan="2" align="center"><html:submit /></td>
</tr>
</table>
</html:form>
<html:javascript formName="userLoginForm"/>
</body>
</html:html>
运行效果如下:
其实到最后我们看到,第二种方式的验证其实就是用javascript脚本来验证!
说句实话做到现在已经搞了好大半天了,就想到了微软的ASP.NET,里面的validatorControls真是太方便了,哪儿还用我们这上面的那么多步骤啊,直接拉来用就OK,哎~感叹~ING~~~