第十一部分_Struts2.1类型转换精析

首先,我们用第一种方式:继承ognl包下面的DefaultTypeConverter类,做一个类型转换:

新建一个input.jsp:

<%@ page language="java" import="java.util.*" pageEncoding="GBK"%>

<%

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 'input.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>

    

    <h1>请输入一个点的坐标(使用逗号分隔)</h1>

    <form action="converterAction.action" method="post">

    	坐标:<input type="text" name="point" size="20"><br>

    	坐标2:<input type="text" name="point2" size="20"><br>

    	用户名:<input type="text" name="username" size="20"><br>

    	年龄:<input type="text" name="age" size="20"/><br/>

    	出生日期:<input type="text" name="birthday" size="20"/><br/>

    	<input type="submit" value="submit"/>"

    

    

    </form>

    

    

  </body>

</html>

接下来编写处理类,在com.test.action包下建立一个PointAction类:

package com.test.action;



import java.util.Date;



import com.opensymphony.xwork2.ActionSupport;

import com.test.bean.Point;



public class PointAction extends ActionSupport

{

	private Point point;

	

	private Point point2;

	

	private String username;

	

	private int age;

	

	private Date birthday;



	public Point getPoint2()

	{

		return point2;

	}



	public void setPoint2(Point point2)

	{

		this.point2 = point2;

	}



	public Point getPoint()

	{

		return point;

	}



	public void setPoint(Point point)

	{

		this.point = point;

	}



	public String getUsername()

	{

		return username;

	}



	public void setUsername(String username)

	{

		this.username = username;

	}



	public int getAge()

	{

		return age;

	}



	public void setAge(int age)

	{

		this.age = age;

	}



	public Date getBirthday()

	{

		return birthday;

	}



	public void setBirthday(Date brithday)

	{

		this.birthday = brithday;

	}

	

	public String execute() throws Exception

	{

		return "success";

	}

}

对于坐标的赋值,需要新建一个类,在com.test.bean包下新建一个类Point:

package com.test.bean;



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;

	}

	

	

}

然后再com.test.converter包下面建立一个点坐标的转换类PointConverter(该类需要继承ognl包下面的DefaultTypeConverter类):

package com.test.converter;



import java.util.Map;



import ognl.DefaultTypeConverter;



import com.test.bean.Point;



public class PointConverter extends DefaultTypeConverter

{

	@Override

	public Object convertValue(Map context, Object value, Class toType)

	{

		if(Point.class==toType)

		{

			String[] str = (String[])value;

			

			String firstValue = str[0];

			

			String[] resultValue = firstValue.split(",");

			

			Point point = new Point();

			point.setX(Integer.parseInt(resultValue[0]));

			point.setY(Integer.parseInt(resultValue[1]));

			

			return point;

		}

		else if(String.class == toType)

		{

			Point point = (Point)value;

			

			int x = point.getX();

			int y = point.getY();

			

			String result = "X: " + x + " Y: " + y;

			

			return result;

		}

		

		return null;

	}

}

此外,我们需要做一些相关的配置让struts2找到这个处理类,在com.test.action下建立一个文件:PointAction-conversion.properties,注意到这个文件在'-'后的字符都是固定的,只用前面是可以变化的,此外他必须和PointAction放在同一个包下面:

point=com.test.converter.PointConverter

point2=com.test.converter.PointConverter

然后配置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>

			</action>

			

			<action name="converterAction" class="com.test.action.PointAction">

				<result name="success">/output.jsp</result>

			</action>

		</package>

	

	

	</struts>

最后写一个output.jsp,输出有几种选择:JSP脚本;EL;Struts2的标签库。这里我们使用后者:

<%@ 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 'output.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:property value="point"/><br/>

  	坐标2:<s:property value="point2"/><br/>

  	用户名:<s:property value="username"/><br>

  	年龄:<s:property value="age"/><br>

  	出生日期:<s:property value="birthday"/>



  </body>

</html>

下面是运行结果的一个截图:

第十一部分_Struts2.1类型转换精析

其次,我们用Struts2提供的StrutsTypeConverter(它也继承了ognl包下面的DefaultTypeConverter类,如何在MyEclipse中查看其源代码?MyEclipse中找到struts2-core-2.1.6.jar,展开,找到org.apach.struts2.util,找到旗下的Struts TypeConverter.class,打开,点击Attach Source->External Folder,找到struts-2.1.6的解压缩目录,找到目录下的src,在src下面展开core,展开main,main下面有一个java,选择java,确定,这样就把硬盘上的源码和MyEclipse关联起来了)抽象类:

在com.test.converter包下面新建一个类PointConverter2:

package com.test.converter;



import java.util.Map;



import org.apache.struts2.util.StrutsTypeConverter;



import com.test.bean.Point;



public class PointConverter2 extends StrutsTypeConverter

{



	@Override

	public Object convertFromString(Map context, String[] values, Class toClass)

	{

		Point point = new Point();

		

		String value = values[0];

		

		String[] result = value.split(",");

		

		point.setX(Integer.parseInt(result[0]));

		point.setY(Integer.parseInt(result[1]));

		

		return point;

	}



	@Override

	public String convertToString(Map context, Object o)

	{

		Point point = (Point)o;

		

		int x =point.getX();

		int y = point.getY();

		

		String result = "x: " + x + " y: " + y;

		

		return result;

	}



}

修改PointAction-conversion.properties:

point=com.test.converter.PointConverter2

point2=com.test.converter.PointConverter2

浏览器访问http://localhost:8080/struts2/input.jsp,运行结果和用第一种方式实现的结果一样。

一个问题:如何进行批量处理(假如有100个point,难道要从point1定义到point100)?

我们假设有三个坐标表示"很多个坐标",在input.jsp中,注意到这些点的name属性都是相同的:

<form action="converterAction.action" method="post">

    	坐标:<input type="text" name="point" size="20"><br>

    	坐标2:<input type="text" name="point" size="20"><br>

    	坐标3:<input type="text" name="point" size="20"><br>

    	用户名:<input type="text" name="username" size="20"><br>

    	年龄:<input type="text" name="age" size="20"/><br/>

    	出生日期:<input type="text" name="birthday" size="20"/><br/>

    	<input type="submit" value="submit"/>"

    

    

    </form>

修改PointAction类:

package com.test.action;



import java.util.Date;

import java.util.List;



import com.opensymphony.xwork2.ActionSupport;

import com.test.bean.Point;



public class PointAction extends ActionSupport

{

	/*private Point point;

	

	private Point point2;*/

	

	private List<Point> point;

	

	private String username;

	

	



	private int age;

	

	private Date birthday;

	

	public List<Point> getPoint()

	{

		return point;

	}



	public void setPoint(List<Point> point)

	{

		this.point = point;

	}

	/*public Point getPoint2()

	{

		return point2;

	}



	public void setPoint2(Point point2)

	{

		this.point2 = point2;

	}



	public Point getPoint()

	{

		return point;

	}



	public void setPoint(Point point)

	{

		this.point = point;

	}*/



	public String getUsername()

	{

		return username;

	}



	public void setUsername(String username)

	{

		this.username = username;

	}



	public int getAge()

	{

		return age;

	}



	public void setAge(int age)

	{

		this.age = age;

	}



	public Date getBirthday()

	{

		return birthday;

	}



	public void setBirthday(Date brithday)

	{

		this.birthday = brithday;

	}

	

	public String execute() throws Exception

	{

		return "success";

	}

}

然后编写转换类PointConverter3:

package com.test.converter;



import java.util.ArrayList;

import java.util.List;

import java.util.Map;



import org.apache.struts2.util.StrutsTypeConverter;



import com.test.bean.Point;



public class PointConverter3 extends StrutsTypeConverter

{



	@Override

	public Object convertFromString(Map context, String[] values, Class toClass)

	{

		List<Point> list = new ArrayList<Point>();

		

		for(String value : values)

		{

			String[] result = value.split(",");

			Point point = new Point();

			

			point.setX(Integer.parseInt(result[0]));

			point.setY(Integer.parseInt(result[1]));

			

			list.add(point);

		}

		

		return list;

	}



	@Override

	@SuppressWarnings("unchecked")

	public String convertToString(Map context, Object o)

	{

		List<Point> list = (List<Point>)o;

		

		StringBuffer sb = new StringBuffer();

		

		int number = 0;

		

		for(Point point : list)

		{

			number++;

			

			int x = point.getX();

			int y = point.getY();

			

			// 这里不要使用以前PointConverter里那种直接拼接的方式,字符串太多,效率太低

			sb.append(number).append(".x=").append(x).append(" y=").append(y).append(" ");

			

			

		}

		

		return sb.toString();

	}



}

更改配置文件PointAction-conversion.properties:

#point=com.test.converter.PointConverter2

#point2=com.test.converter.PointConverter2

point=com.test.converter.PointConverter3

最后更改output.jsp:

 <body> 

  	坐标:<s:property value="point"/><br/>

  	用户名:<s:property value="username"/><br>

  	年龄:<s:property value="age"/><br>

  	出生日期:<s:property value="birthday"/>



  </body>

下面是运行结果的一个截图:

第十一部分_Struts2.1类型转换精析  

 此外,还用一种类型转换的方式(要求用户输入坐标分别在两个输入框中):

修改input.jsp:

<body>

    

    <h1>请输入一个点的坐标(使用逗号分隔)</h1>

    <form action="converterAction.action" method="post">

    <!-- 

    	坐标:<input type="text" name="point" size="20"><br>

    	坐标2:<input type="text" name="point" size="20"><br>

    	坐标3:<input type="text" name="point" size="20"><br>

     -->

     	x:<input type="text" name="point.x" size="20"/><br/>

     	y:<input type="text" name="point.y" size="20"/><br/>

    	用户名:<input type="text" name="username" size="20"><br>

    	年龄:<input type="text" name="age" size="20"/><br/>

    	出生日期:<input type="text" name="birthday" size="20"/><br/>

    	<input type="submit" value="submit"/>"

    

    

    </form>

PointAction类内容如下:

package com.test.action;



import java.util.Date;

import java.util.List;



import com.opensymphony.xwork2.ActionSupport;

import com.test.bean.Point;



public class PointAction extends ActionSupport

{

	private Point point;

	

	private String username;



	private int age;

	

	private Date birthday;



	public Point getPoint()

	{

		return point;

	}



	public void setPoint(Point point)

	{

		this.point = point;

	}



	public String getUsername()

	{

		return username;

	}



	public void setUsername(String username)

	{

		this.username = username;

	}



	public int getAge()

	{

		return age;

	}



	public void setAge(int age)

	{

		this.age = age;

	}



	public Date getBirthday()

	{

		return birthday;

	}



	public void setBirthday(Date brithday)

	{

		this.birthday = brithday;

	}

	

	public String execute() throws Exception

	{                

                // 两行测试语句,输出到控制台

		System.out.println("X: " + point.getX());

		System.out.println("Y: " + point.getY());





		return "success";

	}

}

更改Point类,重写其toString方法:

package com.test.bean;



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;

	}

	

	@Override

	public String toString()

	{

		String result = "x: " + x + " y: " + y;

		return result;

	

	}

}

注释掉PointAction-conversion.properties:

#point=com.test.converter.PointConverter2

#point2=com.test.converter.PointConverter2

#point=com.test.converter.PointConverter3

output.jsp如下:

<body> 

  	坐标:<s:property value="point"/><br/>

  	用户名:<s:property value="username"/><br>

  	年龄:<s:property value="age"/><br>

  	出生日期:<s:property value="birthday"/>



  </body>

浏览器运行结果:

坐标:x: 1 y: 2
用户名:name
年龄:20
出生日期:93-3-30

 

此外,附送一个小知识点:如果我们的Action有多个,比如增删查改,那么类就有点多了,我们可以用同一个action来处理多个业务需求,如下修改PointAction(增加了一个test方法,struts2要求这个方法除了方法名和execute不同外,其他签名包括public修饰符、抛出异常等必须完全一致):

package com.test.action;



import java.util.Date;

import java.util.List;



import com.opensymphony.xwork2.ActionSupport;

import com.test.bean.Point;



public class PointAction extends ActionSupport

{

	private Point point;

	

	private String username;



	private int age;

	

	private Date birthday;



	public Point getPoint()

	{

		return point;

	}



	public void setPoint(Point point)

	{

		this.point = point;

	}



	public String getUsername()

	{

		return username;

	}



	public void setUsername(String username)

	{

		this.username = username;

	}



	public int getAge()

	{

		return age;

	}



	public void setAge(int age)

	{

		this.age = age;

	}



	public Date getBirthday()

	{

		return birthday;

	}



	public void setBirthday(Date brithday)

	{

		this.birthday = brithday;

	}

	

	public String test() throws Exception

	{

		System.out.println("test invoked");

		

		System.out.println("X: " + point.getX());

		System.out.println("Y: " + point.getY());

		

		return SUCCESS; // 读过Action的源代码,就知道它定义了一个叫做SUCCESS的常量,其值就是“success”,因此这里的效果和 return "success"相同

	}

	

	public String execute() throws Exception

	{

		System.out.println("X: " + point.getX());

		System.out.println("Y: " + point.getY());

		return "success";

	}

}

那么如何让我们的程序不执行默认的execute而是执行test方法呢?方法就是修改对应的struts.xml文件:

<action name="converterAction" class="com.test.action.PointAction" method="test">

				<result name="success">/output.jsp</result>

			</action>

可以看到在原有的基础上我们为其增加了一个method属性,并将其赋值为test,这样浏览器中访问http://localhost:8080/struts2/input.jsp,输出依旧,回到控制台可以看到test invoked,说明我们的做法成功了。

补充:注意到上面程序中我给return SUCCESS语句添加了注释,提到了Action源码,其源码不在Struts2中,需要根据版本单独下载,比如我们这里是xwork-2.1.2,下载XWork源代码,找到对应的目录,比如我下载完成后,解压放到了struts2下面的D:\ProgramFiles\struts-2.1.6\xwork-2.1.2\src\java。MyEclipse中关联起来即可。

我们怎么知道这个类的呢?

因为我们的PointAction继承了ActionSupport,而ActionSupport实现了Action。

再补充:如果我们要转换的Point在除了PointAction中还有其他的Action类需要对同样地Point转换,我们是不是针对每一个Action都得在它对应的包下面写一个同样的配置文件呢?答案是不需要,struts考虑到这点,给我们提供了一个全局转换的功能,在src(不要定义在某个包里,否则这个全局转换就失效了)下面新建一个文件命名为xwork-conversion.properties,注意到这里每个字符都是固定的。内容如下:

#要转换的对象的类的全名=右边是转换器的名字

com.test.bean.Point=com.test.converter.PointConverter2

将input.jsp的坐标部分更改为:坐标:<input type="text" name="point" size="20"/><br/> 

注释掉PointAction-conversion.properties,浏览器访问,输出结果正常,说明我们的配置是正确的。

你可能感兴趣的:(struts2)