标签:
首先,我们用第一种方式:继承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提供的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>
下面是运行结果的一个截图:
此外,还用一种类型转换的方式(要求用户输入坐标分别在两个输入框中):
修改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,浏览器访问,输出结果正常,说明我们的配置是正确的。
标签:
原文地址:http://www.cnblogs.com/Code-Rush/p/4659815.html