struts1(5)----表单校验与回显

在struts中,当用户在action表中中配置了validate属性为true时(默认为true), struts在用户提交的数据封装到ActionForm中后(这个Form会存到action标签的scope属性所指定的容器中,名称为form-bean标签中指定的name属性名)会自动对这些数据进行校验,负责这部分操作的函数是

ActionErrors validate(ActionMapping mapping, HttpServletRequest request) ,

此函数返回一个ActionErrors对象,当这个对象为空时,说明校验成功,要是这个对象不为空,则说明校验失败。开发者可以在这个function中天剑相应的校验代码,ActionErrors封装了相关错误属性的错误信息。要是校验失败,则会返回到Input指定的页面,否则会调用ActionServlet查找到的对应Action进行下一步操作。

在Struts中,对表单数据校验时,对错误信息的显示是可以通过errors标签来回显:回显方式如下

<html:errors property="xxx" />

proterty是指定对应表单相关属性的错误信息。其原理是当检验遇到有些不合格的信息时,将会创建一个ActionErrors的对象,并将此错误信息封装到其中,而这个ActionErrors将被添加到pageContex域中,之后在显示错误信息时,会从此域中获取此ActionErrors对象,并从中解析出对应属性的错误信息。

只的注意的是,ActionServlet在用用户提交的数据填充UserFormBean对象前(即调用bean相关set方法),会先调用actionForm的reset方法,因此可以用此方法来清空对应的FormBean对象。

下面是手动编写的一个UserFormBean

userFormBean

package cn.itcast.web.formbean;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;


import org.apache.commons.beanutils.locale.converters.DateLocaleConverter;
import cn.itcast.global.Gender;
import cn.itcast.global.Interest;

public class UserFormBean extends ActionForm {
	private String username;
	private String password;
	private String password2; 
	private String gender; //request上传过来的所有参数类型都将是String类型
	private String emails;
	private String birthday;
	private String[] interest;//爱好,对应可以选择多种,request上传过来的是一个数组
	private String city;
	
	public String getCity() {
		return city;
	}
	public void setCity(String city) {
		this.city = city;
	}
	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 getPassword2() {
		return password2;
	}
	public void setPassword2(String password2) {
		this.password2 = password2;
	}
	public String getGender() {
		return gender;
	}
	public void setGender(String gender) {
		this.gender = gender;
	}
	public String getEmails() {
		return emails;
	}
	public void setEmails(String emails) {
		this.emails = emails;
	}
	public String getBirthday() {
		return birthday;
	}
	public void setBirthday(String birthday) {
		this.birthday = birthday;
	}
	
	public String[] getInterest() {
		return interest;
	}
	public void setInterest(String[] interest) {
		this.interest = interest;
	}
	@Override
	public ActionErrors validate(ActionMapping mapping,
			HttpServletRequest request) {
		// TODO Auto-generated method stub
		ActionErrors ae = new ActionErrors();
		
		if(isEmpty(this.username)){
			addErrorMessage(ae, "username", "用户名不能为空");
		}else if(!this.username.matches("[a-zA-Z]{3,9}")){
			//3-8位字母
			addErrorMessage(ae, "username", "用户名需要为3-8为字母");
		}
		
		if(isEmpty(this.password)){
			addErrorMessage(ae, "password", "密码不能为空");
		}
		
		if(isEmpty(this.password2) || !this.password2.equals(this.password)){
			addErrorMessage(ae, "password2", "密码两次输入不一致");
		}
		
		if(isEmpty(this.gender)){
			addErrorMessage(ae, "gender", "性别不能为空,请选择性别");
		}else{
			try{
				//判断一个枚举是否有效,可以通过将此值强转成此枚举型,要是不是会暴异常
				Gender.valueOf(this.gender.toUpperCase());
			}catch(Exception e){
				addErrorMessage(ae, "gender", "请选择有效的性别");
			}
		}
		if(isEmpty(this.emails)){
			addErrorMessage(ae, "emails", "邮箱不能为空");
		}else{
			if(!this.emails.matches("\\w+@\\w+(\\.+\\w+)+")){
				addErrorMessage(ae, "emails", "邮箱格式不对");
			}
		}
		if(isEmpty(this.birthday)){
			addErrorMessage(ae, "birthday", "生日不能为空");
		}else{
			try{
				DateLocaleConverter convert = new DateLocaleConverter();//通过此转化器,将字符串形式的日期YYYY-MM-DD转化成Date,要是格式不对,会暴异常
				convert.convert(this.birthday);
			}catch(Exception e){
				addErrorMessage(ae, "birthday", "生日格式无效");
			}
		}
		
		if(interest==null || interest.length==0){
			addErrorMessage(ae, "interest", "请选择您所感兴趣的东西");
		}else{
			for(String in : interest){
				try{
					Interest.valueOf(in.toUpperCase());
				}catch(Exception e){
					addErrorMessage(ae, "interest", "请选择您所感兴趣的东西");
				}
			}
		}
		
		if(isEmpty(this.city)){
			addErrorMessage(ae, "city", "请选择您所感兴趣的东西");
		}
		return ae;
	}
	
	private boolean isEmpty(String value){
		if(value==null || value.trim().equals("")){
			return true;
		}
		return false;
	}
	
	private void addErrorMessage(ActionErrors ae, String key, String message){
		ActionMessage am = new ActionMessage(message, false);
		ae.add(key, am);
	}
}

Register.jsp 是注册显示页面,此页面涉及到数据回显等内容。数据回显包含两部分,一部分是提交校验单本身输入的内容回显,可以利用UserFormBean对象(它是由ActionServlet创建的ActionForm对象,封装了用户提交的数据,并存在action标签的scop属性指定的域中)来进行回显。另一部分是校验的错误提示信息回显,此部分内容可以由<html:errors>标签来完成。

<%@page import="cn.itcast.global.Interest"%>
<%@page import="cn.itcast.global.Location"%>
<%@page import="cn.itcast.global.Gender"%>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
   <title>注册页面</title>

  </head>
  
  <body>
    <form action="${pageContext.request.contextPath }/Register.do" method="post">
    	用户名: <input type="text" value="${UserFormBean.username }" name="username" />
    		<html:errors property="username" /> <br />
    		
    	密码:  <input type="password" name="password" />
    		<html:errors property="password" /><br />
    		
    	确认密码: <input type="password" name="password2" />
    		<html:errors property="password2" /><br />
    		
    	性别: <c:forEach var="g" items="<%=Gender.values() %>">
    				<input type="radio" name="gender" value="${g.name }"
    					${UserFormBean.gender==g.name?'checked':'' }/>${g.value }
    		</c:forEach>
    		<html:errors property="gender" /> <br />
    		
    	邮箱: <input type="text" name="emails" value="${UserFormBean.emails }" />
    		<html:errors property="emails" /> <br />
    		
    	生日: <input type="text" name="birthday" value="${UserFormBean.birthday }"/>
    		<html:errors property="birthday" /><br />
    		
    	爱好:<c:forEach var="int" items="<%=Interest.values() %>">
    			<input type="checkbox" name="interest" value=${int.name } 
    				${fn:contains(fn:join(UserFormBean.interest, ","), int.name)?'checked':''}/>${int.value }
    		</c:forEach> 
    		<html:errors property="interest" /><br />
    		
    	居住城市: <select name="city" >
    				<option value=" " selected="selected">请选择居住城市</option>
    				<c:forEach var="c" items="<%=Location.values() %>">
    					<option  value="${c.name }" ${UserFormBean.city==c.name?'selected':''}>
    						${c.value }
    					</option>
    				</c:forEach>
    			</select>
    		<html:errors property="city" /><br />	
    	<input type="submit" value="注册" />
    </form>
  </body>
</html>
  这个jsp页面在显示性别及爱好时,采用了一些相对较好的方法。它没有将jsp中相关爱好写死,而是通过配置相关文件(这里是枚举类)来填写相关爱好,这样就可以保证当爱好发生变化时,jsp页面无需修改。如上代码,通过枚举类的values()方法可以获取到这个类的所有枚举值,枚举也是一个类,下面是定义的几个类:

package cn.itcast.global;

public enum Gender {
	MALE("male", "男"), FEMALE("female", "女");
	
	private String name;
	private String value;
	
	private Gender(String name, String value){
		this.name = name;
		this.value = value;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getValue() {
		return value;
	}

	public void setValue(String value) {
		this.value = value;
	}
	
}

package cn.itcast.global;

public enum Interest {
	SING("sing", "唱歌"),
	DANCE("dance", "跳舞"),
	BASKBALL("baskball", "篮球"),
	FOOTBALL("football", "足球");
	
	private String name;
	private String value;
	
	private Interest(String name, String value){
		this.name = name;
		this.value = value;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getValue() {
		return value;
	}

	public void setValue(String value) {
		this.value = value;
	}
}

package cn.itcast.global;

public enum Location {
	BEIJING("beijing", "北京"),
	GUANZHOU("guangzhou", "广州"),
	SHANGHAI("shanghai", "上海"),
	SHENZHENG("shenzheng", "深圳");
	
	private String name;
	private String value;
	
	private Location(String name, String value){
		this.name = name;
		this.value = value;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getValue() {
		return value;
	}

	public void setValue(String value) {
		this.value = value;
	}
	
	
}

对于jsp显示页面中的表单标签,struts框架也提供了一个Form标签,如:<html:form>,使用此标签相对于html标签来说有一下几点好处:

   1.不用编写${pageContext.request.contextPath}来指定context路径

  2.指定的action不用带".do"后缀

此标签会生成一个html的form标签代码,同时也会将UserFormBean对象以key值org.apache.struts.taglib.html.BEAN存到pageContext域中,这样在表单数据回显时,会从此表单中提取对应属性的值。

          针对上面使用scriptlet标签来回显表单数据,struts提供了相关标签:

<html:text property="xx" />  ------> <input type="text" name="xxx" />

<html:password property="xxx" /> ----><input type="password" name="xxx"/>

<html:radio>

<html:checkbox>

<html:mul

<html:select property="xxx" />  -----> <select name="xxx" >

<html:textarea property="xxx" />  -----> <textarea name="xxx" >

等标签,这些标签功能除了相当于scriptlet对应标签功能外,还具有回显相关数据功能。

因此上面jsp代码,可以用下面的代码替换:

<%@page import="cn.itcast.global.Interest"%>
<%@page import="cn.itcast.global.Location"%>
<%@page import="cn.itcast.global.Gender"%>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
   <title>注册页面</title>

  </head>
  
  <body>
    <html:form action="/Register" >
    	用户名: <html:text property="username" />
   			<html:errors property="username" /> <br />
    		
    	密码:  <html:password property="password" redisplay="false"/>
    		<html:errors property="password" /><br />
    		
    	确认密码: <html:password property="password2" redisplay="false"/>
    		<html:errors property="password2" /><br />
    		
    	性别: <c:forEach var="g" items="<%=Gender.values() %>">
    				<html:radio property="gender" value="${g.name }" />${g.value }
    		</c:forEach>
    		<html:errors property="gender" /> <br />
    		
    	邮箱: <html:text property="emails" />
    		<html:errors property="emails" /> <br />
    		
    	生日: <html:text property="birthday"/>
    		<html:errors property="birthday" /><br />
    		
    	爱好:<c:forEach var="int" items="<%=Interest.values() %>">
    			<html:multibox property="interest" value="${int.name }" />${int.value }
    		</c:forEach> 
    		<html:errors property="interest" /><br />
    		
    	居住城市: <html:select property="city" >
    				<html:option value=" ">请选择居住城市</html:option>
    				<c:forEach var="c" items="<%=Location.values() %>">
    					<html:option  value="${c.name }">${c.value }</html:option>
    				</c:forEach>
    			</html:select>
    		<html:errors property="city" /><br />	
    	<html:submit value="注册" /><html:reset value="清空" />
    </html:form>
  </body>
</html>




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值