First look at the project directory structure of this sample teaching:
(Of course, the i18n folder and three properties files in the resource are also We need to build it ourselves, but we don’t need to worry about the Resource Bundle. This is automatically generated by adding the corresponding configuration items to the yml. If you are not sure, just continue to read the tutorial)
Start typing (CV) code:
pom.xml Dependencies:
<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>
Return code enumeration
CodeEnum.java
/** * @author JCccc */ public enum CodeEnum { SUCCESS(1000, "请求成功"), FAIL(2000, "请求失败"); 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; } }
Return data Simple encapsulation
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's simple method encapsulation
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 Language Conversion Tool Class
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; } /** * 获取指定哪个配置文件下的key * * @param key * @param local * @return */ public String getKey(String key, Locale local) { String name = localeMessage.getMessage(key, local); return name; } }
The next step is a key step in our conversion. The aop method intercepts the data returned by the controller interface:
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层返回的结果,修改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; } } }
Simple interpretation of the code:
1. The address of the annotationLangCut cutoff control needs to be changed by yourself to the folder you want to control. Path2. @ConditionalOnProperty annotation, read the configuration items starting with lang in the yml, the key is open, the value is true
Only if it is true, this aop interception will take effect
3. String langFlag = request.getHeader("lang");
You can see from this sentence that what I adopted in this article is to let the docking interface party (front-end) pass in the language flag that needs to be used in the header. For example, passing in EN (English) means that the prompt language needs to be converted into English.
You can combine the actual situation of your project and change it to read from yml or read from the database or read from redis, etc.4. ResultData r = (ResultData) obj;
String msg = r.getMessage().trim();
The purpose of these two lines of code is to put the intercepted obj into Get the message prompt. If the return data of your project is not the ResultData used in my article, you need to make magic adjustments yourself.
Finally, there are three mess properties files:
mess.properties
Customized return language = Hello, if the article is useful to you, Please pay attention to the favorite comments
This file will first detect the current language flag value according to the aop interception method in this article. If it is not detected, it will be found in the
mess.properties file.
mess_en_US.properties
Request success=success
Request failure=fail
mess_zh_CN.properties
Request success = Request success
Request failure = Request failure
success = Request success
fail = Request failure
Finally write a test interface to demonstrate the effect for everyone:
@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("自定义的返回语"); } return ResultData.success(CodeEnum.SUCCESS); }
Call test:
The above is the detailed content of How Springboot+AOP implements internationalization of return data prompts. For more information, please follow other related articles on the PHP Chinese website!