版权声明: 本文由 一只博客 发表于 bloghome博客

文章链接: https://www.bloghome.com.cn/user/cnn237111


使用DefaultTypeConverter

---------------------------

web页面往后台传值,只能传递字符串,要使得字符串能自动的转换成一个类,以便于后台能更好的处理数据,就需要使用到struts中的类型转换器了。

比如,页面上传递一个值"zhangsan,20",表示张三,20岁,action中可以直接获得直接获得这样一个user对象。即在action中能使用如下的代码:

public class testconvert extends ActionSupport { 
	private User user333; 
	@Override
	public String execute() throws Exception { 
		System.out.println("username: " + user333.getUsername()); 
		System.out.println("age: " + user333.getAge()); 
		return SUCCESS; 
	} 
}

定义了user类型,并且在execute方法中可以直接使用user这个对象。

要实现这个功能,就需要把传过来的string转变成user对象。

转换的方式需要一个转换类,并且这个转换类必须继承DefaultTypeConverter类,然后,实现它的convertValue方法。

实现了转换类之后,还需要一个配置文件,来指示说明该转换类用于转换哪个变量的,(java真的很繁琐)。

首先要覆盖掉DefaultTypeConverter类中的convertValue方法,该方法有3个重载,通常覆盖签名如下的方法:

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

其中Map context没有什么用。

常规写法如下:

public class UserConverter extends DefaultTypeConverter {
	@Override     
	public Object convertValue(Map context, Object value, Class toType) {
		System.out.println("convertValue");
		//从页面向后台对象转换       
		if(myUser.class == toType) {
			//value是一个数组,因为它是根据表单中可能有多个元素的name属性是相同的,因此只要name属性为指定的表单元素的值都会被传输过来。
			String[] str = (String[])value; //通常只会取第一个。             
			String firstValue = str[0];                          
			System.out.println(firstValue);                          
			StringTokenizer st = new StringTokenizer(firstValue, ",");
			String username = st.nextToken();             
			int age =Integer.parseInt( st.nextToken());                          
			myUser user = new myUser();                          
			user.setUsername(username);             
			user.setAge(age);                          
			return user;                 
		} else if(String.class == toType) { //从后台对象向页面转换             
			myUser user = (myUser)value;                          
			String username = user.getUsername();             
			int age = user.getAge();                          
			String userInfo = "username: " + username + ", age: " + age;
			return userInfo;         
		}
		return null;
	}  
}

然后在action类中,把要转换的对象,完成他们的set和get方法,注意大小写,set,get后的字母要大写,这是基于约定的。OGNL转换会去找这2个方法调用的。

public class testconvert extends ActionSupport {
	private myUser user333;      
	public myUser getUser333() {         
		System.out.println("getuser333");         
		return user333;     
	}      
	public void setUser333(myUser user) {         
		System.out.println("setuser333");         
		this.user333 = user;     
	}      
	@Override     
	public String execute() throws Exception     
	{         
		System.out.println("username: " + user333.getUsername());
		System.out.println("age: " + user333.getAge());          
		System.out.println("execute");         
		return SUCCESS;     
	} 
}

接下来属性文件的命名,必须是按照固定格式的,action类名-conversion.properties,此例中命名为testconvert-conversion.properties,和action类在同一级目录下。如果要寻找某一个action中的某属性对应的转换类,必须按照这种文件名格式寻找对应的文件。属性文件中如下编码格式为:

属性名=转换类,此例中为:

user333=com.tutorialspoint.sconvert.UserConverter,表示user333这个值用com.tutorialspoint.sconvert.UserConverter这个类做转换。

注意,此处的键名user333,是根据setUser333,getUser333而命名的,并不是根据private myUser  user333,因此,即使把private的user333改成变量user444,只要set和get的名字不改,properties文件中依旧是用user333作为键名。

在jsp提交页面中,编码如下:


	Please enter your name
       

此处的变量名都要对应相同,不然会出错。

对于从Javabean中把值传到前台的HTML,上面的编码已经展示了,唯一要做的是在展示页面把该值读出来。

通过语句即可,该语句会调用getUser333这个方法,进而调用 UserConverter 中的convertValue方法,完成转换。

使用StrutsTypeConverter

--------------------------------

由于继承DefaultTypeConverter需要做类型判断等操作,比较麻烦,strut2提供了StrutsTypeConverter,该类一个抽象类,是对DefaultTypeConverter的继承。该类是把之前convertValue方法中的if判断逻辑,封装成2个不同的方法。分别是convertFromString(Map context, String[] values, Class toClass) 和 convertToString(Map context, Object o)

这样的话,逻辑上更为清晰。如可以参照之前的UserConverter类,实现UserConverter2类。完成一样的工作。

public class UserConverter2 extends StrutsTypeConverter {      
	@Override     
	public Object convertFromString(Map arg0, String[] arg1, Class arg2) {
		System.out.println("convertFromString");                          
		//通常只会取第一个。             
		String firstValue = arg1[0];                          
		System.out.println(firstValue);                          
		StringTokenizer st = new StringTokenizer(firstValue, ",");
		String username = st.nextToken();             
		int age =Integer.parseInt( st.nextToken());
		myUser user = new myUser();                          
		user.setUsername(username);             
		user.setAge(age);                          
		return user;                      
	}      
	@Override     
	public String convertToString(Map arg0, Object arg1) {
		System.out.println("convertToString");                  
		myUser user = (myUser)arg1;                  
		String username = user.getUsername();         
		int age = user.getAge();                  
		String userInfo = "username: " + username + ", age: " + age;
		return userInfo;     
	}  
}

当然,运行前要记得在properties文件中,将

user333=com.tutorialspoint.sconvert.UserConverter改成

user333=com.tutorialspoint.sconvert.UserConverter2

全局转换器

----------------------------------

对于某些类型,需要在全局实现转换,则对单个action配置properties文件比较繁琐,struts提供了全局转换配置文件,只需在src目录下新建xwork-conversion.properties文件即可,在文件中依旧是键值对,

但是键名有变化,为具体的类型=对应类型转换器。此例中,内容即写为:

com.tutorialspoint.struts2.myUser=com.tutorialspoint.sconvert.UserConverter2,而实现转换逻辑的类依旧不变。