Struts2的类型转换
类型转换的作用:
HTTP请求都是字符串类型,需要把这些字符串类型转化成相应的数据类型,使得Web应用的控制组件可以使用。
1.內建的类型转换器
Struts2可以完成大多数常用类型的转换,因为它已经内奸了字符串数据类型和如下类型之间互相转换的转换器:
(1)boolean和Boolean:完成字符串和布尔值之间的转换。
(2)char和Character:完成字符串和字符之间的转换。
(3)int和Integer:完成字符串和整型值之间的转换。
(4)long和Long:完成字符串和长整型值之间的转换。
(5)float和Float:完成字符串和单精度浮点型值之间的转换。
(6)double和Double:完成字符串和双精度浮点型值之间的转换。
(7)Date:完成字符串和时间类型之间的转换。
(8)数组:默认情况下,数组元素是字符串,如果用户提供了自定义类型转换器,也可以是其他复合类型的数组。
(9)集合:在默认情况下,嘉定集合元素类型为String,并创建一个新的ArrayList封装所有的字符串。
注意:
对于数组而言,类型转换将按照数组元素的类型来单独转换每一个元素,如果数组元素的类型转换本身不能完成,系统 将出现类型转换的错误。
2.基于OGNL表达式的类型转换
Struts2允许将请求参数用使用OGNL表达式的方式将其转换成符合类型。
(1)转换成一个简单的符合类型
JavaBean代码:
public class User { //属性 private String username; private String password; //构造方法 public User(){ } public User(String username,String password){ this.username = username; this.password = password; } //setter、getter方法 public void setUsername(String username){ this.username = username; } public String getUsername(){ return this.username; } public void setPassword(String password){ this.password = password; } public String getPassword(){ return this.password; } }
Action类代码:
er user){ this.user = user; } public User getUser(){ return this.user; } //处理逻辑 public String execute()throws Exception{ if(this.getUser().getUsername().equals("jiagoushi")&& this.getUser().getPassword().equals("jiagoushi")){ addActionMessage("转换成功"); return SUCCESS; }else{ addActionMessage("换换失败"); return ERROR; } } }
使用OGNL表达式执行类型转换代码:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>OGNL - test - 1</title> </head> <body> <s:form> <!-- 封装请求参数名为user.username --> <s:textfield name="user.username" key="用户名"/> <!-- 封装请求参数名为user.password --> <s:password name="user.password" key="密码"/> <s:submit value="登陆"/> </s:form> </body> </html>
(2)直接生成Collection实例或者Map实例(这里生成的是Map实例,List实例则更加简单)
JavaBean依然使用User。
Action类为:
import java.util.Map; import myBean.User; import com.opensymphony.xwork2.ActionSupport; public class Login2Action extends ActionSupport{ //封装的请求参数是一个Map类型 //Map类型中的元素为User类型 private Map<String,User> users; //setter、getter方法 public void setUsers(Map<String,User> users){ this.users = users; } public Map<String,User> getUsers(){ return this.users; } //处理逻辑 public String execute()throws Exception{ //控制台输出此Action封装的Map对象 System.out.println(getUsers()); if(getUsers().get("one").getUsername().equals("jiagoushi1")&& getUsers().get("one").getPassword().equals("jiagoushi1")){ addActionMessage("登陆成功"); return SUCCESS; }else{ return ERROR; } } }
使用OGNL表达式执行类型转换代码:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>OGNL - test - 2</title> </head> <body> <s:form action="login2"> <s:textfield name="users['one'].username" key="用户名1"/> <s:password name="users['one'].password" key="密码1"/> <s:textfield name="users['two'].username" key="用户名2"/> <s:password name="users['two'].password" key="密码2"/> <s:submit value="登陆"/> </s:form> </body> </html>
3.指定集合元素的类型
Struts2允许通过局部类型转换文件来指定集合元素的类型,类型转换文件就是一个普通的*.properties文件,下面介绍使用此文件确定集合元素类型。
Action类:
import myBean.User; import com.opensymphony.xwork2.ActionSupport; public class Login3Action extends ActionSupport{ //封装请求参数,注意这里没有为List添加泛型 private List users; //setter、getter方法 public void setUsers(List users){ this.users = users; } public List getUsers(){ return this.users; } //处理逻辑 public String execute()throws Exception{ //因为此List没有使用泛型指定元素类型 //那么需要进行强制类型转换 User firstUser = (User)getUsers().get(0); if(firstUser.getUsername().equals("jiagoushi")&& firstUser.getPassword().equals("jiagoushi")){ return SUCCESS; }else{ return ERROR; } } }
局部类型转换文件:
其文件名根据Action指定为:Login3Action-conversion.properties(其中-conversion.properties为固定格式)。
局部类型转换文件的内容:
Element_users=myBean.User。
4.使用自定义的类型转换器
当需要把一个字符串对象转换成一个复合对象时,就需要使用自定义类型转换器。示例:
JSP页面:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <s:form action="login4"> <!-- 请求是一个字符串类型 (实际上是字符串数组)--> <s:textfield name="user" key="用户"/> <s:submit value="登陆"/> </s:form> </body> </html>
Action类:
package myAction; import myBean.User; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; public class Login4Action extends ActionSupport{ //传来的请求参数是一个String //封装的请求参数是一个User类型 private User user; //setter、getter方法 public void setUser(User user){ this.user = user; } public User getUser(){ return this.user; } //处理逻辑 public String execute()throws Exception{ System.out.println(this.user); if(getUser().getUsername().equals("jiagoushi")&& getUser().getPassword().equals("jiagoushi")){ ActionContext context = ActionContext.getContext(); context.put("name", getUser().getUsername()); context.put("pass", getUser().getPassword()); return SUCCESS; }else{ return ERROR; } } }
Converter类:
package myConverter; import java.util.Map; import myBean.User; import com.opensymphony.xwork2.conversion.impl.DefaultTypeConverter; //User的类型转换器 //实现类型转换器必须继承一个实现类DefaultTypeConverter类 public class UserConverter extends DefaultTypeConverter{ //重写convertValue()方法, //此方法用需要完成双向的转换 public Object convertValue(Map context,Object value,Class toType){ //当需要讲String向User类型转换时 if(toType==User.class){ //系统的请求参数是一个String数组 String[] params = (String[])value; //创建一个User实例 User user = new User(); //只处理请求参数的第一个数组元素 //并将该字符串用英文逗号分割成两个字符串 String[] userValue = params[0].split(","); //为User实例赋值 user.setUsername(userValue[0]); user.setPassword(userValue[1]); //返回转换来的User实例 return user; }else if(toType==String.class){ //将需要转换的值强制转换为User实例 User user = (User)value; return "["+user.getUsername()+","+user.getPassword()+"]"; }else{ return null; } } }
注意,当使用局部类型转换器时,该Converter类的注册文件必须放在与对应Action相同的路径下,而对于全局类型转换器则放在src路径下即可。
5.基于Struts2的自定义类型转换器
Struts2提供了一个抽象类来简化类型转换器的实现,这个类就是StrutsTypeConverter类,这个抽象类是DefaultTypeConverter类的子类,其注册方法与DefaultTypeConverter的方法相同,其示例如下:
package myConverter; import java.util.Map; import myBean.User; import org.apache.struts2.util.StrutsTypeConverter; //使用Struts2提供的自定义类型转换器抽象类 //继承此抽象类:StrutsTypeConverter public class UserConverter2 extends StrutsTypeConverter{ //将字符串类型转换成符合类型的方法 @Override public Object convertFromString(Map arg0, String[] arg1, Class arg2) { //创建一个User实例 User user = new User(); //只处理请求参数的第一个数组元素 //并将该元素用都好分割形成一个新的String数组 String[] userValue = arg1[0].split(","); //为User实例赋值 user.setUsername(userValue[0]); user.setPassword(userValue[1]); //返回转换成的User实例 return user; } //实现将符合类型转换成字符串类型 @Override public String convertToString(Map arg0, Object arg1) { //将需要转换的值强制转换成User类型 User user = (User)arg1; return "["+user.getUsername()+","+user.getPassword()+"]"; } }
6.对于Set集合的处理
通常不建议在Action中使用Set集合作为封装的请求,因为Set集合处于无序的状态,所以Struts2不能准确的将请求参数转换成Set集合的元素。不仅如此,Struts2也不能准确的读取Set集合中的元素。除非在此Set集合中的元素有一个标识属性,这个标识属性可以唯一确定集合元素,这样的情况下,Struts2才能根据此标识属性存取元素。处理Set集合的示例如下:
Action类:
import java.util.Date; import java.util.Set; import com.opensymphony.xwork2.ActionSupport; public class Login5Action extends ActionSupport{ //使用Set集合封装users private Set users; private Date birth; //setter、getter方法 public void setUsers(Set users){ this.users = users; } public Set getUsers(){ return this.users; } public void setBirth(Date birth){ this.birth = birth; } public Date getBirth(){ return this.birth; } //使用ActionSupport默认的execute方法 }
类型转换器:
import java.util.HashSet; import java.util.Map; import java.util.Set; import myBean.User; import org.apache.struts2.util.StrutsTypeConverter; public class UserConverter3 extends StrutsTypeConverter{ //转化为Set类型 @Override public Object convertFromString(Map arg0, String[] arg1, Class arg2) { Set result = new HashSet(); for(int i = 0;i<arg1.length;i++){ //创建一个User实例 User user = new User(); //只处理请求参数的第一个数组元素 //并用都好分割形成新的字符串数组 String[] usersValue = arg1[i].split(","); //为User实例的属性赋值 user.setUsername(usersValue[0]); user.setPassword(usersValue[1]); //把此User实例添加到Set集合中去 result.add(user); } return result; } //转化为String类型 @Override public String convertToString(Map arg0, Object arg1) { if(arg1.getClass()==Set.class){ Set users = (Set) arg1; String result = "["; for(Object obj : users){ User user = (User)obj; result = result + "[" + user.getUsername() + "," +user.getPassword() + "]"; } return result + "]"; }else{ return ""; } } }
User类:
package myBean; public class User { //属性 private String username; private String password; //构造方法 public User(){ } public User(String username,String password){ this.username = username; this.password = password; } //setter、getter方法 public void setUsername(String username){ this.username = username; } public String getUsername(){ return this.username; } public void setPassword(String password){ this.password = password; } public String getPassword(){ return this.password; } //下面方法与HashSet中比较是否为同一个元素时使用 //重写equals方法 public boolean equals(Object obj){ //两个对象为同一个对象时返回true if(this == obj){ return true; }else if(obj != null && obj.getClass()==User.class){ //只有当obj为User对象时 User user = (User)obj; //两个对象的username属性相同时认为两个对象为同一个对象 return this.getUsername().equals(user.getUsername()); }else{ return false; } } //根据username计算hashcode值 public int hashCode(){ return username.hashCode(); } }
在局部类型转换文件中添加key、value对指定Set集合元素的标识属性:
keyProperty_users=username。