5.26日音訊,Struts2必須掌握的知識(shí)。Struts2是在WebWork2基礎(chǔ)發(fā)展而來(lái)的。和struts1一樣,Struts2也屬于MVC框架。一、Struts2類型轉(zhuǎn)換介紹
類型轉(zhuǎn)換:解析HTTP請(qǐng)求參數(shù),將Http請(qǐng)求參數(shù)賦值給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的屬性,類型轉(zhuǎn)換是指這個(gè)賦值過(guò)程中可能出現(xiàn)的類型不一致問(wèn)題而做出的轉(zhuǎn)換,因?yàn)镠TTP參數(shù)都是字符串類型的;因此從String類型的age參數(shù)傳給int類型的age屬性時(shí),就需要類型轉(zhuǎn)換,當(dāng)然這些struts2框架已經(jīng)做完了,開發(fā)人員不需要自行處理;
Struts2已經(jīng)內(nèi)建了對(duì)于String和基本類型的類型轉(zhuǎn)換,比如String<-->int、String<-->boolean等;
Action屬性一定要有g(shù)etter和setter方法!
Struts2提供了強(qiáng)大的類型轉(zhuǎn)換支持,不僅提供了內(nèi)置的類型轉(zhuǎn)換器,還可以自定義類型轉(zhuǎn)換器,以滿足自定義需求;
Struts2類型轉(zhuǎn)換是通過(guò)params攔截器進(jìn)行轉(zhuǎn)換;如果轉(zhuǎn)換失敗,則conversionError攔截器攔截該異常,并封裝到fieldError中,放入ActionContext中;
Struts2類型轉(zhuǎn)換還支持OGNL表達(dá)式,只需要在表單控件的name屬性使用ognl表達(dá)式即可,比如表單控件的name屬性為user.name,則此控件的數(shù)據(jù)將進(jìn)入賦值給Action的user屬性中的name屬性;
二、通過(guò)一個(gè)例子初步了解Struts2類型轉(zhuǎn)換
此處的類型轉(zhuǎn)換因?yàn)槭莾?nèi)建的,因此代碼上和原來(lái)的struts2應(yīng)用沒(méi)有不同,struts2框架內(nèi)部完成了所有了類型轉(zhuǎn)換,以下程序是將name、age賦值給Action類的name、age屬性,gender、salary賦值給p.gender、p.salary屬性;struts.xml的配置和原來(lái)一樣,所以就不給出了;
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表達(dá)式;
<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>
補(bǔ)充:List和Map的Action屬性的類型轉(zhuǎn)換問(wèn)題
前面我們將的都是基本類型和自定義類型,因此這里我們將講述集合類型的類型轉(zhuǎn)換問(wèn)題;
如果Action的屬性為L(zhǎng)ist類型,List<String>lists,則表單控件的命名方式為lists[i],如lists[0]表示第1個(gè)元素;
如果Action的屬性為Map類型,Map<String,Person>maps;則表單控件的命名方式為maps['first'].salary,表示map中key為'first'的value中的salary屬性;
以上的list和map類型屬性都通過(guò)泛型的方式說(shuō)明集合元素的類型,如果在JDK1.5之前,泛型沒(méi)有出現(xiàn),則需要通過(guò)局部類型轉(zhuǎn)換文件進(jìn)行表示;
局部類型轉(zhuǎn)換文件:對(duì)于特定Action的特定屬性有效,位于特定Action同一目錄下,命名規(guī)則:ActionName-conversion.properties;
對(duì)于List元素來(lái)說(shuō),內(nèi)容如:Element_attributeName=typeName;
對(duì)于Map元素來(lái)說(shuō),
(1)如果表示key的類型,則:Key_attributeName=typeName;
(2)如果表示value的類型,則為:Element_attributeName=typeName;
比如,此處沒(méi)有使用泛型,而是使用了局部類型轉(zhuǎn)換文件:
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
<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
三、自定義類型轉(zhuǎn)換器
1.繼承DefaultTypeConverter
如果我們自定義一個(gè)類型轉(zhuǎn)換器,第一種方法是繼承DefaultTypeConverter,并重寫publicObjectconvertValue(ActionContextcontext,Objectvalue,ClasstoType);
這個(gè)函數(shù)的功能是完成雙向轉(zhuǎn)換,即從String數(shù)組轉(zhuǎn)到Action屬性及Action屬性轉(zhuǎn)到String;需要注意的是從String數(shù)組轉(zhuǎn)到Action屬性,而不是String轉(zhuǎn)到Action屬性;如果只有一個(gè)字符串,則取params[0]即可;
因此一般此函數(shù)的模板代碼如下:
publicObjectconvertValue(Map<String,Object>context,Objectvalue,
ClasstoType){
if(toType==String.class){
......
returnString;
}
elseif(toType==Action屬性.class){
Stringparams[]=(String[])value;//必須是字符串?dāng)?shù)組
.......
returnAction屬性;
}
returnnull;
}
完成自定義類型轉(zhuǎn)換器編寫后,如果需要使用此轉(zhuǎn)換器,就需要配置,通常有兩種配置方法:
1.局部類型轉(zhuǎn)換文件中配置,僅對(duì)特定的Action的特定屬性有效,比如在Action1中有aa屬性,則僅對(duì)Action1的aa屬性有效;
2.全局類型轉(zhuǎn)換文件中配置,對(duì)某個(gè)類型都有效;比如對(duì)Person注冊(cè)了類型轉(zhuǎn)換器,則對(duì)任何Person和String的轉(zhuǎn)換都有效;
全局類型轉(zhuǎn)換文件命名為:xwork-conversion.properties,通常放在WEB-INF\classes下;
文件內(nèi)容如:attributeName=ConvertClass,比如aa=org.convert.Converter1
attributeName表示屬性名稱,convertClass表示轉(zhuǎn)換器的實(shí)現(xiàn)類;
局部類型轉(zhuǎn)換文件命名為:ActionName-conversion.properties,放在特定Action的目錄下;
文件內(nèi)容如:typeName=ConvertClass,比如org.person.Person=org.convert.Converter2
注意:typeName表示轉(zhuǎn)換類型,convertClass表示轉(zhuǎn)換器的實(shí)現(xiàn)類;
代碼示例:
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
pageEncoding="utf-8"%>
<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的類型轉(zhuǎn)換器是在一個(gè)函數(shù)中進(jìn)行雙向轉(zhuǎn)換,而繼承StrutsTypeConverter的類型轉(zhuǎn)換器則是將兩個(gè)方向分別用兩個(gè)函數(shù)實(shí)現(xiàn):
@Override
publicObjectconvertFromString(Mapcontext,String[]values,ClasstoClass){
}
@Override
publicStringconvertToString(Mapcontext,Objecto){
}