Springboot+AOP實(shí)現(xiàn)返回?cái)?shù)據(jù)提示語(yǔ)國(guó)際化的示例代碼
前言
本篇內(nèi)容:
提示語(yǔ)的國(guó)際化返回,自定義多語(yǔ)言。
本文使用aop方式,攔截接口返回的數(shù)據(jù),進(jìn)行轉(zhuǎn)換。
正文
先看這次示例教學(xué)的項(xiàng)目 目錄結(jié)構(gòu):

(當(dāng)然resource里面的i18n文件夾和三個(gè)properties文件也是要我們自己建的,但是 那個(gè)Resource Bundle 不用管,這個(gè)在yml加上對(duì)應(yīng)配置項(xiàng)自動(dòng)生成的。 不清楚的繼續(xù)往下看教學(xué)就好)
開(kāi)始敲(CV)代碼:
pom.xml 依賴:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.68</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
返回碼的枚舉
CodeEnum.java
/**
* @author JCccc
*/
public enum CodeEnum {
SUCCESS(1000, "請(qǐng)求成功"),
FAIL(2000, "請(qǐng)求失敗");
public final int code;
public final String msg;
public Integer getCode() {
return this.code;
}
CodeEnum(int code, String msg) {
this.code = code;
this.msg = msg;
}
public String getMsg() {
return this.msg;
}
}
返回?cái)?shù)據(jù)的簡(jiǎn)單封裝
ResultData.java
import com.test.myi18n.enums.CodeEnum;
import lombok.Data;
/**
* @author JCccc
*/
@Data
public class ResultData<T> {
private Integer code;
private String message;
private T data;
public ResultData(int code, String message) {
this.code = code;
this.message = message;
}
public static ResultData success(CodeEnum codeEnum) {
return new ResultData(codeEnum.code, codeEnum.msg);
}
public static ResultData success(String msg) {
return new ResultData(CodeEnum.SUCCESS.getCode(),msg);
}
}
Locale、 MessageSource的簡(jiǎn)單方法封裝
LocaleMessage.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Component;
import java.util.Locale;
/**
* @author JCccc
*/
@Component
public class LocaleMessage {
@Autowired
private MessageSource messageSource;
public String getMessage(String code){
return this.getMessage(code,new Object[]{});
}
public String getMessage(String code,String defaultMessage){
return this.getMessage(code,null,defaultMessage);
}
public String getMessage(String code,String defaultMessage,Locale locale){ return this.getMessage(code,null,defaultMessage,locale); }
public String getMessage(String code,Locale locale){
return this.getMessage(code,null,"",locale);
}
public String getMessage(String code,Object[] args){ return this.getMessage(code,args,""); }
public String getMessage(String code,Object[] args,Locale locale){
return this.getMessage(code,args,"",locale);
}
public String getMessage(String code,Object[] args,String defaultMessage){ return this.getMessage(code,args, defaultMessage,LocaleContextHolder.getLocale()); }
public String getMessage(String code,Object[]args,String defaultMessage,Locale locale){ return messageSource.getMessage(code,args, defaultMessage,locale); }
}
i18n語(yǔ)言轉(zhuǎn)換工具類
I18nUtils.java
import java.util.Locale;
import com.test.myi18n.message.LocaleMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class I18nUtils {
@Autowired
private LocaleMessage localeMessage;
/**
* 獲取key
*
* @param key
* @return
*/
public String getKey(String key) {
String name = localeMessage.getMessage(key);
return name;
}
/**
* 獲取指定哪個(gè)配置文件下的key
*
* @param key
* @param local
* @return
*/
public String getKey(String key, Locale local) {
String name = localeMessage.getMessage(key, local);
return name;
}
}
接下來(lái)是我們轉(zhuǎn)換的一個(gè)關(guān)鍵環(huán)節(jié), aop方式攔截 controller接口返回的數(shù)據(jù):
LanguageAspect.java
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
/**
* @author JCccc
*/
@Aspect
@Component
@AllArgsConstructor
@ConditionalOnProperty(prefix = "lang", name = "open", havingValue = "true")
public class LanguageAspect {
@Autowired
I18nUtils i18nUtils;
@Pointcut("execution(* com.test.myi18n.controller.*.*(..)))")
public void annotationLangCut() {
}
/**
* 攔截controller層返回的結(jié)果,修改msg字段
*
* @param point
* @param obj
*/
@AfterReturning(pointcut = "annotationLangCut()", returning = "obj")
public void around(JoinPoint point, Object obj) {
Object resultObject = obj;
try {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
//從獲取RequestAttributes中獲取HttpServletRequest的信息
HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
String langFlag = request.getHeader("lang");
if (null != langFlag) {
ResultData r = (ResultData) obj;
String msg = r.getMessage().trim();
if (StringUtils.isNotEmpty(msg)) {
if ("CN".equals(langFlag)) {
Locale locale = Locale.CHINA;
msg = i18nUtils.getKey(msg, locale);
} else if ("EN".equals(langFlag)) {
Locale locale = Locale.US;
msg = i18nUtils.getKey(msg, locale);
} else {
msg = i18nUtils.getKey(msg);
}
}
r.setMessage(msg);
}
} catch (Exception e) {
e.printStackTrace();
//返回原值
obj = resultObject;
}
}
}
代碼簡(jiǎn)單解讀:
1. annotationLangCut 上面切點(diǎn)管控的地址 需要自己改下,改成自己想管控的文件夾路徑2. @ConditionalOnProperty 注解,讀取yml 里面lang開(kāi)頭的配置項(xiàng),key為 open ,value 為true
只有為true,這個(gè)aop攔截才會(huì)生效
3. String langFlag = request.getHeader("lang");
從這句可以看到我這次文章采取的是讓對(duì)接接口方(前端)在header里面?zhèn)魅胄枰褂玫恼Z(yǔ)言flag。 例如傳入 EN (英文),意思就是需要把提示語(yǔ)轉(zhuǎn)為英文。
大家可以結(jié)合自己的項(xiàng)目實(shí)際情況,改為從yml讀取或者從數(shù)據(jù)庫(kù)讀取或者從redis讀取等等都可以。4. ResultData r = (ResultData) obj;
String msg = r.getMessage().trim();
這兩行代碼為了就是把攔截到的obj中的message提示語(yǔ)獲取出來(lái), 如果大家項(xiàng)目的返回?cái)?shù)據(jù)不是我文中使用的 ResultData,則需要自己進(jìn)行魔改調(diào)整。
最后是 三份 mess properties文件:
mess.properties
自定義的返回語(yǔ)= 您好,如果文章對(duì)你有用,請(qǐng)關(guān)注+收藏+評(píng)論
這個(gè)文件按照本文里aop的攔截方式,會(huì)先檢測(cè) 當(dāng)前 的 語(yǔ)言flag值,如果檢測(cè)不到就h會(huì)到
mess.properties 文件里面找。
mess_en_US.properties
請(qǐng)求成功=success
請(qǐng)求失敗=fail
mess_zh_CN.properties
請(qǐng)求成功=請(qǐng)求成功
請(qǐng)求失敗=請(qǐng)求失敗
success=請(qǐng)求成功
fail=請(qǐng)求失敗
最后寫(xiě)個(gè)測(cè)試接口給大家演示一下效果:
@GetMapping("test")
public ResultData test(@RequestParam int testNum) {
if (1==testNum){
return ResultData.success(CodeEnum.SUCCESS);
}
if (2==testNum){
return ResultData.success(CodeEnum.FAIL);
}
if (3==testNum){
return ResultData.success("自定義的返回語(yǔ)");
}
return ResultData.success(CodeEnum.SUCCESS);
}
調(diào)用測(cè)試:


好,就先到這。
到此這篇關(guān)于Springboot+AOP實(shí)現(xiàn)返回?cái)?shù)據(jù)提示語(yǔ)國(guó)際化的示例代碼的文章就介紹到這了,更多相關(guān)Springboot 返回?cái)?shù)據(jù)提示語(yǔ)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot集成I18n國(guó)際化文件在jar包外生效問(wèn)題
- SpringBoot的@GetMapping路徑匹配規(guī)則、國(guó)際化詳細(xì)教程
- SpringBoot實(shí)現(xiàn)前后端分離國(guó)際化的示例詳解
- 史上最佳springboot Locale 國(guó)際化方案
- 基于springboot i18n國(guó)際化后臺(tái)多種語(yǔ)言設(shè)置的方式
- 如何在springboot中實(shí)現(xiàn)頁(yè)面的國(guó)際化
- SpringBoot參數(shù)校驗(yàn)與國(guó)際化使用教程
- SpringBoot實(shí)現(xiàn)國(guó)際化過(guò)程詳解
- SpringBoot 國(guó)際化適配方案使用解決方案
相關(guān)文章
springboot controller無(wú)效的處理方案
這篇文章主要介紹了springboot controller無(wú)效的處理方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10
一文帶你掌握J(rèn)ava?LinkedBlockingQueue
LinkedBlockingQueue?是一個(gè)可選有界阻塞隊(duì)列,這篇文章主要為大家詳細(xì)介紹了Java中LinkedBlockingQueue的實(shí)現(xiàn)原理與適用場(chǎng)景,感興趣的可以了解一下2023-04-04
解決@ResponseBody作用在返回類型為String的方法時(shí)的坑
這篇文章主要介紹了解決@ResponseBody作用在返回類型為String的方法時(shí)的坑,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06
Java 爬蟲(chóng)如何爬取需要登錄的網(wǎng)站
這篇文章主要介紹了Java 爬蟲(chóng)如何爬取需要登錄的網(wǎng)站,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-10-10

