您的位置:首页 > 编程语言 > Java开发

五、Struts2之类型转换

2012-02-02 21:34 183 查看

一、Struts2类型转换介绍

类型转换:解析HTTP请求参数,将Http请求参数赋值给Action的属性;比如:

<s:formaction="valid"> <s:textfieldlabel="用户名"name="name"></s:textfield> <s:passwordlabel="密码"name="password"></s:password> <s:textfieldlabel="年龄"name="age"></s:textfield> <s:submitvalue="提交"></s:submit> </s:form>

此处将名为name、password、age的值赋值给Action的属性,类型转换是指这个赋值过程中可能出现的类型不一致问题而做出的转换,因为HTTP参数都是字符串类型的;因此从String类型的age参数传给int类型的age属性时,就需要类型转换,当然这些struts2框架已经做完了,开发人员不需要自行处理;

Struts2已经内建了对于String和基本类型的类型转换,比如String<-->int、String<-->boolean等;

Action属性一定要有getter和setter方法!

Struts2提供了强大的类型转换支持,不仅提供了内置的类型转换器,还可以自定义类型转换器,以满足自定义需求;

Struts2类型转换是通过params拦截器进行转换;如果转换失败,则conversionError拦截器拦截该异常,并封装到fieldError中,放入ActionContext中;

Struts2类型转换还支持OGNL表达式,只需要在表单控件的name属性使用ognl表达式即可,比如表单控件的name属性为user.name,则此控件的数据将进入赋值给Action的user属性中的name属性;

二、通过一个例子初步了解Struts2类型转换

此处的类型转换因为是内建的,因此代码上和原来的struts2应用没有不同,struts2框架内部完成了所有了类型转换,以下程序是将name、age赋值给Action类的name、age属性,gender、salary赋值给p.gender、p.salary属性;struts.xml的配置和原来一样,所以就不给出了;

Conversion01Action.java

packageorg.conversion.action; importorg.person.Person; importcom.opensymphony.xwork2.ActionSupport; publicclassConversion01ActionextendsActionSupport{ privateStringname; privateintage; privatePersonp; publicStringexecute()throwsException{ System.out.println(name); System.out.println(age); System.out.println(p.getGender()); System.out.println(p.getSalary()); returnSUCCESS; } publicStringgetName(){ returnname; } publicvoidsetName(Stringname){ this.name=name; } publicintgetAge(){ returnage; } publicvoidsetAge(intage){ this.age=age; } publicPersongetP(){ returnp; } publicvoidsetP(Personp){ this.p=p; } }

1.jsp

此处需要注意的是性别、薪水的表单控件的name属性是OGNL表达式;

<%@pagelanguage="java"contentType="text/html;charset=utf-8" pageEncoding="utf-8"%> <%@taglibprefix="s"uri="/struts-tags"%> <!DOCTYPEhtmlPUBLIC"-//W3C//DTDHTML4.01Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <metahttp-equiv="Content-Type"content="text/html;charset=utf-8"> <title>Inserttitlehere</title> </head> <body> <s:fielderror></s:fielderror> <s:formaction="conversion01"> <s:textfieldlabel="姓名"name="name"></s:textfield> <s:textfieldlabel="年龄"name="age"></s:textfield> <s:textfieldlabel="性别"name="p.gender"></s:textfield> <s:textfieldlabel="薪水"name="p.salary"></s:textfield> <s:submitvalue="提交"></s:submit> </s:form> </body> </html>

补充:List和Map的Action属性的类型转换问题

前面我们将的都是基本类型和自定义类型,因此这里我们将讲述集合类型的类型转换问题;
如果Action的属性为List类型,List<String>lists,则表单控件的命名方式为lists[i],如lists[0]表示第1个元素;
如果Action的属性为Map类型,Map<String,Person>maps;则表单控件的命名方式为maps['first'].salary,表示map中key为'first'的value中的salary属性;

以上的list和map类型属性都通过泛型的方式说明集合元素的类型,如果在JDK1.5之前,泛型没有出现,则需要通过局部类型转换文件进行表示;

局部类型转换文件:对于特定Action的特定属性有效,位于特定Action同一目录下,命名规则:ActionName-conversion.properties;

对于List元素来说,内容如:Element_attributeName=typeName;
对于Map元素来说,
(1)如果表示key的类型,则:Key_attributeName=typeName;
(2)如果表示value的类型,则为:Element_attributeName=typeName;

比如,此处没有使用泛型,而是使用了局部类型转换文件:

Conversion02Action.java
packageorg.conversion.action; importjava.util.List; importjava.util.Map; importorg.person.Person; importcom.opensymphony.xwork2.ActionSupport; publicclassConversion02ActionextendsActionSupport{ privateListlists; privateMapmaps; publicStringexecute()throwsException{ System.out.println(((Person)lists.get(0)).getGender()); System.out.println(((Person)lists.get(0)).getSalary()); System.out.println(((Person)maps.get("one")).getGender()); System.out.println(((Person)maps.get("one")).getSalary()); returnSUCCESS; } publicListgetLists(){ returnlists; } publicvoidsetLists(Listlists){ this.lists=lists; } publicMapgetMaps(){ returnmaps; } publicvoidsetMaps(Mapmaps){ this.maps=maps; } }

Conversion02Action-conversion.properties

Element_lists=org.person.Person Key_maps=java.lang.String Element_maps=org.person.Person

2.jsp

<%@pagelanguage="java"contentType="text/html;charset=utf-8" pageEncoding="utf-8"%> <%@taglibprefix="s"uri="/struts-tags"%> <!DOCTYPEhtmlPUBLIC"-//W3C//DTDHTML4.01Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <metahttp-equiv="Content-Type"content="text/html;charset=utf-8"> <title>Inserttitlehere</title> </head> <body> <s:fielderror></s:fielderror> <s:formaction="conversion02"> <s:textfieldlabel="list1.salary"name="lists[0].salary"></s:textfield> <s:textfieldlabel="list1.gender"name="lists[0].gender"></s:textfield> <s:textfieldlabel="map1.gender"name="maps['one'].gender"></s:textfield> <s:textfieldlabel="map1.salary"name="maps['one'].salary"></s:textfield> <s:submitvalue="提交"></s:submit> </s:form> </body> </html>

Conversion02Action-conversion.properties

Element_lists=org.person.Person
Key_maps=java.lang.String
Element_maps=org.person.Person


三、自定义类型转换器

1.继承DefaultTypeConverter

如果我们自定义一个类型转换器,第一种方法是继承DefaultTypeConverter,并重写publicObject
convertValue(ActionContextcontext,Objectvalue,ClasstoType);

这个函数的功能是完成双向转换,即从String数组转到Action属性及Action属性转到String;需要注意的是从String数组转到Action属性,而不是String转到Action属性;如果只有一个字符串,则取params[0]
即可;


因此一般此函数的模板代码如下:

publicObjectconvertValue(Map<String,Object>context,Objectvalue,
ClasstoType){
if(toType==String.class){
......
returnString;
}
elseif(toType==Action属性.class){
Stringparams[]=(String[])value;//必须是字符串数组
.......
returnAction属性;
}
returnnull;
}

完成自定义类型转换器编写后,如果需要使用此转换器,就需要配置,通常有两种配置方法:
1.局部类型转换文件中配置,仅对特定的Action的特定属性有效,比如在Action1中有aa属性,则仅对Action1的aa属性有效;
2.全局类型转换文件中配置,对某个类型都有效;比如对Person注册了类型转换器,则对任何Person和String的转换都有效;

全局类型转换文件命名为:xwork-conversion.properties,通常放在WEB-INF\classes下;
文件内容如:attributeName=ConvertClass,比如aa=org.convert.Converter1
attributeName表示属性名称,convertClass表示转换器的实现类;

局部类型转换文件命名为:ActionName-conversion.properties,放在特定Action的目录下;
文件内容如:typeName=ConvertClass,比如org.person.Person=org.convert.Converter2

注意:typeName表示转换类型,convertClass表示转换器的实现类;

代码示例:

Conversion03Action.java

packageorg.conversion.action;

importorg.person.Person;

importcom.opensymphony.xwork2.ActionSupport;

publicclassConversion03ActionextendsActionSupport{

privatePersonp;
publicStringexecute()throwsException{
System.out.println(p.getGender());
System.out.println(p.getSalary());
returnSUCCESS;
}
publicPersongetP(){
returnp;
}
publicvoidsetP(Personp){
this.p=p;
}

}


Converter01.java

packageorg.converter;

importjava.util.Map;

importorg.person.Person;

importcom.opensymphony.xwork2.conversion.impl.DefaultTypeConverter;

publicclassConverter01extendsDefaultTypeConverter{

@Override
publicObjectconvertValue(Map<String,Object>context,Objectvalue,
ClasstoType){
if(toType==String.class){
Personp=(Person)value;
returnp.getSalary()+","+p.getGender();
}
elseif(toType==Person.class){
Stringparams[]=(String[])value;
String[]values=params[0].split("\\,");
Personp=newPerson();
p.setGender(values[1]);
p.setSalary(Double.parseDouble(values[0]));
returnp;
}
returnnull;
}

}

3.jsp

<%@pagelanguage="java"contentType="text/html;charset=utf-8"
pageEncoding="utf-8"%>
<%@taglibprefix="s"uri="/struts-tags"%>
<!DOCTYPEhtmlPUBLIC"-//W3C//DTDHTML4.01Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<metahttp-equiv="Content-Type"content="text/html;charset=utf-8">
<title>Inserttitlehere</title>
</head>
<body>
<s:fielderror></s:fielderror>
<s:formaction="conversion03">
<s:textfieldlabel="薪水,性别"name="p"></s:textfield>
<s:submitvalue="提交"></s:submit>
</s:form>
</body>
</html>

Conversion03Action-conversion.properties

p=org.convert.Converter01



2.继承StrutsTypeConverter

StrutsTypeConverter是DefaultTypeConverter的子类,DefaultTypeConverter的类型转换器是在一个函数中进行双向转换,而继承StrutsTypeConverter的类型转换器则是将两个方向分别用两个函数实现:

@Override
publicObjectconvertFromString(Mapcontext,String[]values,ClasstoClass){

}

@Override
publicStringconvertToString(Mapcontext,Objecto){

}


将DefaultTypeConverter中的Converter01换成如下代码就可以完成StrutsTypeConverter的类型转换器;

packageorg.converter;

importjava.util.Map;

importorg.apache.struts2.util.StrutsTypeConverter;
importorg.person.Person;

publicclassConverter02extendsStrutsTypeConverter{

@Override
publicObjectconvertFromString(Mapcontext,String[]value,ClasstoClass){
Stringparams[]=(String[])value;
String[]values=params[0].split("\\,");
Personp=newPerson();
p.setGender(values[1]);
p.setSalary(Double.parseDouble(values[0]));
returnp;
}

@Override
publicStringconvertToString(Mapcontext,Objecto){
Personp=(Person)o;
returnp.getSalary()+","+p.getGender();
}
}

xwork-conversion.properties

org.person.Person=org.converter.Converter02

四、错误处理机制

客户输入错误信息是很正常的事,因此需要对此种行为进行处理,Struts2提供了很好的错误处理机制,是由conversionError拦截器自动完成,我们只需要配置输出什么错误信息即可;
当发生类型转换错误时,conversionError拦截器拦截此错误,并封装成fieldError,将此错误信息放入ActionContext中,并返回input逻辑视图;当然在<action>元素中必须配一个类似于<result
name="input">/1.jsp</result>的子元素,以应对类型转换错误;
而为了显示错误信息,则在jsp页面中使用<s:fielderror/>即可显示错误信息;
注意:类型转换的Action在struts.xml中配置所在包需要extends="struts-default",因此在此文件中包含conversionError拦截器;

这时我们需要配置显示的错误信息,错误信息配置方式有两种:

1.配置默认提示信息

国际化资源文件中配置形如:
xwork.default.invalid.fieldvalue={0},错误;
{0}代表类型转换错误的属性名称;

2.配置Action特定属性错误信息

Action范围的国际化资源文件中配置形如:
invalid.fieldvalue.attributeName=内容
attributeName是Action中的属性名称;

我们在上面的程序中添加类型转换错误的消息:

在Conversion04Action_zh_CN.properties中添加:

invalid.fieldvalue.p=person类型转换错误;

意思是对p属性配置了特定的错误提示信息,当p属性类型转换错误后就会显示此信息;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: