一、國際化
準備資源文件,資源文件的命名格式如下:
baseName_language_country.properties
baseName_language.properties
baseName.properties
其中baseName是資源檔案的基本名,我們可以自訂,但language和country必須是java支援的語言和國家。如:
中國大陸: baseName_zh_CN.properties
美國: baseName_en_US.properties
現在為應用程式新增兩個資源檔案:
第一個存放中文:csdn_zh_CN.properties
內容為:welcome=歡迎來到傳智播客第二個存放英文(美國): csdn_en_US.properties
內容為: welcome=welcome to csdn
對於中文的屬性文件,我們寫好後,應該要用jdk提供的native2ascii指令把文件轉換成unicode編碼的文件。指令的使用方式如下:
native2ascii 原始檔.properties 目標檔.properties
二、配置全域資源與輸出國際化訊息
當準備好資源文件之後,我們可以在struts.xml中透過struts.custom.i18n.resources常數把資源文件定義為全域資源文件,如下:
<constant name="struts.custom.i18n.resources" value=“csdn" />
csdn為資源檔案的基本名稱。
後面我們就可以在頁面或在action中存取國際化資訊:
在JSP頁面中使用<s:text name=“”/>標籤輸出國際化資訊:
<s:text name=“user”/>,name為資源檔案中的key
在Action類別中,可以繼承ActionSupport,使用getText()方法得到國際化訊息,該方法的第一個參數用來指定資源檔案中的key。
在表單標籤中,透過key屬性指定資源檔案中的key,如:
<s:textfield name="realname" key="user"/>
三、國際化―輸出帶佔位符的國際化訊息
資源文件中的內容如下:
welcome= {0},歡迎來到傳智播客{1}
在jsp頁面中輸出帶佔位符的國際化訊息
<s:text name="welcome">
<s:param><s:property value="realname"/></s:param>
<s:param>學習</s:param>
</s:text>
在Action類別中取得帶有佔位符的國際化訊息,可以使用getText(String key, String[] args)或getText(String aTextName, List args)方法。
四、國際化―包範圍資源文件
在一個大型應用程式中,整個應用程式有大量的內容需要實現國際化,如果我們把國際化的內容都放置在全局資源屬性文件中,顯然會導致資源文件變的過於龐大、臃腫,不便於維護,這個時候我們可以針對不同模組,使用包範圍來組織國際化文件。
方法如下:
在java的套件下放置package_language_country.properties資源文件,package為固定寫法,處於該套件及子包下的action都可以存取該資源。當尋找指定key的訊息時,系統會先從package資源檔案尋找,當找不到對應的key時,才會從常數struts.custom.i18n.resources指定的資源檔案中尋找。
五、國際化―Action範圍資源文件
我們也可以為某個action單獨指定資源文件,方法如下:
在Action類別所在的路徑,放置ActionClassName_language_country.properties資源文件,ActionClassName為action類別的簡單名稱。
當尋找指定key的訊息時,系統會先從ActionClassName_language_country.properties資源檔案中尋找,如果沒有找到對應的key,然後沿著目前套件往上尋找基本名為package 的資源文件,一直找到最頂層套件。如果還沒找到對應的key,最後會從常數struts.custom.i18n.resources指定的資源檔案中尋找。
六、國際化―JSP中直接存取某個資源文件
struts2為我們提供了<s:i18n>標籤,使用<s:i18n>標籤我們可以在類路徑下直接從某個資源文件中獲取國際化數據,而無需任何配置:
<s:i18n name=「csdn">
<s:text name=“welcome”/>
</s:i18n>
csdn為類別路徑下資源檔案的基本名稱。
如果要存取的資源檔案在類別路徑的某個套件下,可以這樣存取:
<s:i18n name=「cn/csdn/action/package">
<s:text name="welcome">
<s:param>小張</s:param>
</s:text>
</s:i18n>
上面存取cn.csdn.action套件下基本名為package的資源檔案。
七、OGNL表達式語言
OGNL是Object Graphic Navigation Language(物件圖導航語言)的縮寫,它是一個開源專案。 Struts 2框架使用OGNL作為預設的表達式語言。
相對EL表達式,它提供了平時我們需要的一些功能,如:
支援物件方法調用,如xxx.sayHello();
支援類別靜態方法呼叫和值訪問,表達式的格式為@[類別全名(包括套件路徑)]@[方法名稱| 值名],例如:@java.lang.String@format('foo %s' , 'bar')或@cn.csdn.Constant@APP_NAME;
操作集合物件。
Ognl 有一個上下文(Context)概念,說白了上下文就是一個MAP結構,它實現了java.utils.Map接口,在Struts2中上下文(Context)的實現為ActionContext,下面是上下文(Context)的結構示意圖
存取上下文(Context)中的物件需要使用#符號標註命名空間,如#application、#session
另外OGNL會設定一個根物件(root物件),在Struts2中根物件就是ValueStack(值堆疊) 。如果要存取根物件(即ValueStack)中物件的屬性,則可以省略#命名空間,直接存取該物件的屬性即可。
在struts2中,根物件ValueStack的實作類別為OgnlValueStack,該物件不是我們想像的只存放單一值,而是存放一組物件。在OgnlValueStack類別裡有一個List類型的root變量,就是使用他來存放一組對象
|--request
|--application
context ------|--OgnlValueStack root變數[action, OgnlUtil, ... ]
|--session
|--attr
|--parameters
在root變數中處於第一位的物件叫棧頂物件。通常我們在OGNL表達式裡直接寫上屬性的名稱即可存取root變數裡物件的屬性,搜尋順序是從棧頂物件開始尋找,如果棧頂物件不存在該屬性,就會從第二個物件尋找,如果沒有找到就從第三個物件尋找,依序往下訪問,直到找到為止。
大家注意: Struts2中,OGNL表達式需要配合Struts標籤才可以使用。如:<s:property value="name"/>
由於ValueStack(值棧)是Struts 2中OGNL的根對象,如果使用者需要存取值棧中的對象,在JSP頁面可以直接透過下面的EL表達式存取ValueStack(值棧)中對象的屬性:
${foo} //取得值堆疊中某個物件的foo屬性
如果訪問其他Context中的對象,由於他們不是根對象,所以在訪問時,需要添加#前綴。
application物件:用於存取ServletContext,例如#application.userName或#application['userName'],相當於呼叫ServletContext的getAttribute("username")。
session物件:用來存取HttpSession,例如#session.userName或#session['userName'],相當於呼叫session.getAttribute("userName")。
request物件:用來存取HttpServletRequest屬性(attribute)的Map,例如#request.userName或#request['userName'],相當於呼叫request.getAttribute("userName")。
parameters物件:用於存取HTTP的請求參數,例如#parameters.userName或#parameters['userName'],相當於呼叫request.getParameter("username")。
attr物件:用於按page->request->session->application順序存取其屬性。
八、為何使用EL表達式能夠存取valueStack中物件的屬性
原因是Struts2對HttpServletRequest作了進一步的封裝。簡略程式碼如下:
public class StrutsRequestWrapper extends HttpServletRequestWrapper {
public StrutsRequestWrapper(HttpServletRequest req) {
super(req);
}
public Object getAttribute(String s) {
.....
ActionContext ctx = ActionContext.getContext();
Object attribute = super.getAttribute(s);//先從request範圍取得屬性值
if (ctx != null) {
if (attribute == null) {//如果從request範圍沒有找到屬性值,即從ValueStack中尋找物件的屬性值
.....
ValueStack stack = ctx.getValueStack();
attribute = stack.findValue(s);
.....
}
}
return attribute;
}
}
九、採用OGNL表達式建立List/Map集合對象
如果需要一個集合元素的時候(例如List物件或Map物件),可以使用OGNL中同集合相關的表達式。
使用如下程式碼直接產生一個List物件:
<s:set name="list" value="{'zhangming','xiaoi','liming'}" />
<s:iterator value="#list" id="n">
<s:property value="n"/><br>
</s:iterator>
產生一個Map物件:
<s:set name="foobar" value="#{'foo1':'bar1', 'foo2':'bar2'}" />
<s:iterator value="#foobar" >
<s:property value="key"/>=<s:property value="value"/><br>
</s:iterator>
Set標籤用於將某個值放入指定範圍。
scope:指定變數被放置的範圍,該屬性可以接受application、session、request、 page或action。如果沒有設定該屬性,則預設放置在OGNL Context中。
value:賦給變數的值。如果沒有設定該屬性,則將ValueStack堆疊頂的值賦給變數。