MVC框架具有將字符串請求參數(shù)轉(zhuǎn)換為響應(yīng)數(shù)據(jù)類型的功能,而Struts2.0作為MVC框架的實(shí)現(xiàn)者,理所當(dāng)然提供了類型轉(zhuǎn)換機(jī)制,概述如下:
HTTP沒有“類型”的概念,表單輸入的只可能是字符串或字符串?dāng)?shù)組;Struts2從表單到Action對象的類型轉(zhuǎn)換即是從字符串到非字符串的;Struts2的params攔截器在將請求參數(shù)映射到Action對象屬性時(shí),可自動完成字符串和基本數(shù)據(jù)類型間的轉(zhuǎn)換。ConversionError攔截器作為默認(rèn)攔截器棧的一員,負(fù)責(zé)添加與類型轉(zhuǎn)換有關(guān)的出錯(cuò)消息(前提是Action類實(shí)現(xiàn)了ValidationAware接口)和保存各請求參數(shù)的原始值。 若字段標(biāo)簽使用非simple主題,則類型轉(zhuǎn)換錯(cuò)誤消息為:”Invalid field value for field fieldName”。
如果類型轉(zhuǎn)換發(fā)生錯(cuò)誤,則
若Action類未實(shí)現(xiàn)ValidationAware接口:Struts2發(fā)生類型轉(zhuǎn)換錯(cuò)誤時(shí),仍會繼續(xù)調(diào)用其Action方法,就好像什么都沒發(fā)生一樣;若Action類實(shí)現(xiàn)了ValidationAware接口:Struts2發(fā)生類型轉(zhuǎn)換錯(cuò)誤時(shí),不會繼續(xù)調(diào)用其Action方法;而將檢查相關(guān)action元素的聲明是否包含name=input的result元素,若有則將控制權(quán)轉(zhuǎn)交給該元素,否則拋出異常。注意:可以直接繼承于實(shí)現(xiàn)了ValidationAware接口的ActionSupport類來代替實(shí)現(xiàn)ValidationAware接口。如果表單是simple主題,則不會自動顯示錯(cuò)誤消息。解決方案如下:
使用EL或OGNL表達(dá)式顯示:${fieldErrors.age[0]},即通過debug標(biāo)簽可知,類型轉(zhuǎn)換出錯(cuò)時(shí)在值棧的Action對象中有一個(gè)類型為Map<String, List<String>>的fieldErrors屬性;使用s:fielderror標(biāo)簽來顯示:<s:fielderror fieldName="fieldname"></s:fielderror>,即使用其fieldName屬性顯示指定字段的錯(cuò)誤信息。 問題:若是simple主題,且用s:fielderror標(biāo)簽來顯示錯(cuò)誤消息,則該消息包含在一個(gè)ul、li、span中,影響頁面排版,如何去除?
在src下新建template.simple包,并新建fielderror.ftl文件;將Struts2核心包/template/simple/fielderror.ftl文件內(nèi)容復(fù)制到新建fielderror.ftl文件中;剔除掉影響頁面排版的ul、li、span部分即可。因?yàn)镾truts2不能自動完成字符串到非基本數(shù)據(jù)類型的轉(zhuǎn)換,故需要定制類型轉(zhuǎn)換器,主要包括開發(fā)類型轉(zhuǎn)換器類和配置類型轉(zhuǎn)換器兩部分;具體如下:
自定義類型轉(zhuǎn)換器必須實(shí)現(xiàn)ongl.TypeConverter接口或該接口某種具體實(shí)現(xiàn)類進(jìn)行擴(kuò)展,常擴(kuò)展StrutsTypeConverter類即可。
(1)基于字段的配置 該方式可以為某Model類(可能是Action也可能是javaBean) 的各個(gè)屬性分別配置一個(gè)自定義類型轉(zhuǎn)換器;配置方法如下:
新建屬性文件ModelClassName-conversion.properties,放在Model類所在包下;添加鍵值對:字段名=類型轉(zhuǎn)換器的全類名;注意:第一次使用該轉(zhuǎn)換器時(shí)即創(chuàng)建實(shí)例(單實(shí)例的)……(2)基于類型的配置 該方式為整個(gè)應(yīng)用中所有Model類的各個(gè)屬性均配置同一個(gè)自定義類型轉(zhuǎn)換器,配置方法如下:
在src目錄下新建xwork-conversion.properties文件;添加鍵值對:待轉(zhuǎn)換的類型=類型轉(zhuǎn)換器的全類名;注意:在當(dāng)前Struts2應(yīng)用被加載時(shí)創(chuàng)建實(shí)例(創(chuàng)建兩次)……要求:時(shí)間pattern需要以web應(yīng)用初始化參數(shù)的形式配置在web.xml中,且當(dāng)類型轉(zhuǎn)換失敗給出自定義信息。 web.xml中配置初始化參數(shù)如下:
<context-param> <param-name>pattern</param-name> <param-value>yyyy-mm-dd hh:mm:ss</param-value></context-param>類型轉(zhuǎn)換器DateConverter.java代碼如下:
package com.qiaobc.struts.converter;import java.text.DateFormat;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Map;import javax.servlet.ServletContext;import org.apache.struts2.ServletActionContext;import org.apache.struts2.util.StrutsTypeConverter;public class DateConverter extends StrutsTypeConverter { private DateFormat dateFormat; public DateConverter() { System.out.println("DateConverter..."); // 獲取應(yīng)用程序的初始化參數(shù) /** * 基于字段的配置采用如下方法獲取初始化參數(shù),因其在第一次使用類型轉(zhuǎn)換器時(shí)創(chuàng)建實(shí)例 */ // ServletContext servletContext = ServletActionContext.getServletContext(); // String dateStr = servletContext.getInitParameter("pattern"); // dateFormat = new SimpleDateFormat(dateStr); } /** * 基于類型的配置采用如下方法獲取初始化參數(shù),因其在應(yīng)用加載時(shí)即創(chuàng)建實(shí)例 */ public DateFormat getdDateFormat() { if(dateFormat == null) { ServletContext servletContext = ServletActionContext.getServletContext(); String dateStr = servletContext.getInitParameter("pattern"); dateFormat = new SimpleDateFormat(dateStr); } return dateFormat; } @Override public Object convertFromString(Map context, String[] values, Class toClass) { System.out.println("convertFromString..."); if(toClass == Date.class) { if(values != null && values.length > 0) { // 將values[0]轉(zhuǎn)換為Date型 try { // 基于字段的配置采用如下方法 // return dateFormat.parse(values[0]); // 基于類型的配置采用如下方法 return getdDateFormat().parse(values[0]); } catch (ParseException e) { e.printStackTrace(); } } } // 未轉(zhuǎn)換成功則返回values return values; } @Override public String convertToString(Map context, Object o) { System.out.println("convertToString..."); if(o instanceof Date) { Date date = (Date) o; return dateFormat.format(date); } // 未轉(zhuǎn)換成功則返回null return null; }} 類型轉(zhuǎn)換器與復(fù)雜屬性協(xié)同使用的基本原理圖如下所示:
類型轉(zhuǎn)換器與集合協(xié)同使用的基本原理圖如下所示: 
新聞熱點(diǎn)
疑難解答