Jsp页面中的数据传送到服务器端,在进行验证之前会先进行类型转换。类型转换成功之后再进行验证,如果类型转换不成功,当然也就没有必要进行数据验证了。今天我们就来学习一下Struts2中的数据类型转换。
为什么要进行数据类型转换呢?jsp页面中的数据传送到服务器端,都是String类型,而Java类中可能会有int,double,date,还有对象类型等等,这就造成了数据类型的不一致,这就是我们要进行数据类型转换的原因。
Struts2中的数据类型转换分为两大类,第一类是基本数据类型转换,如int,date等等。这类转换有Struts2自动完成,所以这类转换我们不用关心,也不做介绍。第二类是对象类型转换,这是我们介绍的重点。
对象类型转换又分为两种,一种是局部的类型转换,即针对某个类中的某个属性进行类型转换。一种是全局的类型转换,即整个项目中的所有的该类型的数据都会调用指定的转换类进行转换。
假如我们的jsp页面要传送一个点(point)的数据到服务器端,这个点的数据由x和y值组成,x和y值用逗号“,”分隔开,如“23,28”等等。这种对象类型的数据Struts2无法自动完成类型转换,所以就需要我们手动编写类型转换代码来完成类型转换。
先看jsp页面point.jsp中的代码:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<%
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 'point.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 name="pointForm" action="pointConverte">
<s:textfield name="point" label="Point"></s:textfield>
<s:submit name="btnSubmit" value=" Submit "></s:submit>
</s:form>
</body>
</html>
该页面中有一个point文本框,在里边输入x和y的值,中间用“,”分隔。该页面提交到名为“pointConverte”的action中,所以在struts.xml文件中要配置一个名为“pointConverte”的action。struts.xml文件中的部分代码如下所示:
<action name="pointConverte"
class="cn.com.huixin.tsms.action.UserAction" method="pointConverte">
<result name="success">/result.jsp</result>
<result name="input">/point.jsp</result>
</action>
所以在cn.com.huixin.tsms.action包中应该有一个名为UserAction的类,该类中有一个名为“pointConverte”的方法。UserAction中的代码如下所示:
package cn.com.huixin.tsms.action;
import cn.com.huixin.tsms.model.Point;
import com.opensymphony.xwork2.ActionSupport;
public class UserAction extends ActionSupport {
private static final long serialVersionUID = 1l;
private Point point;
public Point getPoint() {
return point;
}
public void setPoint(Point point) {
this.point = point;
}
public String pointConverte() throws Exception {
return SUCCESS;
}
}
在pointConverte方法中什么都不用做,直接返回SUCCESS,表示成功。
在UserAction所在的目录中编写一个名为“UserAction-conversion.properties”的properties文件,该文件的代码如下:
point=cn.com.huixin.tsms.converter.PointConverter
这个properties文件的命名规则为:要进行类型转换的属性所在的action的名字-conversion.properties。文件中的内容表示用类cn.com.huixin.tsms.converter.PointConverter来转换point属性。
PointConverter的代码如下:
package cn.com.huixin.tsms.converter;
import java.util.Map;
import org.apache.struts2.util.StrutsTypeConverter;
import cn.com.huixin.tsms.model.Point;
public class PointConverter extends StrutsTypeConverter {
@SuppressWarnings("unchecked")
@Override
public Object convertFromString(Map context, String[] values, Class toClass) {
Point point = new Point();
String[] params = values[0].split(",");
int x = Integer.parseInt(params[0]);
int y = Integer.parseInt(params[1]);
point.setX(x);
point.setY(y);
return point;
}
@SuppressWarnings("unchecked")
@Override
public String convertToString(Map context, Object o) {
Point point = (Point) o;
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("x=").append(point.getX());
stringBuilder.append(", y=").append(point.getY());
return stringBuilder.toString();
}
}
public Object convertFromString(Map context, String[] values, Class toClass)方法为从页面传入的String转换为Point时调用。参数toClass表示要转换为的类型,values为从页面传过来的参数,要把values转换为toClass类型。注意values为String数组,由于页面上可以将多个text的name属性都设为point,即可以有多个name属性值相同的text元素,在这种情况下传到服务器端就是一个String数组,而struts考虑的是最通用的情况,所以这儿是一个String数组。由于页面上目前只有一个name属性值为point的text元素,所以取values数组中的第一个字符串,由于x和y值我们是用“,”分隔的,所以调用split方法用“,”分隔开,然后分别取x和y值,将它们放入point对象中,返回point对象。
public String convertToString(Map context, Object o)方法是将point对象从服务器端传到客户端的页面时调用,传到页面的都是String类型,所以这里只有一个要转换为String的对象Object o,将o转换为字符串返回给页面。jsp页面上即可显示point属性。
整个程序的运行流程为,页面提交point的值到服务器,根据struts.xml文件中的配置可知pointConverte需要由cn.com.huixin.tsms.action.UserAction类中的pointConverte方法来处理,所以生成一个cn.com.huixin.tsms.action.UserAction类的实例,然后调用准备赋值,即调用setPoint方法。在赋值之前会先检查cn.com.huixin.tsms.action.UserAction类所在的目录中是否有以“UserAction”开头,后加“-conversion.properties”的属性文件,如果有,说明UserAction中有属性需要进行类型转换。到UserAction-conversion.properties文件中发现,point属性需要用cn.com.huixin.tsms.converter.PointConverter进行类型转换,又调用PointConverter类中的convertFromString方法,将字符串转换为Point对象返回,该返回值赋给setPoint方法中的point对象。这样就完成了从客户端到服务器端的数据类型转换。然后调用UserAction中的pointConverte方法,之后返回jsp页面。到页面发现有一个point属性,又调用PointConverter类中的convertToString方法,将point对象转换为String类型,返回该String,将该值赋给getPoint方法中的返回值。这样就完成了从服务器端的对象向页面的String类型转换的过程。
以上是局部类型转换,下面介绍一下全局类型转换。
假如多个Action中都有Point属性,那么我们就需要写多个acton-conversion.properties文件,显然这样非常麻烦,Struts为我们提供一个全局类型转换的功能。全局类型转换和局部类型转换的不同在于properties文件。全局类型转换的properties文件名字必须为“xwork-conversion.properties”,而且该文件必须放在classes目录下。在IDE中如eclipse或myeclipse中,我们只要放在src目录中即可,IDE会自动为我们编译到classes目录中的。该文件的实例代码如下:
cn.com.huixin.tsms.model.Point=cn.com.huixin.tsms.converter.PointConverter
表示项目中所有的类型为cn.com.huixin.tsms.model.Point的对象都用cn.com.huixin.tsms.converter.PointConverter进行转换。
Point的代码如下:
package cn.com.huixin.tsms.model;
public class Point {
private int x;
private int y;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
Struts首先检查action所在的目录中有没有以该action名字+“-conversion.properties”命名的属性文件,如果有则根据该文件中提供的类来进行类型转换。如果没有局部类型转换文件,则检查classes目录中有么有名为“xwork-conversion.properties”的文件,如果有,则根据该文件中提供的类来转换数据类型。
Struts2中关于类型转换的内容还有很多,我这里讲的只是最简单、最基本、我们最常用的。