SpringBoot第十集:國際化與Webjars的應用(2020最新最易懂)
SpringBoot第十集:i18n與Webjars的應用(2020最新最易懂)
一,頁面國際化
i18n(其來源是英文單詞 internationalization的首末字元i和n,18為中間的字元數)是“國際化”的簡稱。除了i18n(支援多種語言),L10n(localization),g11n(globalization),還有m17n(multilingualization)
1,什麼是國際化
國際化就是可以把頁面中的中文變成英文。根據地區使用語言,及瀏覽器語言使用不同,頁面語言也隨之而變化。例如阿里巴巴官網,Dubbo的官方網站等
2, 如何實現頁面國際化?
A,準備工作
- 確保工作空間編碼,和後續新建工程檔案編碼都是UTF-8(支援語言型別最強大,俗稱萬國碼)
- 新建SpringBoot工程整合Thymeleaf(一切網頁交給模板引擎Thymeleaf接管),並提供預設模板。(整合參考:SpringBoot第九集整合模板引擎)
至於頁面模板,自己做一個挺麻煩的,可以參考很多後臺元件或模板,BootStrap,EazyUI,layUI,Sematic UI,Admin,XAdmin,AdminLet, Light Year Admin等(我用過的都說了,你看著辦) - 新增控制器,訪問頁面模板
1 @Controller 2 public class AdminController { 3 4 /** 5 * @return 跳轉去登入 6 */ 7 @RequestMapping("/login") 8 public String login() { 9 return "login"; 10 } 11 12 }
http://localhost:8080/login
訪問效果:
注意不要忘記整合Thymeleaf需要加如約束:
1 <html class="x-admin-sm" xmlns:th="http://www.thymeleaf.org">
- 新增國際化配置檔案properties,抽取頁面需要顯示的國際化訊息定義在不同命名的檔案中。
關於配置檔案的命名格式:基本名稱+“_”+語言簡稱+“_”+國家簡稱.properties 注意嚴格區分大小寫(關於語言簡稱可以在附錄中查閱,列舉了 部分可供參考)
該案例命名舉例:
login.properties:這個用於作為預設顯示語言配置(預設訪問頁面時顯示的語言配置)
login_zh_CN.properties:這個用於當指定使用中文時顯示的語言配置
login_en_US.properties:這個用於當指定使用英文時顯示的語言配置
實現:
a,在src/main/resources目錄下新增i18n目錄,新增三個配置檔案
(當然不同的開發工具,目錄結構效果和適配使用效果是不一樣的,參考SpringBoot第一集)本次演示使用的工具是Spring Tool Suite
b,內容大概,實際情況根據你的情況而定
key對應value,其中key是自定義的,不一定要新增字首,但是,幾個檔案中key一定要相同。1 ###用於預設語言顯示的配置檔案 2 login.message=管理員登入 3 login.username=使用者名稱 4 login.password=密碼 5 login.submit=請登入 6 ######################################### 7 ###用於指定英文語言顯示的配置檔案 8 login.message=Administrator Login 9 login.username=user name 10 login.password=password 11 login.submit=Please Login
c,對應關係
- 修改網頁預設資料區
按照Thymeleaf語法,修改網頁,將所有文字資訊,替換為properties屬性獲取的方式。
th:Thymeleaf配置屬性語法,Thymeleaf替換值語法th:text,Thymeleaf取值語法#{..........}。詳情參考博主模板引擎Thymeleaf常用語法。
1 <div class="login layui-anim layui-anim-up"> 2 <!-- th:text的值會替換標籤對之間的內容 --> 3 <div class="message" th:text="#{login.message}">x-admin2.0-管理登入</div> 4 <div id="darkbannerwrap"></div> 5 6 <form method="post" class="layui-form" > 7 <input name="username" th:placeholder="#{login.username}" type="text" lay-verify="required" class="layui-input" > 8 <hr class="hr15"> 9 <input name="password" lay-verify="required" th:placeholder="#{login.password}" type="password" class="layui-input"> 10 <hr class="hr15"> 11 <input th:value="#{login.submit}" lay-submit lay-filter="login" style="width:100%;" type="submit"> 12 <hr class="hr20" > 13 </form> 14 </div>
B,實現步驟
- 修改yml核心配置檔案
1 spring: 2 # 國際化配置 3 messages: 4 # 國際化的檔案的儲存在src\main\resources 資料夾下的什麼位置。注意這是個相對位置 5 basename: i18n/login 6 # 表示 messages 檔案的快取失效時間,如果不配置則快取一直有效 7 cache-duration: 3600 8 # 配置編碼 9 encoding: UTF-8 10 # 如果找不到語言,是不是返回伺服器系統語言。 11 fallback-to-system-locale: true
- 修改頁面前端提交切換引數
th:是Thymeleaf屬性設定語法。連結語法@{...uri..}。引數語法(key=value&key=value....)詳情參考博主模板引擎Thymeleaf常用語法。
1 <a th:href="@{login(language=zh_CH)}">簡體中文</a> 2 <a th:href="@{login(language=en_US)}">English</a>
- 編寫自定義語言資訊解析器
編寫普通類實現介面LocaleResolver,仿SpringBoot預設語言解析器實現(至於為什麼,可以參考附錄SpringBoot國際化原始碼解析)
1 public class LocaleMessageResolver implements LocaleResolver{ 2 /** 3 * 使用者可以使用request,根據指定的方式獲取一個Locale,如果沒有獲取到,則使用使用者指定的預設的Locale 4 */ 5 @Override 6 public Locale resolveLocale(HttpServletRequest request) { 7 // 獲取請求資料(切換語言傳遞的引數) 8 String language = request.getParameter("language"); 9 System.out.println("測試獲取的語言環境引數:"+language); 10 // 獲取Java虛擬機器此的預設區域語言環境 11 Locale defaultLocale = Locale.getDefault(); 12 // 判斷頁面是否選擇切換了語言 13 if (!StringUtil.isEmpty(language)) {// 如果不為null 14 // 選擇了切換語言環境,將語言環境,根據下劃線拆分 15 String[] split = language.split("_");// zh CH 16 // 建立新的語言環境,並替換預設語言環境(引數一:語言,引數二:國家,詳情參考附錄或JDK-API) 17 defaultLocale = new Locale(split[0], split[1]); 18 } 19 // 返回給頁面的語言環境(要麼系統預設,要麼已經選定的) 20 return defaultLocale; 21 } 22 23 /** 24 * 用於實現Locale的切換。及響應(SpringBoot整合無需這個處理方法) 25 */ 26 @Override 27 public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {} 28 29 }
- 將自定義加如到Spring IOC
如果不將自定義的語言解析器放入到Spring容器中,那麼國際化就是無效的!!!
1 @Configuration // <beans> 2 public class LocaleConfig { 3 /** 4 * 說明:注入語言解析器時,方法名必須交localeResolver 5 */ 6 @Bean // 注入bean 7 public LocaleMessageResolver localeResolver() { 8 return new LocaleMessageResolver(); 9 } 10 11 }
- 重啟SpringBoot工程,訪問測試
二.SpringBoot整合WebJars
通常對於web開發
而言,像js
、css
、images
等靜態資源版本管理是比較混亂的,比如Jquery
、Bootstrap
、Vue.js
可能各個前端框架所依賴的自個元件的版本都不盡相同,一不注意就可能引起不同版本的衝突問題。WebJars
是將web前端資源(如jQuery & Bootstrap & VUE 等)打成jar
包檔案。藉助版本管理工具(Maven、gradle等)進行版本管理,保證這些Web資源版本唯一性。避免了檔案混亂、版本不一致等問題。
開始使用前,我們看下Jquery
的webjars
,藉此來了解下webjars
包的目錄結構。
如上圖,可以看到資原始檔地址:META-INF/resources/webjars/jquery/3.5.1/jquery.js
使用方式
1.修改pom檔案引入webjars依賴。
例如:當前引入JQuery測試(注意,雖然已經講過熱部署,但新增依賴依然可能需要重啟服務)。查詢更多依賴
1 <dependency> 2 <groupId>org.webjars</groupId> 3 <artifactId>jquery</artifactId> 4 <version>3.5.1</version> 5 </dependency>
2.頁面引入JQueyr核心檔案測試
webjars檔案如何引入呢?參考SpringBoot第八集靜態資源地址原始碼解析。
1 <script src="webjars/jquery/3.5.1/jquery.js" type="text/javascript" charset="utf-8"></script> 2 <script type="text/javascript"> 3 $(function(){ 4 alert("測試webjars是否引入JQuery可用...."); 5 }); 6 </script>
當訪問:webjars/jquery/3.5.1/jquery.js 時,實際載入地址:META-INF/resources/webjars/jquery/3.5.1/jquery.js(資源原地址)
3.webjars應用擴充套件
當前狀態:頁面引入依賴檔案時,訪問路徑地址加上版本號,總的來說一切都很正常!但時,一旦pom依賴引入的webjars版本更新了,我們就被迫必須更新前臺程式碼。即當前的狀態是,前端硬編碼,不便於靈活使用和更新。所以官方提供了一個webjars-locator
包,就是來解決此問題的。
- 在maven倉庫搜尋依賴,並引入到當前專案下
1 <!-- webjars優化版更新本問題 --> 2 <dependency> 3 <groupId>org.webjars</groupId> 4 <artifactId>webjars-locator</artifactId> 5 <version>0.40</version> 6 </dependency>
- 修改頁面引入路徑問題
將頁面引入路徑版本號去除,此後,即使pom依賴更新版本,頁面也無需更改了。(當然除非官方有特大改動,名字包名都更新了)
<script src="webjars/jquery/jquery.js" type="text/javascript" charset="utf-8"></script>
- 頁面測試訪問
附錄
1.國際化配置檔案語言命名
格式說明(嚴格區分大小寫):語言_國家
命名下劃線之前是:語言簡稱
命名下劃線之後是:國家簡稱
語言 | 簡稱 |
---|---|
簡體中文(中國) | zh_CN |
繁體中文(中國臺灣) | zh_TW |
繁體中文(中國香港) | zh_HK |
英語(中國香港) | en_HK |
英語(美國) | en_US |
英語(英國) | en_GB |
英語(全球) | en_WW |
英語(加拿大) | en_CA |
英語(澳大利亞) | en_AU |
英語(愛爾蘭) | en_IE |
英語(芬蘭) | en_FI |
芬蘭語(芬蘭) | fi_FI |
英語(丹麥) | en_DK |
丹麥語(丹麥) | da_DK |
英語(以色列) | en_IL |
希伯來語(以色列) | he_IL |
英語(南非) | en_ZA |
英語(印度) | en_IN |
英語(挪威) | en_NO |
英語(新加坡) | en_SG |
英語(紐西蘭) | en_NZ |
英語(印度尼西亞) | en_ID |
英語(菲律賓) | en_PH |
英語(泰國) | en_TH |
英語(馬來西亞) | en_MY |
英語(阿拉伯) | en_XA |
韓文(韓國) | ko_KR |
日語(日本) | ja_JP |
荷蘭語(荷蘭) | nl_NL |
荷蘭語(比利時) | nl_BE |
葡萄牙語(葡萄牙) | pt_PT |
葡萄牙語(巴西) | pt_BR |
法語(法國) | fr_FR |
法語(盧森堡) | fr_LU |
法語(瑞士) | fr_CH |
法語(比利時) | fr_BE |
法語(加拿大) | fr_CA |
西班牙語(拉丁美洲) | es_LA |
西班牙語(西班牙) | es_ES |
西班牙語(阿根廷) | es_AR |
西班牙語(美國) | es_US |
西班牙語(墨西哥) | es_MX |
西班牙語(哥倫比亞) | es_CO |
西班牙語(波多黎各) | es_PR |
德語(德國) | de_DE |
德語(奧地利) | de_AT |
德語(瑞士) | de_CH |
俄語(俄羅斯) | ru_RU |
義大利語(義大利) | it_IT |
希臘語(希臘) | el_GR |
挪威語(挪威) | no_NO |
匈牙利語(匈牙利) | hu_HU |
土耳其語(土耳其) | tr_TR |
捷克語(捷克共和國) | cs_CZ |
斯洛維尼亞語 | sl_SL |
波蘭語(波蘭) | pl_PL |
瑞典語(瑞典) | sv_SE |
西班牙語(智利) | es_CL |
2.SpringBoot國際化原始碼解析
springboot國際化的時候,是通過interface LocaleResolver
介面的實現類的bean來確定是哪種語言的。這個介面有2個方法: 1、resolveLocale 用來獲取當前語言環境。 2、setLocale 修改語言環境。(針對Cookie、Session這種有狀態的請求。)
LocaleResolver的實現類只有4個:
- AcceptHeaderLocaleResolver(主要解析看這個原始碼)
- CookieLocaleResolver
- FixedLocaleResolver
- SessionLocaleResolver 預設使用AcceptHeaderLocaleResolver實現。
1 public class AcceptHeaderLocaleResolver implements LocaleResolver { 2 /**略其他原始碼 3 * 語言解方法 4 */ 5 @Override 6 public Locale resolveLocale(HttpServletRequest request) { 7 // 每次請求的時候,獲取http的名字叫Accept-Language的header引數,當Accept-Language==null時,使用系統預設Locale; 8 Locale defaultLocale = getDefaultLocale(); 9 if (defaultLocale != null && request.getHeader("Accept-Language") == null) { 10 return defaultLocale; 11 } 12 // 從當前請求中獲取Locale 13 Locale requestLocale = request.getLocale(); 14 // 從配置中獲取支援的Locale集合 15 List<Locale> supportedLocales = getSupportedLocales(); 16 // Locale集合為null或者Locale集合中包括請求語言,則直接使用客戶請求Locale 17 if (supportedLocales.isEmpty() || supportedLocales.contains(requestLocale)) { 18 return requestLocale; 19 } 20 // 找到設定的Locale集合中是否有請求的Locale 21 Locale supportedLocale = findSupportedLocale(request, supportedLocales); 22 if (supportedLocale != null) { 23 return supportedLocale; 24 } 25 return (defaultLocale != null ? defaultLocale : requestLocale); 26 } 27 // 略其他原始碼 28 }
總結:AcceptHeaderLocaleResolver實現了國際化解析器介面LocaleResolver,當每次請求發出後,都會執行resolveLocale方法,並通過獲取請求頭"Accept-Language"來判斷使用者是否使用國際化語言切換,沒有選擇切換語言,則直接使用預設語言,當有切換並定義國際化語言時,直接返回指定切換的語言。
&n