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是转换器类名字