SpringBoot項(xiàng)目中實(shí)現(xiàn)返回結(jié)果和枚舉類的國際化

前言

什么是國際化呢?國際慣例,來時(shí)來一段官方介紹:

國際化(internationalization)是設(shè)計(jì)和制造容易適應(yīng)不同區(qū)域要求的產(chǎn)品的一種方式。

它要求從產(chǎn)品中抽離所有地域語言,國家/地區(qū)和文化相關(guān)的元素。

換言之,應(yīng)用程序的功能和代碼設(shè)計(jì)考慮在不同地區(qū)運(yùn)行的需要,其代碼簡(jiǎn)化了不同本地版本的生產(chǎn)。

開發(fā)這樣的程序的過程,就稱為國際化。

在我們實(shí)際開發(fā)中,一個(gè)web應(yīng)用可能要在多個(gè)地區(qū)使用,面對(duì)不同地區(qū)的不同語言,為了適應(yīng)不同的用戶,我們可以嘗試在前端頁面實(shí)現(xiàn)多語言的支持,那么同樣對(duì)于后端返回的一些提示信息,異常信息等,我們后端也可以根據(jù)不同的語言環(huán)境來進(jìn)行國際化處理,返回相應(yīng)的信息。

開發(fā)工具

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

SpringBoot中的國際化

原理:

想要使應(yīng)用支持國際化,首先需要知道用戶的語言環(huán)境,即用戶想要看到的語言,我們?cè)O(shè)想在用戶每次請(qǐng)求時(shí)告訴服務(wù)器自己的語言環(huán)境,服務(wù)器收到請(qǐng)求后,根據(jù)不同的語言環(huán)境返回不同的信息來實(shí)現(xiàn)國際化。在spring應(yīng)用中,用戶的語言環(huán)境是通過區(qū)域解析器來識(shí)別的,而區(qū)域解析器有分為好幾種(后面詳細(xì)說),在我們不做配置修改時(shí),spring使用

AcceptHeaderLocaleResolver作為默認(rèn)的區(qū)域解析器,它是根據(jù)HTTP請(qǐng)求 Header中的Accept-language的值來解析,當(dāng)然區(qū)域解析器我們也可以自定義配置。

springboot默認(rèn)就支持國際化。我們只需要只需要作相應(yīng)的配置即可。

1.首先你需要一個(gè)springboot項(xiàng)目。IDEA中分分鐘創(chuàng)建好一個(gè)項(xiàng)目。

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

messages.properties (默認(rèn)環(huán)境,無法確定語言環(huán)境時(shí),解析該文件中的相應(yīng)信息)

messages_zh_CN.properties(中文語言環(huán)境時(shí),解析該文件中的相應(yīng)信息)

messages_en_US.properties(英文語言環(huán)境時(shí),解析該文件中的相應(yīng)信息)

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

welcome = 這是一個(gè)支持國際化的項(xiàng)目。

welcome = 這是一個(gè)支持國際化的項(xiàng)目。

welcome = This is a project supporting internationalization.

3.創(chuàng)建thymeleaf頁面

加入thymeleaf依賴

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-thymeleaf</artifactId>

</dependency>

在resources/templates目錄下創(chuàng)建hello.html頁面:

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

<!DOCTYPE html>

<html xmlns:th="http://www.thymeleaf.org">

<head>

<meta charset="UTF-8"/>

<title>demo</title>

</head>

<body>

<p><label th:text="#{welcome}"></label></p>

</body>

</html>

4.創(chuàng)建訪問頁面的controller

注意這里controller的注解時(shí)@Controller

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

/**

* 描述:

*

* @author zhengql

* @date 2018/9/25 19:28

*/

@Controller

public class BaseController {

@RequestMapping("/hi")

public String hello() {

return "/hello";

}

}

測(cè)試國際化效果

這里使用google瀏覽器進(jìn)行測(cè)試,測(cè)試之前需要安裝插件Language Switcher

Language Switcher : 可以改變當(dāng)前請(qǐng)求的語言環(huán)境(根據(jù)自己的選擇)

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

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

ok,大功告成,到此一個(gè)簡(jiǎn)單的國際化項(xiàng)目就完成了。

擴(kuò)展國際化

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

在返回結(jié)果中獲取國際化信息

很多時(shí)候,后端接收到一個(gè)請(qǐng)求后,需要返回一個(gè)提示信息,而此時(shí)我們可以使這個(gè)返回信息支持國際化

這里就用到了

org.springframework.context.MessageSource接口,MessageSource提供了三個(gè)方法

@Nullable//參數(shù)字段可為空

String getMessage(String var1, @Nullable Object[] var2, @Nullable String var3, Locale var4);

String getMessage(String var1, @Nullable Object[] var2, Locale var3) throws NoSuchMessageException;

String getMessage(MessageSourceResolvable var1, Locale var2) throws NoSuchMessageException;

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

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

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

下面我們實(shí)踐一下:

1.創(chuàng)建一個(gè)以json返回格式的controller,注入MessageSource,注意controller的注解為@RestController

在這里首先我們需要獲取到當(dāng)前請(qǐng)求的Locale,有兩種方法:

Locale locale = LocaleContextHolder.getLocale();

Locale locale = RequestContextUtils.getLocale(request);

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

package com.example.i18n.controller;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.MessageSource;

import org.springframework.context.i18n.LocaleContextHolder;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

/**

* 描述:

*

* @author zhengql

* @date 2018/9/21 10:54

*/

@RestController

public class JsonController {

@Autowired

private MessageSource messageSource;

@RequestMapping("/ha")

public String ha() {

return messageSource.getMessage("welcome", null, LocaleContextHolder.getLocale());

}

}

2.啟動(dòng)項(xiàng)目訪問 http://127.0.0.1:8080/ha ,可以看到相應(yīng)語言環(huán)境的返回信息

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

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

我們經(jīng)常會(huì)遇到這樣一個(gè)場(chǎng)景,登錄賬號(hào)需要驗(yàn)證碼,填寫完手機(jī)號(hào)獲取驗(yàn)證碼后會(huì)收到一條類似于尊敬的用戶13099999999您好,您的驗(yàn)證碼是6666,這種信息,其實(shí)就是一個(gè)模板,通過改變參數(shù),重復(fù)使用。我們通過國際化資源文件中的占位符,配合MessageSource提供的api也可以實(shí)現(xiàn)。

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

messages.properties,messages_zh_CN.properties

hello=你好:{0} , 你的驗(yàn)證碼為 :{1}

messages_en_US.properties

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

我們?cè)贘sonController中,創(chuàng)建一個(gè)測(cè)試接口

@RequestMapping("/haha")

public String haha() {

return messageSource.getMessage("hello", new Object[]{"zhangsan","123456"}, LocaleContextHolder.getLocale());

}

啟動(dòng)項(xiàng)目直接,訪問?

http://127.0.0.1:8080/haha 可以看到相應(yīng)語言環(huán)境的返回信息

通過Language Switcher切換語言環(huán)境為English - United States,重新訪問?

http://127.0.0.1:8080/haha ,可以看到如下頁面:

支持國際化的枚舉類

既然返回信息可以實(shí)現(xiàn)國際化,那我們的枚舉類同樣也可以實(shí)現(xiàn)國際化咯

創(chuàng)建一個(gè)枚舉類EnumSuccessOrError.java

/**

* 描述:枚舉類舉例

*

* @author zhengql

* @date 2018/9/26 20:52

*/

public enum EnumSuccessOrError {

SUCCESS(0, "操作成功"),

ERROR(1, "操作失敗");

/**

* 返回狀態(tài)碼

*/

private int statusCode;

/**

* 返回狀態(tài)信息

*/

private String statusMsg;

EnumSuccessOrError(int statusCode, String statusMsg) {

this.statusCode = statusCode;

this.statusMsg = statusMsg;

}

/**

* @return the statusCode

*/

public int getStatusCode() {

return statusCode;

}

/**

* @return the statusMsg

*/

public String getStatusMsg() {

return statusMsg;

}

}

如上,剛剛創(chuàng)建的枚舉類是不支持國際化的,我們呢需要改造他,當(dāng)調(diào)用getStatusMsg方法時(shí)根據(jù)語言環(huán)境返回相應(yīng)的國際化字符串??梢詮娜缦聝蓚€(gè)點(diǎn)著手:

getStatusMsg方法改造

資源文件中添加不同語言環(huán)境對(duì)應(yīng)的返回值

先在三個(gè)資源文件中加入不同環(huán)境的返回值:

messages.properties,messages_zh_CN.properties

SUCCESS = 操作成功

ERROR = 操作失敗

messages_en_US.properties

SUCCESS=success

ERROR=error

改造后的枚舉如下:

public enum EnumSuccessOrError {

SUCCESS(0, "SUCCESS"),

ERROR(1, "ERROR");

/**

* 返回狀態(tài)碼

*/

private int statusCode;

/**

* 返回狀態(tài)信息

*/

private String statusMsg;

EnumSuccessOrError(int statusCode, String statusMsg) {

this.statusCode = statusCode;

this.statusMsg = statusMsg;

}

private MessageSource messageSource;

public EnumSuccessOrError setMessageSource(MessageSource messageSource) {

this.messageSource = messageSource;

return this;

}

//通過靜態(tài)內(nèi)部類的方式注入bean,并賦值到枚舉中

@Component

public static class ReportTypeServiceInjector {

@Autowired

private MessageSource messageSource;

@PostConstruct

public void postConstruct() {

for (EnumSuccessOrError rt : EnumSet.allOf(EnumSuccessOrError.class))

rt.setMessageSource(messageSource);

}

}

/**

* @return the statusCode

*/

public int getStatusCode() {

return statusCode;

}

/**

* @return the statusMsg,根據(jù)語言環(huán)境返回國際化字符串

*/

public String getStatusMsg() {

return messageSource.getMessage(statusMsg,null,statusMsg, LocaleContextHolder.getLocale());

}


此時(shí)我們?cè)贘sonController中,再創(chuàng)建一個(gè)測(cè)試接口

@RequestMapping("/enumDemo")

public String enumDemo() {

return EnumSuccessOrError.SUCCESS.getStatusMsg();

}

啟動(dòng)項(xiàng)目直接,訪問 http://127.0.0.1:8080/enumDemo 可以看到相應(yīng)語言環(huán)境的返回信息。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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