1、在login.jsp中添加一个age的text文本域,在LoginAction中新增一个int类型的成员变量,jsp提交时,将进行自动的类型转换,文本类型的age转换为int类型。
2、对于struts2来说,LoginAction每一次请求都会生成一个新的对象。
3、struts2自带了类型转换功能,8个原生数据类型、日期型、String等,struts2可以使用内建的类型转换器实现自动转换。而我们自己定义的类型,则需要我们自己定义类型转换方式了。
4、我们编写的action类,一般都要继承com.opensymphony.xwork2.ActionSupport这个父类,这个类提供了很多额外的功能支持,
5、类型转换例子剖析:
一个提交页面test.jsp:
<body>
<h1>使用分号隔离用户与密码</h1>
<form action="userAction.action">
user info:<input type="text" name="user"><br>
<input type="submit" value="submit">
</form>
</body>
我们在输入框中输入用户;密码格式的输入文本,用来代表用户和密码,在后台,我们需要将这个字符串转换为一个对象,这个对象如下:
package com.cdtax.bean;
public class User
{
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;
}
}
jsp页面提交的action为:
package com.cdtax.struts2;
import com.cdtax.bean.User;
import com.opensymphony.xwork2.ActionSupport;
public class UserAction extends ActionSupport
{
private User user;
public User getUser()
{
return user;
}
public void setUser(User user)
{
this.user = user;
}
@Override
public String execute() throws Exception
{
System.out.println("username:" + user.getUsername());
System.out.println("password:" + user.getPassword());
return SUCCESS;
}
}
我们看到在这个action中(UserAction)使用的是User对象,这就需要jsp页面在提交表单后,在进入UserAction之前需要进行转换,将页面表单提交的字符串格式用户;密码转换为User对象,具体使用哪个处理类来进行转换,怎么转换,需要在UserAction这个类的相同包下创建一个属性文件,名字为UserAction-conversion.properties,它的内容为字符串键值对,这里是:user=com.cdtax.converter.UserConverter,这个键值对指出UserAction类中的user成员变量使用com.cdtax.converter.UserConverter这个转换器进行类型转换。这个属性文件的名字是固定的,Xxx--conversion.properties,Xxx为相应的action类。
转换器如下:
package com.cdtax.converter;
import java.lang.reflect.Member;
import java.util.Map;
import java.util.StringTokenizer;
import com.cdtax.bean.User;
import ognl.DefaultTypeConverter;
public class UserConverter extends DefaultTypeConverter
{
@Override
public Object convertValue(Map context, Object value, Class toType)
{
if(User.class == toType) //从页面向后台对象转换
{
String[] str = (String[])value;
String firstValue = str[0];
StringTokenizer st = new StringTokenizer(firstValue,";");
String username = st.nextToken();
String password = st.nextToken();
User user = new User();
user.setUsername(username);
user.setPassword(password);
return user;
}
return null;
}
}
我们自己定义的转换器要继承ognl.DefaultTypeConverter,提供了类型转换功能,主要是一个public Object convertValue(Map context, Object value, Class toType)方法,其中参数Object value只要转换的值,如这里是从jsp提交到后台,从字符串转换为User对象,value就是jsp传来的字符串值(实际上是字符串数组),Class toType参数指明要转换为什么类型,这里是User类型,就是User.class。
对于自定义的类型转换器来说需要提供3个信息:Action的名字、Action中待转换的属性名以及该属性对应的类型转换器。其中Action的名字是通过属性文件名来获得的,Action中待转换的属性名是通过属性文件中的key来获得的,该属性对应的类型转换器是通过该key所对应的value来获得的。
完善的UserConverter
package com.cdtax.converter;
import java.lang.reflect.Member;
import java.util.Map;
import java.util.StringTokenizer;
import com.cdtax.bean.User;
import ognl.DefaultTypeConverter;
public class UserConverter extends DefaultTypeConverter
{
@Override
public Object convertValue(Map context, Object value, Class toType)
{
if(User.class == toType) //从页面向后台对象转换
{
String[] str = (String[])value;
String firstValue = str[0];
StringTokenizer st = new StringTokenizer(firstValue,";");
String username = st.nextToken();
String password = st.nextToken();
User user = new User();
user.setUsername(username);
user.setPassword(password);
return user;
}
else if(String.class == toType) //从后台对象向页面转换
{
User user = (User)value;
String username = user.getUsername();
String password = user.getPassword();
String userInfo = "username:" + username + ",password:" + password;
return userInfo;
}
return null;
}
}
最终的success.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 '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>
<s:property value="user" />
</body>
</html>
注意这里引用了struts的标签库,开始使用struts标签:taglib prefix="s" uri="/struts-tags"
6、以上是一种默认的类型转换模式,struts自带的类型转换模式,struts提供了自已的一套类型转换机制
struts提供了自己的类型转换器基类:org.apache.struts2.util.StrutsTypeConverter,提供了三个方法:
convertFromString(Map context, String[] values, Class toClass) 从页面转换为后台对象
convertToString(Map context, Object o) 从后台对象转换为页面字符串
convertValue(Map context, Object o, Class toClass)
StrutsTypeConverter的源代码实现:
public abstract class StrutsTypeConverter extends DefaultTypeConverter {
public Object convertValue(Map context, Object o, Class toClass) {
if (toClass.equals(String.class)) {
return convertToString(context, o);
} else if (o instanceof String[]) {
return convertFromString(context, (String[]) o, toClass);
} else if (o instanceof String) {
return convertFromString(context, new String[]{(String) o}, toClass);
} else {
return performFallbackConversion(context, o, toClass);
}
}
使用struts2框架自带的类型转换器简化类型转换代码的编写:
package com.cdtax.converter;
import java.util.Map;
import java.util.StringTokenizer;
import org.apache.struts2.util.StrutsTypeConverter;
import com.cdtax.bean.User;
public class UserConverter2 extends StrutsTypeConverter
{
@Override
public Object convertFromString(Map context, String[] values, Class toClass)
{
User user = new User();
String value = values[0];
StringTokenizer st = new StringTokenizer(value,";");
user.setUsername(st.nextToken());
user.setPassword(st.nextToken());
return user;
}
@Override
public String convertToString(Map context, Object o)
{
User user = (User)o;
String username = user.getUsername();
String password = user.getPassword();
String userInfo = "username:" + username + ",password:::" + password;
return userInfo;
}
}
同时修改UserAction-conversion.properties属性文件:user=com.cdtax.converter.UserConverter2
7、传递一个文本框数组:
<body>
<h1>使用分号隔离用户与密码</h1>
<form action="userAction2.action">
user info 1:<input type="text" name="user"><br>
user info 2:<input type="text" name="user"><br>
user info 3:<input type="text" name="user"><br>
user info 4:<input type="text" name="user"><br>
<input type="submit" value="submit">
</form>
</body>
新建UserAction2:
package com.cdtax.struts2;
import java.util.List;
import com.cdtax.bean.User;
import com.opensymphony.xwork2.ActionSupport;
public class UserAction2 extends ActionSupport
{
private List<User> user;
public List<User> getUser()
{
return user;
}
public void setUser(List<User> user)
{
this.user = user;
}
@Override
public String execute() throws Exception
{
return SUCCESS;
}
}
创建新的转转器:
package com.cdtax.converter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import org.apache.struts2.util.StrutsTypeConverter;
import com.cdtax.bean.User;
public class UserConverter3 extends StrutsTypeConverter
{
@Override
public Object convertFromString(Map context, String[] values, Class toClass)
{
List<User> list = new ArrayList<User>();
for(String value : values)
{
StringTokenizer st = new StringTokenizer(value,";");
User user = new User();
user.setUsername(st.nextToken());
user.setPassword(st.nextToken());
list.add(user);
}
return list;
}
@Override
public String convertToString(Map context, Object o)
{
List<User> list = (List<User>)o;
StringBuffer buffer = new StringBuffer();
for(User user : list)
{
String username = user.getUsername();
String password = user.getPassword();
buffer.append("username : ").append(username).append(",password: ").append(password);
}
return buffer.toString();
}
}
创建新的属性文件UserAction2-conversion.properties:
user=com.cdtax.converter.UserConverter3
8、全局类型转换
不管哪一个action,只要有User类,就使用这个转换器。而上面所讲的转换器是针对某一个特定的action来说的,可以叫做局部类型转换
对于全局类型转换,要在src目录下新建文件:xwork-conversion.properties
com.cdtax.bean.User=com.cdtax.converter.UserConverter2
它的key是要被转换的类,value是转换器类名字