springboot 有很多自动装配类:XXXAutoConfiguration,国际化配置-> MessageSourceAutoConfiguration
@Configuration(proxyBeanMethods = false) * AbstractApplicationContext.MESSAGE_SOURCE_BEAN_NAME = "messageSource" * SearchStrategy.CURRENT:只搜索当前上下文。 * 这里注解表示:如果当前上下文环境中不存在 messageSource 类,就加载本配置文件中的 MessageSource。 @ConditionalOnMissingBean(name = AbstractApplicationContext.MESSAGE_SOURCE_BEAN_NAME, search = SearchStrategy.CURRENT) @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) * 满足 当前配置文件中的ResourceBundleCondition的匹配规则才会加载当前配置文件,详情请看下面具体解释 @Conditional(ResourceBundleCondition.class) @EnableConfigurationProperties public class MessageSourceAutoConfiguration { private static final Resource[] NO_RESOURCES = {}; * 属性配置:basename: i18n/messages(文件位置) * use-code-as-default-message: true(是否使用消息代码作为默认消息,而不是抛出“NoSuchMessageException”。仅在开发过程中推荐false) * always-use-message-format: false(是否总是应用MessageFormat规则,甚至解析没有参数的消息,当前属性可以看出,我们的国际化文件可以写一些可以被解析的字符串,比如:帐号允许长度范围%s-%s) * encoding: UTF-8 (默认就是UTF-8) * cache-duration: PT-1S(国际化文件中的内容可以被缓存起来,如果不填写将永久被缓存,可以根据情况设置具体的过期时间,格式为:Duration,具体可以百度如何配置,获取查看源码【实际为正则表达式】) @Bean @ConfigurationProperties(prefix = "spring.messages") public MessageSourceProperties messageSourceProperties() { return new MessageSourceProperties(); * 这里使用 ResourceBundleMessageSource 作为获取具体值得管理类,如果需要获取外部文件或者更多功能 * 可以使用 ReloadableResourceBundleMessageSource,但这需要重写 MessageSource,和 类注解@ConditionalOnMissingBean 交相呼应。 @Bean public MessageSource messageSource(MessageSourceProperties properties) { ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); if (StringUtils.hasText(properties.getBasename())) { messageSource.setBasenames(StringUtils .commaDelimitedListToStringArray(StringUtils.trimAllWhitespace(properties.getBasename()))); if (properties.getEncoding() != null) { messageSource.setDefaultEncoding(properties.getEncoding().name()); messageSource.setFallbackToSystemLocale(properties.isFallbackToSystemLocale()); Duration cacheDuration = properties.getCacheDuration(); if (cacheDuration != null) { messageSource.setCacheMillis(cacheDuration.toMillis()); messageSource.setAlwaysUseMessageFormat(properties.isAlwaysUseMessageFormat()); messageSource.setUseCodeAsDefaultMessage(properties.isUseCodeAsDefaultMessage()); return messageSource; * 这里规则为:获取环境变量spring.messages.basename(默认为messages),也就是创建国际化文件的位置 * 去查看是否存在,如果不存在,则没有匹配成功,配置类不加载(不具有国际化功能),反之加载配置文件。 protected static class ResourceBundleCondition extends SpringBootCondition { private static ConcurrentReferenceHashMap<String, ConditionOutcome> cache = new ConcurrentReferenceHashMap<>(); @Override public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { String basename = context.getEnvironment().getProperty("spring.messages.basename", "messages"); ConditionOutcome outcome = cache.get(basename); if (outcome == null) { outcome = getMatchOutcomeForBasename(context, basename); cache.put(basename, outcome); return outcome; private ConditionOutcome getMatchOutcomeForBasename(ConditionContext context, String basename) { ConditionMessage.Builder message = ConditionMessage.forCondition("ResourceBundle"); for (String name : StringUtils.commaDelimitedListToStringArray(StringUtils.trimAllWhitespace(basename))) { for (Resource resource : getResources(context.getClassLoader(), name)) { if (resource.exists()) { return ConditionOutcome.match(message.found("bundle").items(resource)); return ConditionOutcome.noMatch (message.didNotFind("bundle with basename " + basename).atAll()); private Resource[] getResources(ClassLoader classLoader, String name) { String target = name.replace('.', '/'); try { return new PathMatchingResourcePatternResolver(classLoader) .getResources("classpath*:" + target + ".properties"); catch (Exception ex) { return NO_RESOURCES;3. 获取值
配置类加载好了,那么接下来如何获取值呢?
spring 提供了两种总方式:
LocaleContextHolder.getLocale()
查看源码:重点看 如何获取 LocaleContext
* org.springframework.context.i18n.LocaleContextHolder private static final ThreadLocal<LocaleContext> localeContextHolder = new NamedThreadLocal<>("LocaleContext"); private static final ThreadLocal<LocaleContext> inheritableLocaleContextHolder = new NamedInheritableThreadLocal<>("LocaleContext"); public static Locale getLocale() { return getLocale(getLocaleContext()); public static Locale getLocale(@Nullable LocaleContext localeContext) { if (localeContext != null) { Locale locale = localeContext.getLocale(); if (locale != null) { return locale; return (defaultLocale != null ? defaultLocale : Locale.getDefault()); * 这里看出 实际上是从 ThreadLocal 中获取,那么就需要直到是什么时候放入 * ThreadLocal 中。我们继续查看 setLocaleContext 方法 @Nullable public static LocaleContext getLocaleContext() { LocaleContext localeContext = localeContextHolder.get(); if (localeContext == null) { localeContext = inheritableLocaleContextHolder.get(); return localeContext; * 那么是什么时候调用次方法得,我们需要使用debug模式验证一下。具体查看下面解析。 public static void setLocaleContext(@Nullable LocaleContext localeContext, boolean inheritable) { if (localeContext == null) { resetLocaleContext(); else { if (inheritable) { inheritableLocaleContextHolder.set(localeContext); localeContextHolder.remove(); else { localeContextHolder.set(localeContext); inheritableLocaleContextHolder.remove();debug追踪
- 进入过滤器RequestContextFilter.initContextHolders()方法,获取request头中的accept-language来初始化 locale(默认是zh_CN),此时为SimpleLocaleContext
实际就是将国际化上下文localeContext放入 ThreadLocal,再使用的时候取出来。
- 进入DispatcherServlet.buildLocaleContext()方法,此时注意到LocaleContextResolver 进入我们的视野
解析器(LocaleResolver)的配置
查看源码得知:localeResolver 来自项目初始化,会获取LocaleResolver 实例注入。此时我们就需要创建一个属于我们自己的解析器。HeaderLocaleContextResolver
public static final String LOCALE_RESOLVER_BEAN_NAME = "localeResolver"; private void initLocaleResolver(ApplicationContext context) { try { this.localeResolver = context.getBean(LOCALE_RESOLVER_BEAN_NAME, LocaleResolver.class); if (logger.isTraceEnabled()) { logger.trace("Detected " + this.localeResolver); else if (logger.isDebugEnabled()) { logger.debug("Detected " + this.localeResolver.getClass().getSimpleName()); catch (NoSuchBeanDefinitionException ex) { // We need to use the default. this.localeResolver = getDefaultStrategy(context, LocaleResolver.class); if (logger.isTraceEnabled()) { logger.trace("No LocaleResolver '" + LOCALE_RESOLVER_BEAN_NAME + "': using default [" + this.localeResolver.getClass().getSimpleName() + "]");HeaderLocaleContextResolver.resolveLocaleContext() 设置我们自定义的LocaleContext放入ThreadLocal中。
package com.wx.wxcommonlocale.support.i18n; * HeaderLocaleContextResolver * 通过给定的请求解析当前地区上下文。这主要用于框架级处理; * 考虑使用{@link org.springframework.web.servlet.support.RequestContextUtils} * 或{@link org.springframework.web.servlet.support.RequestContext} * 用于应用程序级访问当前地区和/或时区。返回的上下文可能是 * {@link org.springframework.context.i18n。TimeZoneAwareLocaleContext}, * 包含一个地区和相关的时区信息。简单地应用{@code instanceof}检查并相应地进行向下转换。 * 自定义解析器实现还可以在返回的上下文中返回额外的设置,这些设置同样可以通过向下类型转换访问。 @Override public LocaleContext resolveLocaleContext(final HttpServletRequest request) { return new TimeZoneAwareLocaleContext() { @Override @Nullable public Locale getLocale() { Object attribute = request.getAttribute(localeAttributeName); return attribute != null ? (Locale) attribute : getDefaultLocale(); @Override @Nullable public TimeZone getTimeZone() { Object attribute = request.getAttribute(timeZoneAttributeName); return attribute != null ? (TimeZone) attribute : getDefaultTimeZone();接下来继续追踪,进入FrameworkServlet.processRequest()方法的initContextHolders()将上一步自定义的国际化上下文放入ThreadLocal中。【DispatcherServlet 继承了 FrameworkServlet,在processRequest方法中,调用上一步buildLocaleContext()方法】
* 将自定的 上下文 放入 当前线程中。 private void initContextHolders(HttpServletRequest request, @Nullable LocaleContext localeContext, @Nullable RequestAttributes requestAttributes) { if (localeContext != null) { LocaleContextHolder.setLocaleContext(localeContext, this.threadContextInheritable); if (requestAttributes != null) { RequestContextHolder.setRequestAttributes(requestAttributes, this.threadContextInheritable);此时在看LocaleContextHolder.getLocale()方法如何获取值:实际上是从 自定义的方法中 获取。
package com.wx.wxcommonlocale.support.i18n; @Override public LocaleContext resolveLocaleContext(final HttpServletRequest request) { return new TimeZoneAwareLocaleContext() { @Override @Nullable public Locale getLocale() { * 这里怎么来的?为什么要这样获取呢?请看下面解析。【使用拦截器实现】 Object attribute = request.getAttribute(localeAttributeName); return attribute != null ? (Locale) attribute : getDefaultLocale(); @Override @Nullable public TimeZone getTimeZone() { Object attribute = request.getAttribute(timeZoneAttributeName); return attribute != null ? (TimeZone) attribute : getDefaultTimeZone();拦截器的配置
当过滤器执行完成,就要执行拦截器的代码,这里可以看到,是获取自定义的头getParamName()【locale】,来判断是那种语言。
package com.wx.wxcommonlocale.support.i18n; @Slf4j public class HeaderLocaleChangeInterceptor extends LocaleChangeInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException { Locale locale = null; TimeZone timeZone = null; //从请求头中获取信息格式:zh_CN Asia/Shanghai zh_CN GMT+8 String newLocale = request.getHeader(getParamName()); ... //****请看下文解析 LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request); if (localeResolver == null) { throw new IllegalStateException( "No LocaleResolver found: not in a DispatcherServlet request?"); try { //设置地区**** localeResolver.setLocale(request, response, locale); if(locale != null){ request.setAttribute(HeaderLocaleContextResolver.LOCALE_REQUEST_ATTRIBUTE_NAME,locale); //设置区时 if(timeZone != null){ request.setAttribute(HeaderLocaleContextResolver.TIME_ZONE_REQUEST_ATTRIBUTE_NAME,timeZone); ... // Proceed in any case. return true;其中RequestContextUtils.getLocaleResolver(request); 从截图中可以看到,是在请求时,将我们自定义的上下文也放入了 request 域中。
@Nullable public static LocaleResolver getLocaleResolver(HttpServletRequest request) { return (LocaleResolver) request.getAttribute(DispatcherServlet.LOCALE_RESOLVER_ATTRIBUTE);localeResolver.setLocale(request, response, locale); 具体查看自定义上下文(HeaderLocaleContextResolver)的实现。
* 设置当前地区上下文为给定的一个,可能包括一个地区和相关的时区信息。 * @param request 用于修改区域设置的请求 * @param response 用于区域设置修改的响应 * @param localeContext 新的语言环境上下文,或{@code null}来清除语言环境 * @throws UnsupportedOperationException,如果LocaleResolver实现不支持动态更改地区或时区 * @see #setLocale(HttpServletRequest, HttpServletResponse, Locale) * @see org.springframework.context.i18n.SimpleLocaleContext * @see org.springframework.context.i18n.SimpleTimeZoneAwareLocaleContext @Override public void setLocaleContext(HttpServletRequest request, HttpServletResponse response, LocaleContext localeContext) { Locale locale = null; TimeZone timeZone = null; if (localeContext != null) { locale = localeContext.getLocale(); if (localeContext instanceof TimeZoneAwareLocaleContext) { timeZone = ((TimeZoneAwareLocaleContext) localeContext).getTimeZone(); //设置响应头,微服务之间传递 response.setHeader (getLocaleHeadName(), (locale != null ? locale.toString() : "-") + (timeZone != null ? ' ' + timeZone.getID() : "")); //***** request.setAttribute(localeAttributeName, (locale != null ? locale : getDefaultLocale())); //**** request.setAttribute(timeZoneAttributeName, (timeZone != null ? timeZone : getDefaultTimeZone())); @Override public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) { TimeZone timeZone = (TimeZone) request.getAttribute(HeaderLocaleContextResolver.TIME_ZONE_REQUEST_ATTRIBUTE_NAME); setLocaleContext(request, response, (locale != null ? timeZone != null ? new SimpleTimeZoneAwareLocaleContext(locale, timeZone) : new SimpleLocaleContext(locale) : null));其中request.setAttribute(localeAttributeName,(locale != null ? locale : getDefaultLocale()))代码正好解释了这里的问题。
这个介绍完了
RequestContextUtils.getLocale(request)
还是获取自定义的 国际化上下文,调用resolveLocale()方法获取Locale。
继承关系【HeaderLocaleContextResolver extends AbstractLocaleContextResolver】
具体查看HeaderLocaleContextResolver .resolveLocaleContext()方法,上面有介绍
实则还是从 request 域中获取值。
说白了就是 从 拦截器中 赋值。
从上面介绍可以知道:我们需要一个拦截器:用来获取请求头中的语言,放入request 域中。
还需要一个国际化上下文解析器:将上下文放入 ThreadLocal 中。
4. 应用
4.1 配置文件
spring: messages: # 默认 messages, 这里我们多了一层目录i18n basename: i18n/messages # 如果默认 false, 则会出现匹配不到就会跑异常(NoSuchMessageException)的情况 use-code-as-default-message: true # 是否总是应用MessageFormat规则,即使是没有参数的消息也要解析, 默认 false always-use-message-format: false4.2 WxLocaleConfigs
@Configuration @Slf4j public class WxLocaleConfigs { private final String LOCAL_HEAD_NAME = "locale"; @Bean public LocaleResolver localeResolver(final MessageSource messageSource) { I18nUtils.setMessageSource(messageSource); HeaderLocaleContextResolver localeResolver = new HeaderLocaleContextResolver(); localeResolver.setLocaleHeadName(LOCAL_HEAD_NAME); localeResolver.setDefaultLocale(Locale.SIMPLIFIED_CHINESE); return localeResolver; @Bean public WebMvcConfigurer localeInterceptor() { return new WebMvcConfigurer() { @Override public void addInterceptors(InterceptorRegistry registry) { HeaderLocaleChangeInterceptor localeInterceptor = new HeaderLocaleChangeInterceptor(); localeInterceptor.setParamName(LOCAL_HEAD_NAME); registry.addInterceptor(localeInterceptor).order(-1);HeaderLocaleContextResolver
public class HeaderLocaleContextResolver extends AbstractLocaleContextResolver { * 保存区域设置的会话属性的名称。 * 仅在内部使用此实现。 * 使用{@code RequestContext(Utils).getLocale()} * 在控制器或视图中检索当前区域设置。 * @see org.springframework.web.servlet.support.RequestContext#getLocale * @see org.springframework.web.servlet.support.RequestContextUtils#getLocale public static final String LOCALE_REQUEST_ATTRIBUTE_NAME = HeaderLocaleContextResolver.class.getName() + ".LOCALE"; public static final String TIME_ZONE_REQUEST_ATTRIBUTE_NAME = HeaderLocaleContextResolver.class.getName() + ".TIME_ZONE"; private String localeAttributeName = LOCALE_REQUEST_ATTRIBUTE_NAME; private String timeZoneAttributeName = TIME_ZONE_REQUEST_ATTRIBUTE_NAME; private String localeHeadName; public String getLocaleHeadName() { return localeHeadName; public void setLocaleHeadName(String localeHeadName) { this.localeHeadName = localeHeadName; * 通过给定的请求解析当前地区上下文。这主要用于框架级处理; * 考虑使用{@link org.springframework.web.servlet.support.RequestContextUtils} * 或{@link org.springframework.web.servlet.support.RequestContext} * 用于应用程序级访问当前地区和/或时区。返回的上下文可能是 * {@link org.springframework.context.i18n。TimeZoneAwareLocaleContext}, * 包含一个地区和相关的时区信息。简单地应用{@code instanceof}检查并相应地进行向下转换。 * 自定义解析器实现还可以在返回的上下文中返回额外的设置,这些设置同样可以通过向下类型转换访问。 * @param request 解析地区上下文的请求 * @see #resolveLocale(HttpServletRequest) * @see org.springframework.web.servlet.support.RequestContextUtils#getLocale * @see org.springframework.web.servlet.support.RequestContextUtils#getTimeZone @Override public LocaleContext resolveLocaleContext(final HttpServletRequest request) { return new TimeZoneAwareLocaleContext() { @Override @Nullable public Locale getLocale() { Object attribute = request.getAttribute(localeAttributeName); return attribute != null ? (Locale) attribute : getDefaultLocale(); @Override @Nullable public TimeZone getTimeZone() { Object attribute = request.getAttribute(timeZoneAttributeName); return attribute != null ? (TimeZone) attribute : getDefaultTimeZone(); * 设置当前地区上下文为给定的一个,可能包括一个地区和相关的时区信息。 * @param request 用于修改区域设置的请求 * @param response 用于区域设置修改的响应 * @param localeContext 新的语言环境上下文,或{@code null}来清除语言环境 * @throws UnsupportedOperationException,如果LocaleResolver实现不支持动态更改地区或时区 * @see #setLocale(HttpServletRequest, HttpServletResponse, Locale) * @see org.springframework.context.i18n.SimpleLocaleContext * @see org.springframework.context.i18n.SimpleTimeZoneAwareLocaleContext @Override public void setLocaleContext(HttpServletRequest request, HttpServletResponse response, LocaleContext localeContext) { Locale locale = null; TimeZone timeZone = null; if (localeContext != null) { locale = localeContext.getLocale(); if (localeContext instanceof TimeZoneAwareLocaleContext) { timeZone = ((TimeZoneAwareLocaleContext) localeContext).getTimeZone(); //设置响应头,微服务之间传递 response.setHeader(getLocaleHeadName(), (locale != null ? locale.toString() : "-") + (timeZone != null ? ' ' + timeZone.getID() : "")); request.setAttribute(localeAttributeName, (locale != null ? locale : getDefaultLocale())); request.setAttribute(timeZoneAttributeName, (timeZone != null ? timeZone : getDefaultTimeZone())); @Override public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) { TimeZone timeZone = (TimeZone) request.getAttribute(HeaderLocaleContextResolver.TIME_ZONE_REQUEST_ATTRIBUTE_NAME); setLocaleContext(request, response, (locale != null ? timeZone != null ? new SimpleTimeZoneAwareLocaleContext(locale, timeZone) : new SimpleLocaleContext(locale) : null));HeaderLocaleChangeInterceptor
@Slf4j public class HeaderLocaleChangeInterceptor extends LocaleChangeInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException { Locale locale = null; TimeZone timeZone = null; //从请求头中获取信息格式:zh_CN Asia/Shanghai zh_CN GMT+8 String newLocale = request.getHeader(getParamName()); if (newLocale != null) { //过滤不需要变化的方法 if (checkHttpMethod(request.getMethod())) { String localePart = newLocale; String timeZonePart = null; int spaceIndex = localePart.indexOf(' '); if (spaceIndex != -1) { localePart = newLocale.substring(0, spaceIndex); timeZonePart = newLocale.substring(spaceIndex + 1); try { locale = (!"-".equals(localePart) ? parseLocaleValue(localePart) : null); if (!StringUtils.isEmpty(timeZonePart)) { timeZone = StringUtils.parseTimeZoneString(timeZonePart); } catch (IllegalArgumentException ex) { if (request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) != null) { // Error dispatch: ignore locale/timezone parse exceptions log.info("ignore locale/timezone parse exceptions"); } else { throw new IllegalStateException("Invalid locale Header '" + getParamName() + "' with value [" + newLocale + "]: " + ex.getMessage()); LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request); if (localeResolver == null) { throw new IllegalStateException( "No LocaleResolver found: not in a DispatcherServlet request?"); try { //设置地区 localeResolver.setLocale(request, response, locale); if(locale != null){ request.setAttribute(HeaderLocaleContextResolver.LOCALE_REQUEST_ATTRIBUTE_NAME,locale); //设置区时 if(timeZone != null){ request.setAttribute(HeaderLocaleContextResolver.TIME_ZONE_REQUEST_ATTRIBUTE_NAME,timeZone); catch (IllegalArgumentException ex) { if (isIgnoreInvalidLocale()) { if (logger.isDebugEnabled()) { logger.debug("Ignoring invalid locale value [" + newLocale + "]: " + ex.getMessage()); else { throw ex; // Proceed in any case. return true; private boolean checkHttpMethod(String currentMethod) { String[] configuredMethods = getHttpMethods(); if (ObjectUtils.isEmpty(configuredMethods)) { return true; for (String configuredMethod : configuredMethods) { if (configuredMethod.equalsIgnoreCase(currentMethod)) { return true; return false;locale 国际化配置(springboot)1. 创建文件1.1 创建 bundle1.2 添加文件名及语言1.3 文本编写2. springboot自带配置类解析3. 获取值**LocaleContextHolder.getLocale()**debug追踪**解析器(LocaleResolver)的配置**拦截器的配置RequestContextUtils.getLocale(request)总结4. 应用4.1 配置文件4.2 WxLocaleConfigs附录:**HeaderLocaleCon
- spring boot 2.3.3.RELEASE
- nacos
- geteway
- oauth2
- cache(spring+caffeine)
- mybaits
国际化(internationalization)是设计和制造容易适应不同区域要求的产品的一种方式。它要求从产品中抽离所有地域语言,国家/地区和文化相关的元素。换言之,应用程序的功能和代码设计考虑在不同地区运行的需要,其代码简化了不同本地版本的生产。开发这样的程序的过程,就称为国际化。 那么当我们使用Spring Boot如何进行国际化呢?那么当你读完这篇文章你会学到如下知识:可以发现,我点击下方的english标签则整体字体切换为英文 点击下方的中文标签则整体字体切换为中文 此篇文章就是来实现这个功能的,具体怎么做,我们一步一步做。 第一步:编写国际化配置文件 1.首先我们先解决idea的properties的编码问题 如下图所示设置 2.在resources资源文件下......目录1. 设置项目编码UTF82. 在resources目录下新建i18n文件夹及语言配置文件3. 指出国际化相关文件的位置4. 展示页面5. 使用按钮切换中英文页面5.1 新建html页面5.2 实现LocaleResolver 接口5.3 放入Bean 1. 设置项目编码UTF8 英文界面搜索File Encodings, 中文界面搜索文件编码。 2. 在resources目录下新建i18...C语言头文件 LOCALE.HC语言头文件 LOCALE.HC语言头文件 LOCALE.HC语言头文件 LOCALE.HC语言头文件 LOCALE.HC语言头文件 LOCALE.HC语言头文件 LOCALE.HC语言头文件 LOCALE.HC语言头文件 LOCALE.HC语言头文件 LOCALE.HC语言头文件 LOCALE.HC语言头文件 LOCALE.HC语言头文件 LOCALE.HC语言头文件 LOCALE.HC语言头文件 LOCALE.HC语言头文件 LOCALE.HC语言头文件 LOCALE.HC语言头文件 LOCALE.HC语言头文件 LOCALE.HC语言头文件 LOCALE.HC语言头文件 LOCALE.HC语言头文件 LOCALE.HC语言头文件 LOCALE.HC语言头文件 LOCALE.HC语言头文件 LOCALE.HC语言头文件 LOCALE.HC语言头文件 LOCALE.HC语言头文件 LOCALE.HC语言头文件 LOCALE.HC语言头文件 LOCALE.HC语言头文件 LOCALE.HC语言头文件 LOCALE.HC语言头文件 LOCALE.HC语言头文Spring Boot支持本地化消息,这样你的应用程序就可以满足使用不同语言首选项的用户。 Spring Boot会在类路径的根目录中查找message资源包的存在。 当配置的资源包的默认属性文件可用时(messages.properties默认)。 如果资源包只包含特定于语言的属性文件,则需要添加默认值。 如果没有找到与任何配置的基本名称匹配的属性文件,则不会有自动配置的MessagSpring在webmvc依赖包下提供了支持国际化的i18n包,支持根据请求中不同语言环境标志位来动态改变当前的语言环境,同时可以支持配置多个不同的语言资源配置,并自动根据当前的语言环境动态读取不同的资源配置值 代码如下: i18包类结构: 由图可见,一共提供了四种支持国际化的实现类,分别是AcceptHeaderLocaleResolver、CookieLocaleResolver、FixedLocaleResolver和SessionLocaleResolver类,这些类都实现了Lo...Spring Boot 支持国际化,可以通过配置来实现。下面是一个简单的示例: 1. 在 src/main/resources 目录下创建 i18n 目录,在该目录下创建 messages.properties 文件,并填写需要国际化的文本,例如: hello=Hello 2. 在 messages.properties 文件所在目录下创建 messages_zh_CN.properties 文件,填写中文翻译,例如: hello=你好 3. 在 Spring Boot 配置文件 application.properties 中添加如下配置: spring.mvc.locale=zh_CN spring.messages.basename=i18n/messages 其中,`spring.mvc.locale` 指定默认语言为中文,`spring.messages.basename` 指定国际化文件的前缀,Spring Boot 会自动加载 messages.properties 和 messages_zh_CN.properties 文件。 4. 在代码中使用国际化文本,例如: ```java @Controller public class HelloController { @Autowired private MessageSource messageSource; @RequestMapping("/hello") @ResponseBody public String hello(@RequestHeader("Accept-Language") String language) { Locale locale = LocaleContextHolder.getLocale(); return messageSource.getMessage("hello", null, locale); 在上面的例子中,我们使用 `MessageSource` 接口来获取国际化文本,`LocaleContextHolder.getLocale()` 方法获取当前的语言环境。 5. 启动应用程序,访问 /hello 接口,可以看到返回的文本为:"你好"。 以上就是 Spring Boot 国际化的简单实现方法。