struts2之token,类型转换和数据校验
1 Token防重
使用token防止重复提交
1.1 token内部原理
防止重复提交的方式常见的有两种:使用重定向和使用token令牌完成

在struts2框架中使用令牌基本上就是两步:
- 在
jsp页面中使用<s:token></s:token>标签,可以放在表单中任何位置,这个标签的作用就是在页面中产生一个token id,可以通过查看源文件的形式看到。为什么要放在表单中呢?因为这个是要提交到服务器的,要不然服务器怎么知道id是多少 - 在
struts2核心配置文件中为token拦截器添加参数,来指明需要拦截哪些方法
例如:<interceptor-ref name="token"><param name="includeMethods">save</param></interceptor-ref>,指明拦截save方法。当然也可以用excludeMethods来声明不拦截哪些方法。
如果某个jsp页面中有token标签,那么无论是请求这个界面还是内部转发到这个界面,我们统一说成是渲染界面的时候,都会造成token id的产生或者更新。
1.2 实现步骤
1.2.1 在页面中添加<s:token/>标签
<form action="tokenAction.action" method="post">
<s:token></s:token>
用户名:<input type="text" name="user.userName"/><br>
密码:<input type="text" name="user.userPass"/><br>
<input type="submit" value="注册"/>
</form>
1.2.2 配置strtus.xml配置
在struts.xml中配置token拦截器和默认拦截器栈及验证失败的结果视图(invalid.token)
<action name="tokenAction" class="cn.test.action.TokenAction">
<result>/index.jsp</result>
<result name="invalid.token">/error.jsp</result>
<!-- 引入token拦截器 -->
<interceptor-ref name="token"></interceptor-ref>
<!-- 引入默认拦截器栈 -->
<interceptor-ref name="defaultStack"></interceptor-ref>
</action>
2 类型转换器
HTTP参数都是字符串类型。 保存的数据可能是字符串、数字、布尔、日期时间等或者JavaBean类型。 手工的类型转换,比如将字符串转换为日期,通过: 通过request.getParameter方法获取字符串; 检查是否为空; 通过DateFormat.parse方法将字符串转换为Date对象
2.1 Struts2类型转换
Struts2内置的类型转换 :
String和boolean完成字符串与布尔值之间的转换String和char完成字符串与字符之间的转换String和int、Integer完成字符串与整型之间的转换String和Long完成字符串与长整型值之间的转换String和double、Double完成字符串与双精度浮点值的转换String和Float完成字符串和单精度浮点之间的转换String和Date完成字符串和日期类型之间的转换,日期格式使用格式用户请求所在Locale的SHORT格式String和数组在默认的情况,数组元素是字符串,如果用户定义类型转换器,也可以是其它复合数据类型
在访问struts2中某个action之后或者之前,会自动调用的类,就是struts2中的拦截器,具有的最大特点就是实现了AOP(面向切面编程),可插拔式的,也就是说它可以在需要使用的时候通过配置xml文件来实现,而在不使用的时候又不会影响整个框架的效果,这让struts2的拦截器具有非常好的扩展性
2.2 Struts2自定义类型转化器
需求:用户输入20160520 日期,如果Action类的属性为Date类型,则它不能够正确接收到这个时间值。
这时候需要自定义类型转化。
实现步骤
2.2.1 新建注册页面
<form action="studentAction.action" method="post">
姓名:<input type="text" name="student.studentName"><br>
性别:<input type="radio" name="student.studentSex" value="1">男<input type="radio" name="student.studentSex" value="0">女<br>
地址:<input type="text" name="student.studentAddress"><br>
生日:<input type="text" name="student.birthday">(yyyy/MM/dd)<br>
<input type="submit" value="注册"/>
</form>
2.2.2 编写自定义类型转换器
编写自定义类型转换器用于转换日期和业务逻辑Action
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import org.apache.struts2.util.StrutsTypeConverter;
public class DateConverter extends StrutsTypeConverter {
/**
* 将字符串类型转为目标类型
* 第一个参数:context代表上下文
* 第二个参数:params:用户提交的参数值-->request.getParameterValues()
* 第三个参数:toType要转换成的目标类型
*/
@Override
public Object convertFromString(Map context, String[] params, Class toType) {
String value = params[0];//获取输入的日期 1990/01/01
Date date=null;
if(toType==Date.class){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
try {
date = sdf.parse(value);
} catch (ParseException e) {
e.printStackTrace();
}
}
return date;
}
/**
* 将目标类型转换为字符串
*/
@Override
public String convertToString(Map arg0, Object arg1) {
// TODO Auto-generated method stub
return null;
}
}
2.2.3 业务逻辑action
import com.opensymphony.xwork2.ActionSupport;
/**
* 一旦出现跳转input结果视图,将不执行action中方法
* 导致出现input结果视图的原因有两个
* 1.类型转换失败
* 2.验证失败
*
*/
public class StudentAction extends ActionSupport {
private Student student;
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
@Override
public String execute() throws Exception {
System.out.println("新增了:"+student);
return this.SUCCESS;
}
}
2.2.4 配置自定义类型转换器
局部的类型转换器和全局的类型转换器
局部类型转换器:只针对当前的action中的属性进行转换,在action同包下创建名称与action同名的文件,命名方式为:actionClassName-conversion.properties
属性名称=类型转换器的全限定类名
student.birthday=cn.test.conversion.DateConverter全局类型转换器:针对所有的action中的指定类型进行转换,在src下新建名称为xwork-conversion.properties,其内容为
待转换的类型全限定类名=类型转换器的全限定类名
java.util.Date=cn.test.conversion.DateConverter
3 数据校验
3.1 使用硬编码校验
使用硬编码的方式实现数据校验(通过重写validate()方法或validateXxx()方法来实现)
3.1.1 业务逻辑Action
业务逻辑Action需要继承ActionSupport.重写validate()方法:会针对Action中所有的方法进行校验;validateXxx()方法:Xxx代表需要校验的方法名,只针对于Xxx方法进行数据校验,在校验方法validate()获取validateXxx()中,判断校验规则,如果违反规则使用addFiledError方法添加错误消息
import com.opensymphony.xwork2.ActionSupport;
public class UserAction extends ActionSupport {
private String userName;
private String userPass;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserPass() {
return userPass;
}
public void setUserPass(String userPass) {
this.userPass = userPass;
}
/**
* 登录
* @return
* @throws Exception
*/
public String login() throws Exception {
System.out.println("执行了login方法....");
if("admin".equals(userName)&&"admin".equals(userPass)){
return this.SUCCESS;
}
return this.LOGIN;
}
/**
* 注册
* @return
* @throws Exception
*/
public String add() throws Exception {
System.out.println("执行了add方法....");
return this.SUCCESS;
}
/**
* 签名相同的方法:两个方法定义除方法名不同外,其他都相同。
* 重写ActionSupport中的validate()方法,
* 会针对action中所有的与execute具有相同签名的方法进行校验
*/
// @Override
// public void validate() {
// //用户名为空或用户名为空字符串
// if(userName==null||userName.trim().equals("")){
// this.addFieldError("userName", "用户名不能为空!");
// }
// if(userPass==null||userPass.trim().equals("")){
// this.addFieldError("userPass", "密码不能为空!");
// }
// }
/**
* validateXxx()方法:只针对Xxx方法进行校验,Xxx代表需要校验的方法名称(方法名的首字母需要大写)
*/
public void validateAdd() {
if(userName==null||userName.trim().equals("")){
this.addFieldError("userName", "用户名不能为空!");
}
if(userPass==null||userPass.trim().equals("")){
this.addFieldError("userPass", "密码不能为空!");
}
}
}
3.1.2 struts.xml
在struts.xml中配置input结果视图:无法通过校验规则时会跳转到input结果视图
<struts>
<package name="validation" extends="struts-default">
<global-allowed-methods>regex:.*</global-allowed-methods>
<action name="user-*-*" class="cn.test.action.UserAction" method="{1}">
<result name="success">/index.jsp</result>
<result name="input">/{2}.jsp</result>
</action>
</package>
</struts>
3.1.3 页面部分
在页面上使用<s:fielderror>获取错误消息
Login.jsp
<body>
<s:fielderror></s:fielderror>
<form action="user-login-login.action" method="post">
用户名:<input type="text" name="userName"/><br>
密码:<input type="text" name="userPass"/><br>
<input type="submit" value="登录"/>
</form>
</body>
Add.jsp
<s:fielderror></s:fielderror>
<form action="user-add-add.action" method="post">
用户名:<input type="text" name="userName"/><br>
密码:<input type="text" name="userPass"/><br>
<input type="submit" value="注册"/>
</form>
导致Input结果视图出现的原因主要有两个
- 类型转换失败
- 数据校验失败
3.2 使用基于XML配置的方式完成数据校验
3.2.1 常用校验器
required:必填校验器
<!-- Field Validator Syntax -->
<field name="username">
<field-validator type="required">
<message>username must not be null</message>
</field-validator>
</field>
requiredstring:必填字符串校验器
常用属性:trim 类似于string方法中trim()可以去掉前后空格
<!-- Field-Validator Syntax -->
<field name="username">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>username is required</message>
</field-validator>
</field>
int:整型校验器
常用属性:min最小值,max最大值
<field name="age">
<field-validator type="int">
<param name="min">20</param>
<param name="max">50</param>
<message>Age needs to be between ${min} and ${max}</message>
</field-validator>
</field>
double:双精度浮点类型校验器
stringlength:字符串长度校验器
常用属性:maxLength最大长的 minLength最小长度
<field name="myPurchaseCode">
<field-validator type="stringlength">
<param name="minLength">10</param>
<param name="maxLength">10</param>
<param name="trim">true</param>
<message>Your purchase code needs to be 10 characters long</message>
</field-validator>
</field>
email校验器:电子邮件格式校验器
<field name="myEmail">
<field-validator type="email">
<message>Must provide a valid email</message>
</field-validator>
</field>
url校验器:对网站进行格式校验
<!-- Field Validator Syntax -->
<field name="myHomepage">
<field-validator type="url">
<message>Invalid homepage url</message>
</field-validator>
</field>
regex:正则校验器,支持正则表达式
常见的属性:regex
<!-- Field Validator Syntax -->
<field name="myStrangePostcode">
<field-validator type="regex">
<param name="regex"><![CDATA[([aAbBcCdD][123][eEfFgG][456])]]></param>
</field-validator>
</field>
3.2.2 action使用
在action同包(同一级目录)下新建校验规则定义文件,其命名: ActionClassName-validation.xml(action中所有的方法都将采用其中定义的校验规则)或者ActionClass-ActionAliasName-validation.xml
UserAction-validation.xml--->校验UserAction中所有的方法
UserAction-user-doAdd-validation.xml: 校验UserAciton中doAdd方法
<validators>
<field name="userName">
<!-- requiredstring:字符串必填校验器 -->
<field-validator type="requiredstring">
<!-- 错误提示信息 -->
<message>用户名不能为空!</message>
</field-validator>
<field-validator type="regex">
<param name="regex"><![CDATA[\w{8,}]]></param>
<message>用户名不合法!</message>
</field-validator>
</field>
<field name="userPass">
<!-- requiredstring:字符串必填校验器 -->
<field-validator type="requiredstring">
<!-- 错误提示信息 -->
<message>密码不能为空!</message>
</field-validator>
<field-validator type="regex">
<param name="regex"><![CDATA[\d{6}]]></param>
<message>密码不合法!</message>
</field-validator>
</field>
</validators>
3.2.3 页面部分
在页面上使用<s:fielderror>获取验证提示信息
<html>
<head>
<base href="<%=basePath%>">
<title>注册登陆</title>
</head>
<body>
<s:fielderror></s:fielderror>
<form action="user2-doLogin.action" method="post">
用户名:<input type="text" name="userName"/><br>
密码:<input type="text" name="userPass"/><br>
<input type="submit" value="登陆">
</form>
</body>
</html>

浙公网安备 33010602011771号