springboot国际化

server/2025/1/14 9:40:59/

使用springboot开发程序时,如果有国际市场的需求,一般要考虑国际化,在spring中本身对国际化就有很好的支持,下面介绍如何使用springboot开发国际化服务。
正常来说,引入 spring-boot-starter-web 模块后自动就会包括了国际化支持,所以demo程序引入的依赖包就非常简单:

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.2.9</version>
</parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.30</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></dependency>
</dependencies>

国际化要根据语言环境的不同返回对应的国际化资源内容,一般会定义多个 properties 结尾的资源文件:messages.properties、messages_en_US.properties、messages_zh_CN.properties,分别是默认的配置、英文配置、中文配置。

中文的信息写在 messages_zh_CN.properties 文件中:

hello=\u4f60\u597d\uff0c\u4e16\u754c\uff01

英文的信息写在 messages_en_US.properties 文件中:

hello=hello,world!

国际化文件路径

上面三个配置文件都放在resources资源目录下的i18n文件夹中,并且指定配置文件的前缀messages,所以在application.yml中指定资源文件位置:

server:port: 7777
spring:application:name: test-i18nmessages:basename: i18n.messagescache-duration: 3600encoding: UTF-8lifecycle:timeout-per-shutdown-phase: 45s    # 关闭服务缓冲时间,默认30sjackson:date-format: yyyy-MM-dd HH:mm:sstime-zone: GMT+08

在springboot中,实现国际化是通过 org.springframework.context.MessageSource 实现的,这个类在不指定情况下会根据当前系统的language确认语言环境。而在真实环境中,与前端交互一般是通过请求头中的Accept-Language确认语言环境,这里定义一个拦截器拦截前端传递过来的请求头中包含的语音环境信息,并将这个信息设置到 org.springframework.web.servlet.LocaleResolver 中,这样在后续处理时就可以在上下文中获取到语言信息。
所以开发国际化项目后端代码编写流程:

1、定义Locale相关的配置信息:

java">import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;import java.nio.charset.StandardCharsets;
import java.util.Locale;/*** @Author xingo* @Date 2024/12/11*/
@Configuration
public class LocaleConfig {/*** 默认解析器 其中locale表示默认语言,当请求中未包含语种信息,则设置默认语种* 当前默认为简体中文,zh_CN*/@Beanpublic SessionLocaleResolver localeResolver() {
//        AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();SessionLocaleResolver localeResolver = new SessionLocaleResolver();localeResolver.setDefaultLocale(Locale.SIMPLIFIED_CHINESE);return localeResolver;}@Beanpublic LocalValidatorFactoryBean localValidatorFactoryBean() {LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();// 设置消息源bean.setValidationMessageSource(resourceBundleMessageSource());return bean;}@Bean(name = "messageSource")public MessageSource resourceBundleMessageSource() {ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();messageSource.setDefaultEncoding(StandardCharsets.UTF_8.toString());// 多语言文件messageSource.addBasenames("i18n/messages");// 可以根据业务的不同将国际化信息存放在多个文件中
//        messageSource.addBasenames("i18n/security");
//        messageSource.addBasenames("i18n/oss");
//        messageSource.addBasenames("i18n/excel");return messageSource;}
}

2、定义拦截器处理请求头的语言信息:

java">import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.support.RequestContextUtils;import java.util.Locale;/*** @Author xingo* @Date 2024/12/11*/
@Slf4j
@Component
public class LocaleInterceptor extends LocaleChangeInterceptor {private static final String LOCALE = "Accept-Language";@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {String newLocale = request.getHeader(LOCALE);if (newLocale != null) {LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);try {localeResolver.setLocale(request, response, parseLocaleValue(newLocale));} catch (Exception e) {log.error("LocaleInterceptor error", e);localeResolver.setLocale(request, response, Locale.SIMPLIFIED_CHINESE);}} else {LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);localeResolver.setLocale(request, response, Locale.SIMPLIFIED_CHINESE);}return true;}}

3、将拦截器注入到springboot中:

java">import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;/*** @Author xingo* @Date 2024/12/11*/
@Configuration
@RequiredArgsConstructor
public class WebMvcConfiguration implements WebMvcConfigurer {private final LocaleInterceptor localeInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(localeInterceptor).addPathPatterns("/**");    // 所有的请求都要拦截}@Overridepublic void addCorsMappings(CorsRegistry registry) {registry // 允许所有路径.addMapping("/**")// 允许携带凭证.allowCredentials(true)// 允许所有请求方法.allowedMethods("*")// 允许所有请求域名.allowedOriginPatterns("*")// 允许所有请求头.allowedHeaders("*")// 允许所有响应头.exposedHeaders("*");}
}

以上步骤完成后,就实现了一个国际化系统的基本框架,为了使用方便,还需要定义一个工具类用于获取国际化信息:

java">import lombok.Builder;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Component;import java.util.List;
import java.util.Locale;/*** @Author xingo* @Date 2024/12/11*/
@Slf4j
@Component
public class I18NUtils {public static final List<String> LOCALES = List.of("zh_CN", "en_US");private static MessageSource messageSource;public I18NUtils(MessageSource messageSource) {I18NUtils.messageSource = messageSource;}public static String get(String key) {String i18n = key;try {i18n = messageSource.getMessage(key, null, LocaleContextHolder.getLocale());} catch (Exception ex) {log.warn("[I18NUtils]WithoutArg:{}|{}", key, ex.getMessage());}return i18n;}public static String getCustomLocale(String key, Locale locale) {String i18n = null;try {i18n = messageSource.getMessage(key, null, locale);} catch (Exception ex) {log.error("[I18NUtils]WithoutArgWithLocale:{}", ex.getMessage());}return i18n;}public static String get(String key, Object... arg) {String i18n = null;try {i18n = messageSource.getMessage(key, arg, LocaleContextHolder.getLocale());} catch (Exception ex) {log.error("[I18NUtils]WithoutArg:{}", ex.getMessage());}return i18n;}
}

大功告成!写一个测试接口看看是否符合预期:

java">import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.xingo.config.I18NUtils;/*** @Author xingo* @Date 2024/12/11*/
@RestController
public class TestController {@GetMapping("/hello")public String hello() {System.out.println(LocaleContextHolder.getLocale());return I18NUtils.get("hello");}
}

使用postman请求接口,通过调整请求头中的 Accept-Language 观察返回值!
zh_CN返回值

en_US返回值


http://www.ppmy.cn/server/158248.html

相关文章

Springboot内置Apache Tomcat 安全漏洞(CVE-2024-50379)

背景 大家都知道我们使用Springboot开发后&#xff0c;无需再额外配置tomcat&#xff0c;因为Springboot已经帮我们内置好了tomcat。 这次在线上安全团队就扫出来了我们Springboot服务的tomcat漏洞&#xff1a; 可以看到这是2023年的洞&#xff0c;Apache Tomcat 安全漏洞(…

STM32标准库学习笔记(十)SPI

前言 学习永无止境&#xff01;本篇是嵌入式开发之片上外设SPI&#xff0c;了解基本硬件原理以及通信协议。 注&#xff1a;本文章为学习笔记&#xff0c;部分图片与文字来源于网络/江协科技课程/手册&#xff0c;如侵权请联系&#xff01;谢谢&#xff01; 一、SPI通信概述 1.…

Node.js——path(路径操作)模块

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;正逐渐往全干发展 &#x1f4c3;个人状态&#xff1a; 研发工程师&#xff0c;现效力于中国工业软件事业 &#x1f680;人生格言&#xff1a; 积跬步…

基于Android的校园自助打印系统的设计与实现

博主介绍&#xff1a;java高级开发&#xff0c;从事互联网行业多年&#xff0c;熟悉各种主流语言&#xff0c;精通java、python、php、爬虫、web开发&#xff0c;已经做了多年的设计程序开发&#xff0c;开发过上千套设计程序&#xff0c;没有什么华丽的语言&#xff0c;只有实…

使用 Python 实现自动化办公(邮件、Excel)

目录 一、Python 自动化办公的准备工作 1.1 安装必要的库 1.2 设置邮件服务 二、邮件自动化处理 2.1 发送邮件 示例代码 注意事项 2.2 接收和读取邮件 示例代码 三、Excel 自动化处理 3.1 读取和写入 Excel 文件 示例代码 3.2 数据处理和分析 示例代码 四、综合…

docker的学习

理解 我对docker的理解&#xff1a;docker其实就是一个服务&#xff0c;需要进行启动还有关闭。 对镜像的理解&#xff1a;镜像相当于一个安装包&#xff08;可以理解为压缩文件&#xff0c;所以需要从网络上进行下载&#xff09;&#xff0c;镜像下载完之后就要对其运行。运…

【机器学习:十一、神经网络的数学表达式】

神经网络的数学表达式是机器学习的重要理论基础&#xff0c;通过数学语言描述神经网络的结构和工作原理&#xff0c;有助于理解其运算过程、优化方法和性能改进。以下从背景意义、数学表达的重要性、隐藏层与输出层的数学表达&#xff0c;再到二层神经网络的数学表达&#xff0…

【机器学习:十九、反向传播】

1. 计算图和导数 计算图的概念 计算图&#xff08;Computation Graph&#xff09;是一种有向无环图&#xff0c;用于表示数学表达式中的计算过程。每个节点表示一个操作或变量&#xff0c;每条边表示操作的依赖关系。通过计算图&#xff0c;可以轻松理解和实现反向传播。 计算…