7.類型轉換、消息處理與國際化

来源:http://www.cnblogs.com/MPPC/archive/2016/12/03/6128263.html
-Advertisement-
Play Games

前邊我們說過了 Http協議 有兩個缺陷 一個是無狀態 、 一個是純文本 。 純文本也就是說Http請求中的內容都是以字元串的形式發送的。 但是Java又是一個強類型語言,所以將一個字元串轉換成Java中的數據類型這一重任就落在了Struts2的肩膀上。 類型轉換最常見的可能就是將將10/29/20 ...


  • 前邊我們說過了 Http協議 有兩個缺陷一個是無狀態一個是純文本
  • 純文本也就是說Http請求中的內容都是以字元串的形式發送的。
  • 但是Java又是一個強類型語言,所以將一個字元串轉換成Java中的數據類型這一重任就落在了Struts2的肩膀上。
  • 類型轉換最常見的可能就是將將10/29/2015轉換為一個date類型等。
  • 關於類型轉換我們要做的主要有兩件事:
    • 類型轉換失敗後的處理
    • 特殊類型的自定義類型轉換器

類型轉換失敗消息處理

  • 類型轉換失敗
    • 若 Action 類沒有實現 ValidationAware 介面: Struts 在遇到類型轉換錯誤時仍會繼續調用其 Action 方法, 就好像什麼都沒發生一樣.
    • 若 Action 類實現 ValidationAware 介面:Struts 在遇到類型轉換錯誤時將不會繼續調用其 Action 方法:
      • Struts 將檢查相關 action 元素的聲明是否包含著一個 name=input 的 result.
      • 如果有, Struts 將把控制權轉交給那個 result 元素;
      • 若沒有 input 結果, Struts 將拋出一個異常
    • 實現 ValidationAware 介面,在之前的文章中我們提到,我們可以繼承 com.opensymphony.xwork2.ActionSupport 類的形式來實現 ValidationAware 介面, 在ActionSupport 中已經幫我們實現好了

  • 類型轉換出錯時如何處理
    • 如果我們輸入錯誤的數字,想轉換為年齡;當我們的 result name="input" 的時候,會返回到這個結果頁面。
    • 錯誤的年齡
    • 但是對於這種錯誤的提示,我們需要處理
  • 類型轉換錯誤消息的定製
    • 作為預設的 default 攔截器的一員, ConversionError 攔截器負責添加與類型轉換有關的出錯消息(前提: Action 類必須實現了 ValidationAware 介面)和保存各請求參數的原始值.
    • 若欄位標簽使用的不是 simple 主題, 則非法輸入欄位將導致一條有著如上圖格式的出錯消息。
  • 覆蓋預設的出錯消息
    • 在對應的 Action 類所在的包中新建 ActionClassName.properties 文件, ClassName 即為包含著輸入欄位的 Action 類的類名
    • 在屬性文件中添加如下鍵值對: invalid.fieldvalue.fieldName=Customer Message
# EmployeeAction.properties
invalid.fieldvalue.age=年齡格式不正確,請重新輸入!
  • 自定義的消息

  • 定製出錯消息的樣式:
    • 每一條出錯消息都被打包在一個 HTML span 元素里, 可以通過覆蓋其行標為 errorMessage 的那個 css 樣式來改變出錯消息的格式.
    • 顯示錯誤消息: 如果是 simple 主題, 可以通過 <s:fielderror fieldName=“filedname”></s:fielderror> 標簽顯示錯誤消息
    • 通過s:fielderror 標簽
<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>
    <!-- 通過標簽獲取錯誤消息 -->
    <span style="color:red"><s:fielderror fieldName="age"></s:fielderror></span><br>
    部門: <s:textfield name="dept"></s:textfield><br>
    職務:<s:textfield name="role"></s:textfield><br>
    <s:submit value="修改"></s:submit>
</s:form>
  • 但是對於這種錯誤消息的格式我們是可以修改的,修改其預設的 freemark 模板
  • struts2-core-2.3.15.3.jar 的 /template/simple/fielderror.ftl,這是 struts2 預設自帶的錯誤消息模板,我們在 src 路徑下建立相同的包和模板,並且修改裡面的 html 標簽。刪除文件中錯誤消息的 的 ul、li、span便簽

  • ![刪除的模板
  • 效果


自定義類型轉換器

  • 定製類型轉換器
  • 自定義類型轉換器必須實現 ongl.TypeConverter 介面或對這個介面的某種具體實現做擴展
  • 擴展 StrutsTypeConverter 類
    • 在大多數類型轉換器里, 需要提供從 String 類型到非 String 類型和與此相反的轉換功能
    • 在 StrutsTypeConverter 中有兩個抽象方法:
  • 配置自定義的類型轉換器
    • 在應用程式里使用一個自定義的類型轉換器之前, 必須先對它進行配置. 這種配置既可以基於欄位, 也可以基於類型
    • 基於欄位類型轉換配置-局部轉換器
      • 可以為某個 Model(該 Model 類也可能是 Action) 的各個屬性分別配置一個自定義的轉換器.
      • 創建一個屬性文件: ModelClassName-conversion.properties, 該文件需和相對應的 Model(Model有可能是一個Action) 類放在同一個目錄下
      • fieldName=Converter全類名,例如: birth=org.pan.struts2.conver.DateConverter
    • 基於類型-全局轉換器
      • 在資源目錄下,src 或者 其他的 resources 創建 xwork-conversion.properties文件
      • xwork-conversion.properties 文件里把每一個需要進行類型轉換的類與一個類型轉換器關聯起來
      • java.util.Date=org.pan.struts2.conver.DateConverter
      • 若類型轉換失敗,給出自定義的信息。

複雜屬性,集合協同工作

  • 複雜屬性
    • 類型轉換與複雜屬性配合使用
    • form 標簽的 name 屬性可以被映射到一個屬性的屬性.
    • 複雜屬性
    • <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="經理名稱"></s:textfield>
      <s:textfield name="user.mgr.birth" label="經理生日"></s:textfield>
      <s:submit value="添加"></s:submit>
      </s:form>
  • 集合協同
    • 類型轉換與 Collection 配合使用

國際化

  • 概述
    • 在程式設計領域, 把在無需改寫源代碼即可讓開發出來的應用程式能夠支持多種語言和數據格式的技術稱為國際化.
    • 與國際化對應的是本地化, 指讓一個具備國際化支持的應用程式支持某個特定的地區
    • Struts2 國際化是建立在 Java 國際化基礎上的:
    • 為不同國家/語言提供對應的消息資源文件
      • Struts2 框架會根據請求中包含的
        • Locale 載入對應的資源文件
      • 通過程式代碼取得該資源文件中
      • 指定 key 對應的消息
  • 預設攔截器棧中有一個i18n攔截器,這個攔截器用來設置當前Locale信息
    • 當i18n攔截器被調用時,他會先去查找request_locale這個請求參數,它會根據乾參數來創建一個Locale對象。並將Locale對象放入進session域中。之後在載入國際化資源文件時就根據剛剛創建的Locale對象
  • 當i18n攔截的請求中沒有request_locale這個參數,
  • 它會先去session中獲取Locale對象,如果session中,則直接使用該對象
  • 如果session中沒有,則會根據用戶瀏覽器信息或本地伺服器的信息去創建一個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.../> 標簽的 name 屬性指定臨時的國際化資源文件
  • 總結:
    • 國際化資源文件載入的順序如何呢 ?
      • 離當前 Action 較近的將被優先載入.
    • 假設我們在某個 ChildAction 中調用了getText("username")
      • (1)載入和 ChildAction 的類文件在同一個包下的系列資源文件 ChildAction.properties
      • (2)載入 ChildAction 實現的介面 IChild,且和 IChildn 在同一個包下 IChild.properties 系列資源文件。
      • (3)載入 ChildAction 父類 Parent,且和 Parent 在同一個包下的 baseName 為 Parent.properties 系列資源文件。
      • (4) 若 ChildAction 實現 ModelDriven 介面,則對於getModel()方法返回的model 對象,重新執行第(1)步操作。
      • (5) 查找當前包下 package.properties 系列資源文件。
      • (6) 沿著當前包上溯,直到最頂層包來查找 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"> 標簽來獲取
    <!-- 如果是配置了頁面國際化資源文件,
    那麼國際的內容只能在i18n標簽中使用,一旦離開i18n標簽則不能使用 -->
    <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() 方法,並對其進行強制 OGNL 解析,使用%{}
      • 帶占位符:
        • Struts2 直接在國際化消息資源文件中通過 “${}” 使用表達式,該表達式將從值棧中獲取對應的屬性值(對象棧 和 Map 棧)
    • Action 訪問國際化消息:
      • 若 Action 類繼承了 ActionSupport ,則可調用 TextProvider 介面的 getText 方法

  • 利用超鏈接實現動態載入國際化資源文件
    • Struts2 使用 i18n 攔截器 處理國際化,並且將其註冊在預設的攔截器中
    • i18n攔截器在執行Action方法前,自動查找請求中一個名為request_locale 的參數
    • 如果該參數存在,攔截器就將其作為參數,轉換成Locale對象,並將其設為用戶預設的Locale(代表國家/語言環境)。並把其設置為 session 的 WW_TRANS_I18N_LOCALE 屬性
    • request 沒有名為request_locale 的參數,則 i18n 攔截器會從 Session 中獲取 WW_TRANS_I18N_LOCALE 的屬性值,若該值不為空,則將該屬性值設置為瀏覽者的預設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>




您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 英文文檔: The constructor builds a tuple whose items are the same and in the same order as iterable‘s items. iterable may be either a sequence, a containe ...
  • 1、直接把表單的參數寫在Controller相應的方法的形參中,適用於get方式提交,不適用於post方式提交。若"Content-Type"="application/x-www-form-urlencoded",可用post提交 url形式:http://localhost:8080/SSMDe ...
  • 為瞭解決C++記憶體泄漏的問題,C++11引入了智能指針(Smart Pointer)。 智能指針的原理是,接受一個申請好的記憶體地址,構造一個保存在棧上的智能指針對象,當程式退出棧的作用域範圍後,由於棧上的變數自動被銷毀,智能指針內部保存的記憶體也就被釋放掉了,除非將智能指針保存起來。 C++11提供了 ...
  • JDBC2.0提供了javax.sql.DataSource介面,它負責建立與資料庫的連接,在應用程式中訪問資料庫時不必編寫連接資料庫的代碼,可以直接從數據源獲得資料庫連接 1.資料庫和連接池 在DataSource中事先建立了多個資料庫連接,這些資料庫連接保存在連接池(ConnectPool)中。 ...
  • ORM 眾所周知有很多不同的資料庫系統,並且其中的大部分系統都包含Python介面,能夠讓我們更好的利用它們的功能,而這些系統唯一的缺點就是需要你瞭解SQL,如果你是一個更願意操縱Python對象,而不是SQL查詢的程式員,並且仍然希望使用關係資料庫作為你的數據後端,那麼我們可以使用ORM。 這些O ...
  • 1、流程分析: 1. 請求發送給 StrutsPrepareAndExecuteFilter 2. StrutsPrepareAndExecuteFilter 詢問 ActionMapper: 該請求是否是一個 Struts2 請求(即是否返回一個非空的 ActionMapping 對象) 3. 若 ...
  • 冪等概念來自數學,表示N次變換和1次變換的結果是相同的。這裡討論在某些場景下,客戶端在調用服務沒有達到預期結果時,會進行多次調用,為避免多次重覆的調用對服務資源產生副作用,服務提供者會承諾滿足冪等。 ...
  • map()是 Python 內置的高階函數,它接收一個函數 f 和一個 list,並通過把函數 f 依次作用在 list 的每個元素上,得到一個新的 list 並返回。 例如,對於list [1, 2, 3, 4, 5, 6, 7, 8, 9] 如果希望把list的每個元素都作平方,就可以用map( ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...