SpringBoot項目中實現返回結果和枚舉類的國際化

前言

什麼是國際化呢?國際慣例,來時來一段官方介紹:

  1. 國際化(internationalization)是設計和製造容易適應不同區域要求的產品的一種方式。
  2. 它要求從產品中抽離所有地域語言,國家/地區和文化相關的元素。
  3. 換言之,應用程序的功能和代碼設計考慮在不同地區運行的需要,其代碼簡化了不同本地版本的生產。
  4. 開發這樣的程序的過程,就稱為國際化。
SpringBoot項目中實現返回結果和枚舉類的國際化

在我們實際開發中,一個web應用可能要在多個地區使用,面對不同地區的不同語言,為了適應不同的用戶,我們可以嘗試在前端頁面實現多語言的支持,那麼同樣對於後端返回的一些提示信息,異常信息等,我們後端也可以根據不同的語言環境來進行國際化處理,返回相應的信息。

開發工具

IDEA、Maven、SpringBoot2.0.5、Jdk1.8、google瀏覽器

SpringBoot中的國際化

原理:

想要使應用支持國際化,首先需要知道用戶的語言環境,即用戶想要看到的語言,我們設想在用戶每次請求時告訴服務器自己的語言環境,服務器收到請求後,根據不同的語言環境返回不同的信息來實現國際化。在spring應用中,用戶的語言環境是通過區域解析器來識別的,而區域解析器有分為好幾種(後面詳細說),在我們不做配置修改時,spring使用AcceptHeaderLocaleResolver作為默認的區域解析器,它是根據HTTP請求 Header中的Accept-language的值來解析,當然區域解析器我們也可以自定義配置。

springboot默認就支持國際化。我們只需要只需要作相應的配置即可。

1.首先你需要一個springboot項目。IDEA中分分鐘創建好一個項目。

2.在resources下定義國際化配置文件,注意名稱必須以messages開始。(在springboot中,當我們不修改配置時默認去解析名稱以message開始的properties文件)

messages.properties (默認環境,無法確定語言環境時,解析該文件中的相應信息)

messages_zh_CN.properties(中文語言環境時,解析該文件中的相應信息)

messages_en_US.properties(英文語言環境時,解析該文件中的相應信息)

在三個配置文件中分別以Key = Value形式存儲如下三條信息,如下:

welcome = 這是一個支持國際化的項目。

welcome = 這是一個支持國際化的項目。


  • welcome = This is a project supporting internationalization.
  • SpringBoot項目中實現返回結果和枚舉類的國際化

    3.創建thymeleaf頁面

    加入thymeleaf依賴

    1. org.springframework.boot
    2. spring-boot-starter-thymeleaf

    在resources/templates目錄下創建hello.html頁面:

    嘗試在不同的語言環境下,通過#{welcome}獲取信息

    1. demo

    4.創建訪問頁面的controller

    注意這裡controller的註解時@Controller

    1. import org.springframework.stereotype.Controller;
    2. import org.springframework.web.bind.annotation.RequestMapping;
    3. /**
    4. * 描述:
    5. *
    6. * @author zhengql
    7. * @date 2018/9/25 19:28
    8. */
    9. @Controller
    10. public class BaseController {
    11. @RequestMapping("/hi")
    12. public String hello() {
    13. return "/hello";
    14. }
    15. }

    測試國際化效果

    這裡使用google瀏覽器進行測試,測試之前需要安裝插件Language Switcher

    Language Switcher : 可以改變當前請求的語言環境(根據自己的選擇)

    啟動我們的springboot項目,google瀏覽器訪問 http://127.0.0.1:8080/hi ,可以看到如下頁面:

    通過Language Switcher切換語言環境為English - United States,重新訪問 http://127.0.0.1:8080/hi ,可以看到如下頁面:

    ok,大功告成,到此一個簡單的國際化項目就完成了。

    擴展國際化

    通過上面的小栗子,我們可以看到一個簡單的國際化使用,但是在開發中中還需要我們進行一定的配置,來滿足我們不同情況下的使用。

    在返回結果中獲取國際化信息

    很多時候,後端接收到一個請求後,需要返回一個提示信息,而此時我們可以使這個返回信息支持國際化

    這裡就用到了org.springframework.context.MessageSource接口,MessageSource提供了三個方法

    @Nullable//參數字段可為空

    1. String getMessage(String var1, @Nullable Object[] var2, @Nullable String var3, Locale var4);
    2. String getMessage(String var1, @Nullable Object[] var2, Locale var3) throws NoSuchMessageException;
    3. String getMessage(MessageSourceResolvable var1, Locale var2) throws NoSuchMessageException;

    String getMessage(String var1, @Nullable Object[] var2, @Nullable String var3, Locale var4):用來從MessageSource獲取消息的基本方法。如果在指定的locale中沒有找到消息,則使用默認的消息。var2中的參數將使用標準類庫中的MessageFormat來作消息中替換值。

    String getMessage(String code, Object[] args, Locale loc):本質上和上一個方法相同,其區別在:沒有指定默認值,如果沒找到消息,會拋出一個NoSuchMessageException異常。

    String getMessage(MessageSourceResolvable resolvable, Locale locale):上面方法中所使用的屬性都封裝到一個MessageSourceResolvable實現中,而本方法可以指定MessageSourceResolvable實現。

    下面我們實踐一下:

    1.創建一個以json返回格式的controller,注入MessageSource,注意controller的註解為@RestController

    在這裡首先我們需要獲取到當前請求的Locale,有兩種方法:

    1. Locale locale = LocaleContextHolder.getLocale();
    2. Locale locale = RequestContextUtils.getLocale(request);

    兩種方式根據情況選擇使用,下面是controller代碼

    1. package com.example.i18n.controller;
    2. import org.springframework.beans.factory.annotation.Autowired;
    3. import org.springframework.context.MessageSource;
    4. import org.springframework.context.i18n.LocaleContextHolder;
    5. import org.springframework.web.bind.annotation.RequestMapping;
    6. import org.springframework.web.bind.annotation.RestController;
    7. /**
    8. * 描述:
    9. *
    10. * @author zhengql
    11. * @date 2018/9/21 10:54
    12. */
    13. @RestController
    14. public class JsonController {
    15. @Autowired
    16. private MessageSource messageSource;
    17. @RequestMapping("/ha")
    18. public String ha() {
    19. return messageSource.getMessage("welcome", null, LocaleContextHolder.getLocale());
    20. }
    21. }

    2.啟動項目訪問 http://127.0.0.1:8080/ha ,可以看到相應語言環境的返回信息

    通過Language Switcher切換語言環境為English - United States,重新訪問http://127.0.0.1:8080/ha,可以看到如下頁面:

    支持佔位符國際化信息返回

    我們經常會遇到這樣一個場景,登錄賬號需要驗證碼,填寫完手機號獲取驗證碼後會收到一條類似於尊敬的用戶13099999999您好,您的驗證碼是6666,這種信息,其實就是一個模板,通過改變參數,重複使用。我們通過國際化資源文件中的佔位符,配合MessageSource提供的api也可以實現。

    資源文件中加入如下屬性:

    messages.properties,messages_zh_CN.properties

    1. hello=你好:{0} , 你的驗證碼為 :{1}

    messages_en_US.properties

    1. hello=Hello: {0}, your verification code is: {1}

    我們在JsonController中,創建一個測試接口

    1. @RequestMapping("/haha")
    2. public String haha() {
    3. return messageSource.getMessage("hello", new Object[]{"zhangsan","123456"}, LocaleContextHolder.getLocale());
    4. }

    啟動項目直接,訪問 http://127.0.0.1:8080/haha 可以看到相應語言環境的返回信息

    通過Language Switcher切換語言環境為English - United States,重新訪問 http://127.0.0.1:8080/haha ,可以看到如下頁面:

    支持國際化的枚舉類

    既然返回信息可以實現國際化,那我們的枚舉類同樣也可以實現國際化咯

    創建一個枚舉類EnumSuccessOrError.java

    1. /**
    2. * 描述:枚舉類舉例
    3. *
    4. * @author zhengql
    5. * @date 2018/9/26 20:52
    6. */
    7. public enum EnumSuccessOrError {
    8. SUCCESS(0, "操作成功"),
    9. ERROR(1, "操作失敗");
    10. /**
    11. * 返回狀態碼
    12. */
    13. private int statusCode;
    14. /**
    15. * 返回狀態信息
    16. */
    17. private String statusMsg;
    18. EnumSuccessOrError(int statusCode, String statusMsg) {
    19. this.statusCode = statusCode;
    20. this.statusMsg = statusMsg;
    21. }
    22. /**
    23. * @return the statusCode
    24. */
    25. public int getStatusCode() {
    26. return statusCode;
    27. }
    28. /**
    29. * @return the statusMsg
    30. */
    31. public String getStatusMsg() {
    32. return statusMsg;
    33. }
    34. }

    如上,剛剛創建的枚舉類是不支持國際化的,我們呢需要改造他,當調用getStatusMsg方法時根據語言環境返回相應的國際化字符串。可以從如下兩個點著手:

    getStatusMsg方法改造

    資源文件中添加不同語言環境對應的返回值

    先在三個資源文件中加入不同環境的返回值:

    messages.properties,messages_zh_CN.properties

    1. SUCCESS = 操作成功
    2. ERROR = 操作失敗

    messages_en_US.properties

    1. SUCCESS=success
    2. ERROR=error

    改造後的枚舉如下:

    1. public enum EnumSuccessOrError {
    2. SUCCESS(0, "SUCCESS"),
    3. ERROR(1, "ERROR");
    4. /**
    5. * 返回狀態碼
    6. */
    7. private int statusCode;
    8. /**
    9. * 返回狀態信息
    10. */
    11. private String statusMsg;
    12. EnumSuccessOrError(int statusCode, String statusMsg) {
    13. this.statusCode = statusCode;
    14. this.statusMsg = statusMsg;
    15. }
    16. private MessageSource messageSource;
    17. public EnumSuccessOrError setMessageSource(MessageSource messageSource) {
    18. this.messageSource = messageSource;
    19. return this;
    20. }
    21. //通過靜態內部類的方式注入bean,並賦值到枚舉中
    22. @Component
    23. public static class ReportTypeServiceInjector {
    24. @Autowired
    25. private MessageSource messageSource;
    26. @PostConstruct
    27. public void postConstruct() {
    28. for (EnumSuccessOrError rt : EnumSet.allOf(EnumSuccessOrError.class))
    29. rt.setMessageSource(messageSource);
    30. }
    31. }
    32. /**
    33. * @return the statusCode
    34. */
    35. public int getStatusCode() {
    36. return statusCode;
    37. }
    38. /**
    39. * @return the statusMsg,根據語言環境返回國際化字符串
    40. */
    41. public String getStatusMsg() {
    42. return messageSource.getMessage(statusMsg,null,statusMsg, LocaleContextHolder.getLocale());
    43. }
    SpringBoot項目中實現返回結果和枚舉類的國際化

    此時我們在JsonController中,再創建一個測試接口

    1. @RequestMapping("/enumDemo")
    2. public String enumDemo() {
    3. return EnumSuccessOrError.SUCCESS.getStatusMsg();
    4. }

    啟動項目直接,訪問 http://127.0.0.1:8080/enumDemo 可以看到相應語言環境的返回信息。


    分享到:


    相關文章: