今天主要做的事情是理解代码是如何执行的,因此只记录我的理解过程,深入的扩展的底层的知识不涉及
输入jsp代码:
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<s:actionerror cssStyle="color:red"/>
-------------------------------------
<s:fielderror cssStyle="color:blue"></s:fielderror>
<s:form action="registerAction.action" method="post">
<s:textfield name="user.username" label="用户名"></s:textfield>
<s:password name="user.password" label="密码"></s:password>
<s:textfield name="user.age" label="年龄"></s:textfield>
<s:submit value="注册"></s:submit>
</s:form>
</body>
</html>
输出jsp代码:
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<s:property value="user.username"/>
<s:property value="user.password"/>
<s:property value="user.age"/>
</body>
</html>
struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<package name="default" namespace="/" extends="struts-default">
<action name="registerAction" class="com.oracle.action.RegisterAction" method="myExecute">
<result name="success">
/result.jsp
</result>
<result name="input">
/register.jsp
</result>
</action>
</package>
</struts>
bean:
package com.oracle.bean;
public class User {
private String username;
private String password;
private int age;
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 int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
action类:
package com.oracle.action;
import com.opensymphony.xwork2.ActionSupport;
import com.oracle.bean.User;
public class RegisterAction extends ActionSupport{
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public String execute() throws Exception {
System.out.println("execute()方法执行了");
return SUCCESS;
}
public String myExecute() throws Exception {
System.out.println("myExecute()方法执行了");
return SUCCESS;
}
@Override
public void validate() {
System.out.println("validate()方法执行了");
}
public void validateMyExecute() {
System.out.println("validateMyExecute()方法执行了");
if(user.getUsername() == null || !user.getUsername().equals("aa")){
System.out.println("用户名错误");
this.addActionError("用户名错误");
this.addFieldError("username", "用户名为空或错误");
}
if(user.getPassword() == null || !user.getPassword().equals("aa")){
System.out.println("密码错误");
this.addActionError("密码错误");
this.addFieldError("password", "密码为空或错误");
}
if(user.getAge()<20 || user.getAge()>50){
System.out.println("年龄错误");
this.addActionError("年龄错误");
this.addFieldError("age", "年龄为空或错误");
}
// this.getActionErrors().clear();
// this.getFieldErrors().clear();
// this.clearActionErrors();
// this.clearFieldErrors();
}
}
个人理解和笔记:
1.在register.jsp的文本框中输入用户名和密码,name是属性名,label会在输入框前格式化生成
2.通过struts.xml的action找到类和方法
3.首先进行类型转换,根据属性名在action类中的调用set方法对user对象及其属性赋值
4.进行输入校验,首先会执行对应自定义的myExecute方法的验证方法validateMyExecute()方法
5.执行validate()方法
6.执行完所有的验证方法后,如果添加了error并且没有clear,则不会执行任何execute方法,会转向struts.xml中该action的名为input的result所对应的页面
7.执行自定义的myExecute()方法,不再执行execute()方法
8.在result.jsp中,会获取action值栈中的值
ps:
ActionSupport类的addActionError()方法的实现:首先创建一个ArrayList对象,然后将错误消息添加到该ArrayList对象中。
当调用getActionErrors()方法返回Action级别的错误信息列表时,返回的实际上是集合的一个副本而不是集合本身,因此对集合副本调用clear()方法清除的依旧是副本中的元素而非原集合中的元素,此时原集合中的内容没有收到任何的影响。换句话说,Action级别的错误信息列表对开发者来说是只读的。
在这里如果使用this.getActionErrors().clear();错误信息仍然会显示,不会被清除;如果使用this.clearActionErrors();会清除错误信息,从而执行execute方法
====================================================================================================================================
接下来使用xml的验证
对输入jsp做一些修改,添加一个确认密码项
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<s:fielderror cssStyle="color:blue"></s:fielderror>
====================================================
<s:form action="registerAction.action" method="post">
<s:textfield name="user.username" label="用户名"></s:textfield>
<s:password name="user.password" label="密码"></s:password>
<s:password name="user.repassword" label="确认密码"></s:password>
<s:textfield name="user.age" label="年龄"></s:textfield>
<s:submit value="提交"></s:submit>
</s:form>
</body>
</html>
在bean中添加repassword属性
使用RegisterAction-validation.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator 1.0.3//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
<!-- 验证用户名 -->
<field name="user.username">
<field-validator type="requiredstring">
<message>用户名不能为空</message>
</field-validator>
<field-validator type="stringlength">
<param name="minLength">2</param>
<param name="maxLength">6</param>
<message>用户名长度必须在${minLength}和${maxLength}之间</message>
</field-validator>
</field>
<!-- 验证密码 -->
<field name="user.password">
<field-validator type="requiredstring">
<message>密码不能为空</message>
</field-validator>
</field>
<!-- 验证重复密码 -->
<field name="user.repassword">
<field-validator type="requiredstring">
<message>重复密码不能为空</message>
</field-validator>
<field-validator type="fieldexpression">
<param name="expression"><![CDATA[user.password==user.repassword]]></param>
<message>两次输入的密码不相同</message>
</field-validator>
</field>
<!-- 验证年龄 -->
<field name="user.age">
<field-validator type="required">
<message>年龄不能为空</message>
</field-validator>
<field-validator type="int">
<param name="min">10</param>
<param name="max">40</param>
<message>年龄必须在${min}和${max}之间</message>
</field-validator>
</field>
<!--
field-validator type="" 中可填入的类型
int 整数;
double 实数;
date 日期;
expression 两数的关系比较;
fieldexpression
email Email地址;
url
visitor
conversion
regex 正则表达式验证;
required 是否为空;
requiredstring 必须字符;
stringlength 输入字符长度限制;
-->
</validators>
在这里使用的是field error, Field Error级别的错误信息底层是用LinkedHashMap实现的,该Map的key是String类型,value是List<String>类型,这就表示一个Field Name可以对应多条错误信息,这些错误信息都放置在List<String>集合当中。
另外,我们还可以自定义field级别的错误消息,我将对上面的RegisterAction-validation.xml做一点简单的修改
1.首先新建一个以action名命名的properties文件,在这里是RegisterAction.properties
2.为该属性文件中以key=value的方式指定每一个出错字段的错误信息,在这里只举一个简单的例子,例如:
invalid.fieldvalue.user.username=用户名不能为空!
3.稍微修改一下上面的xml代码,将第11行
<message>用户名不能为空</message>
修改为
<message key="invalid.fieldvalue.user.username"></message>
如此即可
在这里,再提一下struts2框架校验执行的先后顺序:
1)首先执行校验框架xml文件
2)执行自定义的校验方法,例如之前的validateMyExecute
3)执行validate方法