第十三部分_XWork对输入校验的支持,类型转换与输入校验总结

当我们使用Struts2表单时,它是一种增强型的表单,自带了错误信息输出的功能,不需要指定它的fielderror等其他的信息,并且其错误信息出现在对应输入框的上面。

如下实例:

首先,login2.jsp:

<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>
<%@ taglib uri="/struts-tags" prefix="s" %><%--pay attention to uri --%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'login2.jsp' starting page</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>
   	<s:form action="login.action" method="Get">
   		<s:textfield name="username" label="username"></s:textfield>r<br/>
   		<s:password name="password" label="password"></s:password>
   		<s:submit value="submit"></s:submit>
   	</s:form>
  </body>
</html>

然后是LoginAction.java:

package com.test.action;

import com.opensymphony.xwork2.ActionSupport;

public class LoginAction extends ActionSupport
{
	private String username;
	
	private String password;

	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 execute() throws Exception
	{
		return "success";
	}
	
	@Override
	public void validate()
	{
		if(null == username || -1 != username.indexOf(("hello")))
		{
			this.addFieldError("username", "username invalid");
		}
		
		if(null == password || password.length() < 4)
		{
			this.addFieldError("password", "password invalid");
		}
	}
}

struts.xml文件相关部分配置如下:

<action name="login" class="com.test.action.LoginAction">
				<result name="success">/result.jsp</result>
				<result name="input">/login2.jsp</result>
			</action>

一个输出样例:

下面给出利用校验框架进行校验的实例:

register.jsp如下:

<%@ page language="java" import="java.util.*" pageEncoding="GBK"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'register.jsp' starting page</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>
  
  	<table align="center" width="40%" border="0">
    		<tr>
    			<td> 
    				 <s:actionerror cssStyle="color:red"/><%--actionerror中增加的所有信息显示到页面上 --%> 
    				 __________________________________________________
    				 <s:fielderror cssStyle="color:blue"></s:fielderror>
    			</td>
    		</tr>
    </table>
   
    <form action="register.action" method="post">
    
    	<table align="center" width="40%" border=1">
    		<tr>
    			<td> 
    				username: 
    			</td>
    				
    			<td>
    				<input type="text" name="username" size="20">
    			</td>
    		</tr>
    		
    		
    		<tr>
    			<td>
    				password:
    			</td>
    				
    			<td>
    				<input type="password" name="password" size="20">
    			</td>
    		</tr>
    		
    		
    		<tr>
    			<td>
    				re-password:
    			</td>
    				
    			<td>
    				<input type="password" name="repassword" size="20">
    			</td>
    		</tr>
    	
    	
    		<tr>
    			<td>
    				age:
    			</td>
    				
    			<td>
    				<input type="text" name="age" size="20">
    			</td>
    		</tr>
    	
    	
    		<tr>
    			<td>
    				birthday:
    			</td>
    				
    			<td>
    				<input type="text" name="birthday" size="20">
    			</td>
    		</tr>
    		
    		
    		<tr>
    			<td>
    				graduation:
    			</td>
    				
    			<td>
    				<input type="text" name="graduation" size="20">
    			</td>
    		</tr>
    		
    		<tr>
    			<td>
    				<input type="submit" value="submit"/>
    			</td>
    				
    			<td>
    				<input type="reset" value="reset"/>
    			</td>
    		</tr>
    	</table>

    
    </form>
    

    
  </body>
</html>

RegisterAction.java如下:

package com.test.action;

import java.util.Calendar;
import java.util.Date;

import com.opensymphony.xwork2.ActionSupport;

public class RegisterAction extends ActionSupport
{
	private String username;
	
	private String password;
	
	private String repassword;
	
	private int age;
	
	private Date birthday;
	
	private Date graduation;

	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 getBirthday()
	{
		return birthday;
	}

	public void setBirthday(Date birthday)
	{
		this.birthday = birthday;
	}

	public Date getGraduation()
	{
		return graduation;
	}

	public void setGraduation(Date graduation)
	{
		this.graduation = graduation;
	}

	@Override
	public String execute() throws Exception
	{
		System.out.println("execute invoked");
		return SUCCESS;
	}	
}

success.jsp如下:

<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'success.jsp' starting page</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>
    
    <table align="center" width="40%" border=1">
    		<tr>
    			<td>
    				username:
    			</td>
    				
    			<td>
    				${requestScope.username }
    			</td>
    		</tr>
    		
    		
    		<tr>
    			<td>
    				password:
    			</td>
    				
    			<td>
    				${requestScope.password }
    			</td>
    		</tr>
    
    		<tr>
    			<td>
    				age:
    			</td>
    				
    			<td>
    				${requestScope.age }
    			</td>
    		</tr>
    	
    	
    		<tr>
    			<td>
    				birthday:
    			</td>
    				
    			<td>
    				${requestScope.birthday }
    			</td>
    		</tr>
    		
    		
    		<tr>
    			<td>
    				graduation:
    			</td>
    				
    			<td>
    				${requestScope.graduation }
    			</td>
    		</tr>
    	</table>
 
    
  </body>
</html>

struts.xml如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">
	
	<struts>
		
		<package name="struts2" extends="struts-default">
		
			<action name="helloworld" class="com.test.action.HelloWorld">
				<result name="success">/helloworld.jsp</result>
			</action>
			
			<action name="login" class="com.test.action.LoginAction">
				<result name="success">/result.jsp</result>
				<result name="input">/login2.jsp</result>
			</action>
			
			<action name="converterAction" class="com.test.action.PointAction" method="test">
				<result name="success">/output.jsp</result>
			</action>
			
			<action name="register" class="com.test.action.RegisterAction">
				<result name="success">/success.jsp</result>
				<result name="input">/register.jsp</result>
			</action>
		</package>
	
	
	</struts>

下面就是重头戏了,在和RegisterAction同包目录下建立RegisterAction-validation.xml文件,文件内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC 
  		"-//OpenSymphony Group//XWork Validator 1.0.2//EN" 
  		"http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
  		
<validators>
	
	<field name="username">
	
		<field-validator type="requiredstring">
			<param name="trim">true</param>
			<message>username invalid</message>
		</field-validator>
	
		<field-validator type="stringlength">
			<param name="minLength">6</param>
			<param name="maxLength">10</param>
			<message>useranme should be between ${minLength} and ${maxLength}</message>
		</field-validator>
	
	</field>
	
	
	<field name="password">
	
		<field-validator type="requiredstring">
			<param name="trim">true</param>
			<message>password invalid</message>
		</field-validator>
	
		<field-validator type="stringlength">
			<param name="minLength">6</param>
			<param name="maxLength">10</param>
			<message>password should be between ${minLength} and ${maxLength}</message>
		</field-validator>
	
	</field>
	
	
	
	<field name="repassword">
	
		<field-validator type="requiredstring">
			<param name="trim">true</param>
			<message>repassword invalid</message>
		</field-validator>
	
		<field-validator type="stringlength">
			<param name="minLength">6</param>
			<param name="maxLength">10</param>
			<message>repassword should be between ${minLength} and ${maxLength}</message>
		</field-validator>
	
	</field>
	
	
	
	<field name="age">
	
		<field-validator type="required">
			<message>age invalid</message>
		</field-validator>
	
		<field-validator type="int">
			<param name="min">1</param>
			<param name="max">150</param>
			<message>age should be between ${min} and ${max}</message>
		</field-validator>
	
	</field>
	
	
	
	<field name="birthday">
	
		<field-validator type="required">
			<message>birthday invalid</message>
		</field-validator>
	
		<field-validator type="date">
			<param name="min">2000-01-10</param>
			<param name="max">2003-11-11</param>
			<message>birthday should be between ${min} and ${max}</message>
		</field-validator>
	
	</field>
	
	
	
	
	<field name="graduation">
	
		<field-validator type="required">
			<message>graduation invalid</message>
		</field-validator>
	
		<field-validator type="int">
			<param name="min">2005-01-10</param>
			<param name="max">2008-11-11</param>
			<message>graduation should be between ${min} and ${max}</message>
		</field-validator>
	
	</field>

</validators>

注意的一点是这里的field-validator的type有"requiredstring"、"stringlength",param的name有minLength、trim、max等,我们是如何知道这些的呢?答案是:找到xwork-2.1.2.jar下的包com.opensymphony.xwork2.validator.validators,里面有一个配置文件叫做default.xml,打开看看你就明白了:

根据这里的name就是我们校验的type,在该包下面找到对应的处理类,查看其get和set方法,我们就可以获悉param中的name的取值有哪些(getX,setX的后缀部分,因为这里利用的是反射的机制进行处理,因此处理类的属性可以和name的取值不同,但是方法名的后缀一定要相同)。

此外,还有一种方式是校验器优先,他不同与我们上面的属性优先的方式:

<!--校验器优先校验规则 -->

	<validator type="requiredstring">
		<param name="fieldName">username</param>
		<message>username invalid</message>	
	</validator>
	
	<validator type="stringlength">
		<param name="fieldName">username</param>
		<param name="minLength">6</param>
		<param name="maxLength">10</param>
		<message>username should be between ${minLength} and ${maxLength}</message>	
	</validator>

两者采用哪种方式均可,没有孰优孰劣之分。

还有一种无所谓优劣之分的Action的实现方式:我们上面的使用的一直是一种叫做属性驱动Action的东东,其实还有一种模型驱动Action,他在属性值比较多的时候很有用,比如我们可以写一个RegisterAction2.java来代替RegisterAction.java(需要实现ModelDriven<T>这个泛型接口,并且实现其中的方法getModel()):

package com.test.action;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.test.bean.User;

public class RegisterAction2 extends ActionSupport implements ModelDriven<User>
{
	private User user = new User();
	
	public User getModel()
	{
		return user;
	}
	
	@Override
	public String execute() throws Exception
	{
		return SUCCESS;
	}
}

然后,在com.test.bean中建立User.java:

package com.test.bean;

import java.util.Date;

public class User
{
private String username;
	
	private String password;
	
	private String repassword;
	
	private int age;
	
	private Date birthday;
	
	private Date graduation;

	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 getBirthday()
	{
		return birthday;
	}

	public void setBirthday(Date birthday)
	{
		this.birthday = birthday;
	}

	public Date getGraduation()
	{
		return graduation;
	}

	public void setGraduation(Date graduation)
	{
		this.graduation = graduation;
	}
}

多提一点:为了防止并发带来的问题,与Servlet不同的是Action对象是多实例的,一个请求对应一个Action对象。

还有一个问题,就是基于用户界面友好性的要求,用户输入的信息应该保存起来,即让用户知道哪里错了,又让用户能在原有的基础上进行修改,如何做到这一点呢?可以利用struts2标签库:不仅内置了错误信息输出功能,而且有一个保留输入的提交信息这样的功能(当然处于安全性的考虑,密码没有保留)。因此对register.jsp做出如下修改即可:

<body>
  	<s:form action="register">
  		<s:textfield name="username" label="username"></s:textfield>
  		<s:password name="password" label="password"></s:password>
  		<s:password name="repassword" label="repassword"></s:password>
  		<s:textfield name="age" label="age"></s:textfield>
  		<s:textfield name="birthday" label="birthday"></s:textfield>
  		<s:textfield name="graduation" label="graduation"></s:textfield>
  		
  		<s:submit value="submit"></s:submit>
  	</s:form>
  </body>

当然,前提是要引入标签库:<%@ taglib uri="/struts-tags" prefix="s" %> 

最后,如果即使用编码的方式进行校验,同时又用校验框架进行校验,结果会如何?校验流程如下:

  1. 首先执行类型转换
  2. 执行对应的校验框架(XML)
  3. 执行特定方法对应的validate验证(test,validateTest)
  4. 执行validate()方法

如果在以上所有过程当中,发现了任何错误,都不再去执行execute方法或指定的特定方法(test),页面转向了struts.xml中input这个result所对应的页面。

原文地址:https://www.cnblogs.com/Code-Rush/p/4663898.html