類型轉(zhuǎn)換:將jsp頁面的請求參數(shù)進行類型的轉(zhuǎn)換后再賦值給action的屬性
Struts2已經(jīng)內(nèi)建了對于String和基本類型的類型轉(zhuǎn)換,比如String<-->int 、String<-->boolean等;
Action屬性一定要有g(shù)etter和setter方法!
Struts2提供了強大的類型轉(zhuǎn)換支持,不僅提供了內(nèi)置的類型轉(zhuǎn)換器,還可以自定義類型轉(zhuǎn)換器,以滿足自定義需求;
Struts2類型轉(zhuǎn)換是通過 params攔截器進行轉(zhuǎn)換;如果轉(zhuǎn)換失敗,則 conversionError攔截器攔截該異常,并封裝到fieldError中,放入ActionContext中;
Struts2類型轉(zhuǎn)換還支持OGNL表達式,只需要在表單控件的name屬性使用ognl表達式即可,比如表單控件的name屬性為user.name,則此控件的數(shù)據(jù)將進入賦值給Action的user屬性中的name屬性;
一、struts2自帶的類型轉(zhuǎn)換
1、普通的string->int類型的轉(zhuǎn)換
參數(shù)請求頁面:
<%@ taglib prefix="s" uri="/struts-tags" %>
<%--
Created by IntelliJ IDEA.
User: yangcs
Date: 2017/2/6
Time: 14:59
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>類型轉(zhuǎn)換器</title>
</head>
<body>
使用struts2自帶的類型轉(zhuǎn)換器對jsp數(shù)據(jù)類型進行轉(zhuǎn)換(注意使用了OGNL表達式和struts標(biāo)簽)<br>
后面要對這樣的帶有非String類型的數(shù)據(jù)輸入進行校驗操作<br>
具體效果可以看后臺<br>
<s:form action="Action008">
<s:textfield label="姓名" name="name"></s:textfield>
<s:textfield label="密碼" name="password"></s:textfield>
<s:textfield label="年齡" name="p.age"></s:textfield>
<s:textfield label="薪水" name="p.salary"></s:textfield>
<s:submit value="提交"></s:submit>
</s:form>
</body>
</html>
接受參數(shù)的action:
package test002;
import Dao.Person;
import com.opensymphony.xwork2.ActionSupport;
/**
* Created by yangcs on 2017/2/6.
* 使用struts2自帶類型轉(zhuǎn)換器轉(zhuǎn)換類型示例action
*/
public class TypeExchangeAction extends ActionSupport{
private String name;
private int password;
private Person p;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPassword() {
return password;
}
public void setPassword(int password) {
this.password = password;
}
public Person getP() {
return p;
}
public void setP(Person p) {
this.p = p;
}
public String execute(){
System.out.println(name);
System.out.println(password);
System.out.println(p.getAge());
System.out.println(p.getSalary());
return SUCCESS;
}
}
結(jié)果展示頁面:
<%@ taglib prefix="s" uri="/struts-tags" %>
<%--
Created by IntelliJ IDEA.
User: yangcs
Date: 2017/2/6
Time: 14:59
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>類型轉(zhuǎn)換器</title>
</head>
<body>
使用struts2自帶的類型轉(zhuǎn)換器對jsp數(shù)據(jù)類型進行轉(zhuǎn)換(注意使用了OGNL表達式和struts標(biāo)簽)<br>
后面要對這樣的帶有非String類型的數(shù)據(jù)輸入進行校驗操作<br>
具體效果可以看后臺<br>
<s:form action="Action008">
<s:textfield label="姓名" name="name"></s:textfield>
<s:textfield label="密碼" name="password"></s:textfield>
<s:textfield label="年齡" name="p.age"></s:textfield>
<s:textfield label="薪水" name="p.salary"></s:textfield>
<s:submit value="提交"></s:submit>
</s:form>
</body>
</html>
2、當(dāng)輸入集合類型的參數(shù)時的轉(zhuǎn)換
如果Action的屬性為List類型,List<String>lists ,則表單控件的命名方式為 lists[i] ,如 lists[0]表示第1個元素;
如果Action的屬性為Map類型,Map<String,Person> maps;則表單控件的命名方式為maps[ ' first ' ].salary ,表示map中key為'first'的value中的salary屬性;
參數(shù)請求頁面:
<%@ taglib prefix="s" uri="/struts-tags" %>
<%--
Created by IntelliJ IDEA.
User: yangcs
Date: 2017/2/6
Time: 16:28
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>類型轉(zhuǎn)換</title>
</head>
<body>
<s:form action="Action009">
<s:textfield label="姓名" name="lists[0].name"></s:textfield>
<s:textfield label="密碼" name="lists[0].password"></s:textfield>
<s:textfield label="年齡" name="map['first'].age"></s:textfield>
<s:textfield label="薪水" name="map['first'].salary"></s:textfield>
<s:submit value="提交"></s:submit>
</s:form>
</body>
</html>
后臺接受參數(shù)的action:
package test002;
import Dao.Person;
import Dao.User;
import com.opensymphony.xwork2.ActionSupport;
import java.util.List;
import java.util.Map;
/**
* Created by yangcs on 2017/2/6.
* 這個action是使用類型轉(zhuǎn)換成list和map類型的數(shù)據(jù)的示例
*/
public class TypeExchangeAction02 extends ActionSupport{
//public List<String> lists; //這個地方不能定義為private???
public List<User> lists; //定義為private還是不行啊!
private Map<String, Person> map;
public List<User> getLists() {
return lists;
}
public void setList(List<User> lists) {
this.lists = lists;
}
public Map<String, Person> getMap() {
return map;
}
public void setMap(Map<String, Person> map) {
this.map = map;
}
public String execute() throws Exception{
System.out.println(lists.get(0).getName());
System.out.println(lists.get(0).getPassword());
System.out.println(map.get("first").getAge());
System.out.println(map.get("first").getSalary());
return SUCCESS;
}
}
結(jié)果展示頁面:
<%@ taglib prefix="s" uri="/struts-tags" %>
<%--
Created by IntelliJ IDEA.
User: yangcs
Date: 2017/2/6
Time: 16:39
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>類型轉(zhuǎn)換結(jié)果</title>
</head>
<body>
姓名:<s:property value="lists[0].getName()"></s:property><br>
密碼:<s:property value="lists[0].getPassword()"></s:property><br>
年齡:<s:property value="map['first'].getAge()"></s:property><br>
薪水:<s:property value="map['first'].getSalary()"></s:property>
</body>
</html>
二、自定義類型轉(zhuǎn)換器
1.繼承DefaultTypeConverter
如果我們自定義一個類型轉(zhuǎn)換器,第一種方法是繼承DefaultTypeConverter,并重寫 public Object convertValue(ActionContext context,Object value,Class toType);
這個函數(shù)的功能是完成雙向轉(zhuǎn)換,即從String數(shù)組轉(zhuǎn)到Action屬性及Action屬性轉(zhuǎn)到String;需要注意的是從String數(shù)組轉(zhuǎn)到Action屬性,而不是String轉(zhuǎn)到Action屬性;如果只有一個字符串,則取params[0] 即可;
因此一般此函數(shù)的模板代碼如下:
public Object convertValue(Map<String, Object> context, Object value,
Class toType) {
if(toType==String.class){
......
return String;
}
else if(toType==Action屬性.class){
String params[] = (String[])value;//必須是字符串?dāng)?shù)組
.......
return Action屬性;
}
return null;
}
完成自定義類型轉(zhuǎn)換器編寫后,如果需要使用此轉(zhuǎn)換器,就需要配置,通常有兩種配置方法:
1.局部類型轉(zhuǎn)換文件中配置,僅對特定的Action的特定屬性有效,比如在Action1中有aa屬性,則僅對Action1的aa屬性有效;
2.全局類型轉(zhuǎn)換文件中配置,對某個類型都有效;比如對Person注冊了類型轉(zhuǎn)換器,則對任何Person和String的轉(zhuǎn)換都有效;
全局類型轉(zhuǎn)換文件命名為: xwork-conversion.properties,通常放在WEB-INF\classes下;
文件內(nèi)容如:attributeName=ConvertClass ,比如org.person.Person = org.convert.Converter2
attributeName表示屬性名稱, convertClass表示轉(zhuǎn)換器的實現(xiàn)類;
局部類型轉(zhuǎn)換文件命名為:ActionName-conversion.properties,放在特定Action的目錄下;
文件內(nèi)容如: typeName=ConvertClass,比如aa=org.convert.Converter1
注意:typeName表示轉(zhuǎn)換類型,convertClass表示轉(zhuǎn)換器的實現(xiàn)類;
代碼示例:
Conversion03Action.java
package org.conversion.action;
import org.person.Person;
import com.opensymphony.xwork2.ActionSupport;
public class Conversion03Action extends ActionSupport {
private Person p ;
public String execute()throws Exception{
System.out.println(p.getGender());
System.out.println(p.getSalary());
return SUCCESS;
}
public Person getP() {
return p;
}
public void setP(Person p) {
this.p = p;
}
}
Converter01.java
package org.converter;
import java.util.Map;
import org.person.Person;
import com.opensymphony.xwork2.conversion.impl.DefaultTypeConverter;
public class Converter01 extends DefaultTypeConverter {
@Override
public Object convertValue(Map<String, Object> context, Object value,
Class toType) {
if(toType==String.class){
Person p = (Person)value;
return p.getSalary()+","+p.getGender();
}
else if(toType==Person.class){
String params[] = (String[])value;
String[]values = params[0].split("\\,");
Person p = new Person();
p.setGender(values[1]);
p.setSalary(Double.parseDouble(values[0]));
return p;
}
return null;
}
}
3.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:fielderror></s:fielderror>
<s:form action="conversion03" >
<s:textfield label="薪水,性別" name="p"></s:textfield>
<s:submit value="提交"></s:submit>
</s:form>
</body>
</html>
Conversion03Action-conversion.properties
p=org.convert.Converter01
2.繼承StrutsTypeConverter
StrutsTypeConverter是DefaultTypeConverter的子類,DefaultTypeConverter的類型轉(zhuǎn)換器是在一個函數(shù)中進行雙向轉(zhuǎn)換,而繼承StrutsTypeConverter的類型轉(zhuǎn)換器則是將兩個方向分別用兩個函數(shù)實現(xiàn):
@Override
public Object convertFromString(Map context, String[] values, Class toClass) {
}
@Override
public String convertToString(Map context, Object o) {
}
將DefaultTypeConverter中的Converter01換成如下代碼就可以完成StrutsTypeConverter的類型轉(zhuǎn)換器;
package org.converter;
import java.util.Map;
import org.apache.struts2.util.StrutsTypeConverter;
import org.person.Person;
public class Converter02 extends StrutsTypeConverter {
@Override
public Object convertFromString(Map context, String[] value, Class toClass) {
String params[] = (String[])value;
String[]values = params[0].split("\\,");
Person p = new Person();
p.setGender(values[1]);
p.setSalary(Double.parseDouble(values[0]));
return p;
}
@Override
public String convertToString(Map context, Object o) {
Person p = (Person)o;
return p.getSalary()+","+p.getGender();
}
}
xwork-conversion.properties
org.person.Person=org.converter.Converter02
三、錯誤處理機制
客戶輸入錯誤信息是很正常的事,因此需要對此種行為進行處理,Struts2提供了很好的錯誤處理機制,是由conversionError攔截器自動完成,我們只需要配置輸出什么錯誤信息即可;
當(dāng)發(fā)生類型轉(zhuǎn)換錯誤時,conversionError攔截器攔截此錯誤,并封裝成fieldError,將此錯誤信息放入ActionContext中,并返回input邏輯視圖;當(dāng)然在<action>元素中必須配一個類似于<result name="input">/1.jsp</result>的子元素,以應(yīng)對類型轉(zhuǎn)換錯誤;
而為了顯示錯誤信息,則在jsp頁面中使用<s:fielderror/>即可顯示錯誤信息;
注意:類型轉(zhuǎn)換的Action在struts.xml中配置所在包需要extends="struts-default",因此在此文件中包含conversionError攔截器;
這時我們需要配置顯示的錯誤信息,錯誤信息配置方式有兩種:
1.配置默認提示信息
在國際化資源文件中配置形如:
xwork.default.invalid.fieldvalue={0},錯誤;
{0}代表類型轉(zhuǎn)換錯誤的屬性名稱;
2.配置Action特定屬性錯誤信息
在Action范圍的國際化資源文件中配置形如:
invalid.fieldvalue.attributeName= 內(nèi)容
attributeName是Action中的屬性名稱;
我們在上面的程序中添加類型轉(zhuǎn)換錯誤的消息:
在Conversion04Action_zh_CN.properties中添加:
<span style="font-family:'Microsoft YaHei';">invalid.fieldvalue.p=person類型轉(zhuǎn)換錯誤;</span>
意思是對p屬性配置了特定的錯誤提示信息,當(dāng)p屬性類型轉(zhuǎn)換錯誤后就會顯示此信息;