7.類型轉(zhuǎn)換、消息處理與國際化

7.類型轉(zhuǎn)換、消息處理與國際化

@(10_Struts2)[JavaEE, Struts2]

  • 前邊我們說過了 Http協(xié)議 有兩個缺陷一個是無狀態(tài)、一個是純文本。
  • 純文本也就是說Http請求中的內(nèi)容都是以字符串的形式發(fā)送的。
  • 但是Java又是一個強(qiáng)類型語言,所以將一個字符串轉(zhuǎn)換成Java中的數(shù)據(jù)類型這一重任就落在了Struts2的肩膀上。
  • 類型轉(zhuǎn)換最常見的可能就是將將10/29/2015轉(zhuǎn)換為一個date類型等。
  • 關(guān)于類型轉(zhuǎn)換我們要做的主要有兩件事:
    • 類型轉(zhuǎn)換失敗后的處理。
    • 特殊類型的自定義類型轉(zhuǎn)換器。

類型轉(zhuǎn)換失敗消息處理

  • 類型轉(zhuǎn)換失敗
    • 若 Action 類沒有實現(xiàn) ValidationAware 接口: Struts 在遇到類型轉(zhuǎn)換錯誤時仍會繼續(xù)調(diào)用其 Action 方法, 就好像什么都沒發(fā)生一樣.

    • 若 Action 類實現(xiàn) ValidationAware 接口:Struts 在遇到類型轉(zhuǎn)換錯誤時將不會繼續(xù)調(diào)用其 Action 方法:

      • Struts 將檢查相關(guān) action 元素的聲明是否包含著一個 name=input 的 result.
      • 如果有, Struts 將把控制權(quán)轉(zhuǎn)交給那個 result 元素;
      • 若沒有 input 結(jié)果, Struts 將拋出一個異常
    • 實現(xiàn) ValidationAware 接口,在之前的文章中我們提到,我們可以繼承 com.opensymphony.xwork2.ActionSupport 類的形式來實現(xiàn) ValidationAware 接口, 在ActionSupport 中已經(jīng)幫我們實現(xiàn)好了


  • 類型轉(zhuǎn)換出錯時如何處理

    • 如果我們輸入錯誤的數(shù)字,想轉(zhuǎn)換為年齡;當(dāng)我們的 result name="input" 的時候,會返回到這個結(jié)果頁面。
    • 錯誤的年齡
    • 但是對于這種錯誤的提示,我們需要處理
  • 類型轉(zhuǎn)換錯誤消息的定制

    • 作為默認(rèn)的 default 攔截器的一員, ConversionError 攔截器負(fù)責(zé)添加與類型轉(zhuǎn)換有關(guān)的出錯消息(前提: Action 類必須實現(xiàn)了 ValidationAware 接口)和保存各請求參數(shù)的原始值.
    • 若字段標(biāo)簽使用的不是 simple 主題, 則非法輸入字段將導(dǎo)致一條有著如上圖格式的出錯消息。
  • 覆蓋默認(rèn)的出錯消息

    • 在對應(yīng)的 Action 類所在的包中新建 ActionClassName.properties 文件, ClassName 即為包含著輸入字段的 Action 類的類名
    • 在屬性文件中添加如下鍵值對: invalid.fieldvalue.fieldName=Customer Message
# EmployeeAction.properties
invalid.fieldvalue.age=年齡格式不正確,請重新輸入!
  • 自定義的消息
  • 定制出錯消息的樣式:

    • 每一條出錯消息都被打包在一個 HTML span 元素里, 可以通過覆蓋其行標(biāo)為 errorMessage 的那個 css 樣式來改變出錯消息的格式.
    • 顯示錯誤消息: 如果是 simple 主題, 可以通過 <s:fielderror fieldName=“filedname”></s:fielderror> 標(biāo)簽顯示錯誤消息
    • 通過s:fielderror 標(biāo)簽
<s:form action="emp_update" theme="simple">
    <s:hidden name="id"></s:hidden>
    姓名:<s:textfield name="name"></s:textfield> <br>
    年齡:<s:textfield name="age" ></s:textfield>
    <!-- 通過標(biāo)簽獲取錯誤消息 -->
    <span style="color:red"><s:fielderror fieldName="age"></s:fielderror></span><br>
    部門: <s:textfield name="dept"></s:textfield><br>
    職務(wù):<s:textfield name="role"></s:textfield><br>
    <s:submit value="修改"></s:submit>
</s:form>
  • 但是對于這種錯誤消息的格式我們是可以修改的,修改其默認(rèn)的 freemark 模板
  • struts2-core-2.3.15.3.jar 的 /template/simple/fielderror.ftl,這是 struts2 默認(rèn)自帶的錯誤消息模板,我們在 src 路徑下建立相同的包和模板,并且修改里面的 html 標(biāo)簽。刪除文件中錯誤消息的 的 ul、li、span便簽

![刪除的模板

  • 效果

自定義類型轉(zhuǎn)換器

  • 定制類型轉(zhuǎn)換器

  • 自定義類型轉(zhuǎn)換器必須實現(xiàn) ongl.TypeConverter 接口或?qū)@個接口的某種具體實現(xiàn)做擴(kuò)展

  • 擴(kuò)展 StrutsTypeConverter 類

    • 在大多數(shù)類型轉(zhuǎn)換器里, 需要提供從 String 類型到非 String 類型和與此相反的轉(zhuǎn)換功能
    • 在 StrutsTypeConverter 中有兩個抽象方法:
  • 配置自定義的類型轉(zhuǎn)換器

    • 在應(yīng)用程序里使用一個自定義的類型轉(zhuǎn)換器之前, 必須先對它進(jìn)行配置. 這種配置既可以基于字段, 也可以基于類型
    • 基于字段類型轉(zhuǎn)換配置-局部轉(zhuǎn)換器
      • 可以為某個 Model(該 Model 類也可能是 Action) 的各個屬性分別配置一個自定義的轉(zhuǎn)換器.
      • 創(chuàng)建一個屬性文件: ModelClassName-conversion.properties, 該文件需和相對應(yīng)的 Model(Model有可能是一個Action) 類放在同一個目錄下
      • fieldName=Converter全類名,例如: birth=org.pan.struts2.conver.DateConverter
    • 基于類型-全局轉(zhuǎn)換器
      • 在資源目錄下,src 或者 其他的 resources 創(chuàng)建 xwork-conversion.properties文件
      • xwork-conversion.properties 文件里把每一個需要進(jìn)行類型轉(zhuǎn)換的類與一個類型轉(zhuǎn)換器關(guān)聯(lián)起來
      • java.util.Date=org.pan.struts2.conver.DateConverter
      • 若類型轉(zhuǎn)換失敗,給出自定義的信息。

復(fù)雜屬性,集合協(xié)同工作

  • 復(fù)雜屬性
    • 類型轉(zhuǎn)換與復(fù)雜屬性配合使用
    • form 標(biāo)簽的 name 屬性可以被映射到一個屬性的屬性.
    • 復(fù)雜屬性
<s:form action="user_add">
    <s:textfield name="user.name" label="姓名"></s:textfield>
    <s:textfield name="user.gender" label="性別"></s:textfield>
    <s:textfield name="user.address" label="地址"></s:textfield>
    <s:textfield name="user.mgr.name" label="經(jīng)理名稱"></s:textfield>
    <s:textfield name="user.mgr.birth" label="經(jīng)理生日"></s:textfield>
    <s:submit value="添加"></s:submit>
</s:form>
  • 集合協(xié)同
    • 類型轉(zhuǎn)換與 Collection 配合使用

國際化

  • 概述

    • 在程序設(shè)計領(lǐng)域, 把在無需改寫源代碼即可讓開發(fā)出來的應(yīng)用程序能夠支持多種語言和數(shù)據(jù)格式的技術(shù)稱為國際化.
    • 與國際化對應(yīng)的是本地化, 指讓一個具備國際化支持的應(yīng)用程序支持某個特定的地區(qū)
    • Struts2 國際化是建立在 Java 國際化基礎(chǔ)上的:
    • 為不同國家/語言提供對應(yīng)的消息資源文件
      • Struts2 框架會根據(jù)請求中包含的
        • Locale 加載對應(yīng)的資源文件
      • 通過程序代碼取得該資源文件中
      • 指定 key 對應(yīng)的消息
  • 默認(rèn)攔截器棧中有一個i18n攔截器,這個攔截器用來設(shè)置當(dāng)前Locale信息

    • 當(dāng)i18n攔截器被調(diào)用時,他會先去查找request_locale這個請求參數(shù),它會根據(jù)干參數(shù)來創(chuàng)建一個Locale對象。并將Locale對象放入進(jìn)session域中。之后在加載國際化資源文件時就根據(jù)剛剛創(chuàng)建的Locale對象
  • 當(dāng)i18n攔截的請求中沒有request_locale這個參數(shù),

  • 它會先去session中獲取Locale對象,如果session中,則直接使用該對象

  • 如果session中沒有,則會根據(jù)用戶瀏覽器信息或本地服務(wù)器的信息去創(chuàng)建一個Locale對象并使用。

  • 配置國際化資源文件

    • Action 范圍資源文件:
      • 在Action類文件所在的路徑建立名為ActionName_language_country.properties 的文件
    • 包范圍資源文件:
      • 在包的根路徑下建立文件名為package_language_country.properties 的屬性文件,一旦建立,處于該包下的所有 Action 都可以訪問該資源文件。
      • 注意:包范圍資源文件的 baseName 就是package,不是Action所在的包名。
    • 全局資源文件
      • 命名方式: basename_language_country.properties
      • struts.xml <constant name="struts.custom.i18n.resources" value="baseName"/>
<!-- 配置國際化資源 -->
<constant name="struts.custom.i18n.resources" value="i18n"/>
  • 臨時指定資源文件:<s:i18n.../> 標(biāo)簽的 name 屬性指定臨時的國際化資源文件
  • 總結(jié):
    • 國際化資源文件加載的順序如何呢 ?
      • 離當(dāng)前 Action 較近的將被優(yōu)先加載.
    • 假設(shè)我們在某個 ChildAction 中調(diào)用了getText("username")
      • (1)加載和 ChildAction 的類文件在同一個包下的系列資源文件 ChildAction.properties
      • (2)加載 ChildAction 實現(xiàn)的接口 IChild,且和 IChildn 在同一個包下 IChild.properties 系列資源文件。
      • (3)加載 ChildAction 父類 Parent,且和 Parent 在同一個包下的 baseName 為 Parent.properties 系列資源文件。
      • (4) 若 ChildAction 實現(xiàn) ModelDriven 接口,則對于getModel()方法返回的model 對象,重新執(zhí)行第(1)步操作。
      • (5) 查找當(dāng)前包下 package.properties 系列資源文件。
      • (6) 沿著當(dāng)前包上溯,直到最頂層包來查找 package.properties 的系列資源文件。
      • (7) 查找 struts.custom.i18n.resources 常量指定 baseName 的系列資源文件。
      • (8) 直接輸出該key的字符串值。
  • Action 范圍國際化
  • package 范圍國際化
  • 全局的國際化
    • 首先需要去 struts.xml 中指定baseName
<!-- 指定國際化 baseName, 以便于建立全局的國際化資源文件 -->
<constant name="struts.custom.i18n.resources" value="myI18n"></constant>
  • 全局的配置
  • 在這還需要講到一種方式:在頁面國際化資源

    • 如果我們在資源路徑下建立好了 國際化資源,但是沒有在 struts.xml 中配置 baseName
    • 我們可以使用 <s:i18n name="baseName"> 標(biāo)簽來獲取
    <!-- 如果是配置了頁面國際化資源文件,
    那么國際的內(nèi)容只能在i18n標(biāo)簽中使用,一旦離開i18n標(biāo)簽則不能使用 -->
    <s:i18n name="myI18n">
        <s:text name="username"></s:text>
        <s:form>
            <s:textfield name="username" key="username"></s:textfield>
            <s:password name="password" key="password"></s:password>
            <s:submit key="submit"></s:submit>
        </s:form>
    </s:i18n>

  • 訪問國際化消息
    • JSP 頁面訪問國際化消息

      • 不帶占位符:
        • <s:text name="key"/>
        • 表單元素的 label 屬性:可替換為 key 或使用 getText() 方法,并對其進(jìn)行強(qiáng)制 OGNL 解析,使用%{}
      • 帶占位符:
        • 在 <s:text.../> 標(biāo)簽中使用多個 <s:param.../> 標(biāo)簽來填充消息中的占位符。
        • Struts2 直接在國際化消息資源文件中通過 “${}” 使用表達(dá)式,該表達(dá)式將從值棧中獲取對應(yīng)的屬性值(對象棧 和 Map 棧)
    • Action 訪問國際化消息:

      • 若 Action 類繼承了 ActionSupport ,則可調(diào)用 TextProvider 接口的 getText 方法。

  • 利用超鏈接實現(xiàn)動態(tài)加載國際化資源文件
    • Struts2 使用 i18n 攔截器 處理國際化,并且將其注冊在默認(rèn)的攔截器中
    • i18n攔截器在執(zhí)行Action方法前,自動查找請求中一個名為request_locale 的參數(shù)
    • 如果該參數(shù)存在,攔截器就將其作為參數(shù),轉(zhuǎn)換成Locale對象,并將其設(shè)為用戶默認(rèn)的Locale(代表國家/語言環(huán)境)。并把其設(shè)置為 session 的 WW_TRANS_I18N_LOCALE 屬性
    • request 沒有名為request_locale 的參數(shù),則 i18n 攔截器會從 Session 中獲取 WW_TRANS_I18N_LOCALE 的屬性值,若該值不為空,則將該屬性值設(shè)置為瀏覽者的默認(rèn)Locale
    • 若 session 中的 WW_TRANS_I18N_LOCALE 的屬性值為空,則從 ActionContext 中獲取 Locale 對象。
<!-- 必須是 struts 請求,使得 i18 攔截器工作 -->
<a href="userLogin.action?request_locale=en_US">English</a>
<a href="userLogin.action?request_locale=zh_CN">中文</a>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容