基於springboot實現http響應異常信息國際化


背景

國際化是指在設計軟件,將軟件與特定語言及地區脫鈎的過程。當軟件被移植到不同的語言及地區時,軟件本身不用做內部工程上的改變或修正。

本文提到的異常響應信息國際化是指:前端向后台發起請求,后台在處理邏輯中發生異常,把異常信息返回給前端,返回的異常信息應該支持國際化,能夠對應特定的語言、地區等環境。例如,中文語言環境下返回的異常信息應該是中文的,英文語言環境下返回的則是對應的英文。

javaweb項目中,不管是對底層的數據操作,還是業務層的處理過程,還是控制層的處理,都不可避免的會遇到各種可預知的(業務異常主動拋出)、不可預知的異常需要處理。一般dao層、service層的異常都會直接拋出,最后由controller統一進行處理,並對前端請求進行異常響應。針對此處的業務異常應該做到設計合理,統一格式,並且支持國際化。

springboot是一個開源的Java/Java EE的應用程序框架,其設計目的是用來簡化新Spring應用的初始搭建以及開發過程。利用springboot提供的API庫,我們能方便地做到全局異常統一攔截,並且Spring提供了完善的國際化支持,在此基礎上,我們能方便地做到全局異常信息的國際化。

原來存在的方案:

  1. 局部的異常信息國際化:程序在拋出異常時手動設置好國際化之后的異常message。

    此種方案代碼耦合性強,代碼繁瑣,處理邏輯過程中拋出異常時還得額外考慮對異常進行國際化操作,使得代碼邏輯無法很好的集中在業務邏輯的處理。示意圖如圖1.1。

  2. 半異常信息國際化:程序中未采用配置文件來記錄國際化資源,而是直接在程序中寫死了固定的異常值,每條異常值記錄分別對應着不同的異常編號、某幾種語言的異常信息。

    這是目前比較常見的方式,寫起來方便,不需要在程序拋出異常時做國際化,只需在全局異常攔截中做統一的異常返回。但是,這種方式支持的異常信息比較單一,不能輕易添加多種語言的支持,只能改動現有程序的代碼。示意圖如圖1.2。

  3. 使用編程語言自帶的異常本地化接口。

    不少后台語言提供了異常信息本地化接口,比如java提供的java.lang.Throwable#getLocalizedMessage方法,但是這種方式只能獲取到本地語言相關的對應的信息,並不能很好的支持多種語言,以及多種語言間的自由切換。

現在的方案

此方案結合異常碼、字符串占位符和資源文件的特點及優勢。異常碼可理解為一個異常信息的ID,具有唯一性,必要性;異常信息資源文件中的值可包含占位符(格式為{n}),處理異常時可用實際值替換,達到異常信息的進一步具體化,但不是必須的。資源文件就是內容為“異常碼=提心信息”的記錄的文件。

方案具體描述如下:

  1. 首先,在springboot項目中定義系統的http請求統一返回的數據格式,此處我們的定義包含三個屬性: code(業務異常狀態碼)、message(異常提示信息)、data(無異常時返回的數據體)。對異常信息國際化主要體現在message屬性,也就是返回前端給用戶展示的異常提示信息。code屬性用於確定唯一的異常。其次定義需要拋出的業務異常,其中主要包括code(異常碼)和params(用於替換異常信息字符串占位符{n}的實際值)屬性。

  2. 在項目路徑下定義異常信息的資源文件,文件內容包含多條記錄,每條記錄為鍵值對的形式,即key=value。對需要實現的語言種類分別提供一份對應的文件,這些文件名除默認信息外,均包含語言(地區信息),文件中包含中key是一致的,value為相應語言的字符串組成。如果添加語言的支持,只需要添加一份對應的資源文件即可。以下包含默認、英文環境和簡體中文環境下對應的異常提示信息國際化資源文件,如圖2.1

  3. 利用springboot的提供的接口定義統一攔截器,並且注入http請求上下文和資源獲取器,在攔截器中對應用拋出的異常進行捕獲,針對上述特定的異常做國際化處理。
    其國際化處理邏輯如下:根據http請求傳入的語言信息指定特定的語言(地區)環境,如沒有傳入語言信息,則采用應用默認的語言配置;據此讀取上述編寫好的對應的異常信息資源文件,並依據捕獲的異常中的code(異常碼)查到到對應的字符串,將params實際值替換掉字符串中的占位符,完成后即為返回給前端的異常提示信息。

  4. 在controller、service和dao層中根據程序邏輯拋出相應異常,其中異常碼應該在資源文件中已定義。示例代碼如下圖2.3

  5. 整體流程圖如下圖2.4

demo

以下是一個demo,其中提供了必要的代碼注釋,以便於理解。

  • 自定義異常結構,包含code和params

  • 異常資源文件定義

  • 全局異常攔截

  • 代碼邏輯中拋出異常

  • 請求響應示例

請求1:http://127.0.0.1:8080/demo?lang=en&msg=a

返回:

請求2:http://127.0.0.1:8080/demo?lang=zh_CN&msg=a

返回:

請求3:http://127.0.0.1:8080/demo?lang=en&msg=c

返回:

請求4:http://127.0.0.1:8080/demo?lang=zh_CN&msg=c
返回:

源碼

https://github.com/newhoo/i18n-exception-demo

總結

  1. 此方案能較好地處理異常信息的國際化,能自如地添加資源文件,不需要改動此方案的現有代碼,這也使得程序耦合性降低;
  2. 統一的異常格式定義、全局異常攔截極大程度上減少了代碼耦合性,大大簡化了團隊編碼中對異常邏輯的處理,能減少重復性編碼,有利於提高工作效率;
  3. 現有方案未能較好地支持異常信息中特定值的支持,此方案利用設置占位符的方式,較好地做到了支持,靈活方便;
  4. springboot支持的國際化實現中默認提供了緩存支持,性能良好。

參考

(文中配圖有空再改!!)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM