前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SpringBoot源码学习系列之Locale自动配置

SpringBoot源码学习系列之Locale自动配置

作者头像
SmileNicky
发布2020-01-13 14:57:26
2K0
发布2020-01-13 14:57:26
举报
文章被收录于专栏:Nicky's blogNicky's blog

ok,本博客并非入门博客,建议先看具体实现,参考我的博客:SpringBoot系列之i18n国际化多语言支持教程 之后,再来看本博客

MessageSourceAutoConfiguration是国际化语言i18n的自动配置类,然后本博客简单跟一下源码,看一下SpringBoot是怎么实现对locale,也可以说是国际化语言i18n的自动配置

MessageSourceAutoConfiguration是i18n自动配置很关键的类,跟一下其源码,@ResourceBundleCondition是 MessageSourceAutoConfiguration的一个条件主键,当条件符合时候就自动配置,跟一下这个条件主键的源码,MessageSourceAutoConfiguration.ResourceBundleCondition 源码:

代码语言:javascript
复制
protected static class ResourceBundleCondition extends SpringBootCondition {
		//定义一个map缓存池
		private static ConcurrentReferenceHashMap<String, ConditionOutcome> cache = new ConcurrentReferenceHashMap<>();

		@Override
		public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
		//2.2.1版本spring.messages.basename必须在application.properties配置
			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) {
		//读取ResourceBundle资源文件
			ConditionMessage.Builder message = ConditionMessage.forCondition("ResourceBundle");
			for (String name : StringUtils.commaDelimitedListToStringArray(StringUtils.trimAllWhitespace(basename))) {
				for (Resource resource : getResources(context.getClassLoader(), name)) {
					if (resource.exists()) {
					//匹配resource bundle资源
						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('.', '/');//spring.messages.basename参数值的点号换成斜杆
			try {
				return new PathMatchingResourcePatternResolver(classLoader)
						.getResources("classpath*:" + target + ".properties");
			}
			catch (Exception ex) {
				return NO_RESOURCES;
			}
		}

	}

ok,这个自动配置类还是比较容易理解的,我们可以知道spring.messages.basename配置ResourceBundle资源文件位置,然后这个自动配置类就会扫描全部的ResourceBundle进行分析匹配后实现自动配置,比较容易理解,所以本博客列举一些注意要点

1、spring.messages.cache-duration

  • spring.messages.cache-duration是配置在application.properties的,在2.2.1版本,指定的是s为单位,找到SpringBoot的MessageSourceAutoConfiguration自动配置类
在这里插入图片描述
在这里插入图片描述

2、LocaleResolver 的方法名必须为localeResolver

  • 如下代码,定义一个Locale解析器类,LocaleResolver 的方法名必须为localeResolver,否则会报错
代码语言:javascript
复制
@Bean
    public LocaleResolver localeResolver(){
        CustomLocalResolver localResolver = new CustomLocalResolver();
        localResolver.setDefaultLocale(webMvcProperties.getLocale());
        return localResolver;
    }

原理: 跟一下源码,点进LocaleChangeInterceptor类

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

DispatcherServlet是Spring一个很重要的分发器类,在DispatcherServlet的一个init方法里找到这个LocaleResolver的init方法

在这里插入图片描述
在这里插入图片描述

这个IOC获取的bean类名固定为localeResolver,写例子的时候,我就因为改了bean类名,导致一直报错,跟了源码才知道Bean类名要固定为localeResolver

在这里插入图片描述
在这里插入图片描述

3、默认LocaleResolver

继续跟源码,抛异常的时候,也是会获取默认的LocaleResolver的

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

找到一个properties配置文件,全局搜索

在这里插入图片描述
在这里插入图片描述

找到资源文件,确认,还是默认为AcceptHeaderLocaleResolver

在这里插入图片描述
在这里插入图片描述

所以在SpringBoot中默认的Locale解析器类是AcceptHeaderLocaleResolver

4、指定默认的locale

  • WebMvcAutoConfiguration的自动配置 配置了locale属性的时候,还是选用AcceptHeaderLocaleResolver作为默认的LocaleResolver
代码语言:javascript
复制
spring.mvc.locale=zh_CN

WebMvcAutoConfiguration.localeResolver方法源码,ConditionalOnMissingBean主键的意思是LocaleResolver没有自定义的时候,才作用,ConditionalOnProperty的意思,有配了属性才走这里的逻辑

在这里插入图片描述
在这里插入图片描述

5、localeChangeInterceptor指定传参

  • 拦截器拦截的请求参数默认为locale,要使用其它参数,必须通过拦截器设置 ,eg:localeChangeInterceptor.setParamName("lang");
在这里插入图片描述
在这里插入图片描述

附录:

  • Locale解析器种类 LocalResolver种类有:CookieLocaleResolver(Cookie)、SessionLocaleResolver(会话)、FixedLocaleResolver、AcceptHeaderLocaleResolver(默认)、.etc

具体实现,参考我的博客:SpringBoot系列之i18n国际化多语言支持教程

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-11-26 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、spring.messages.cache-duration
  • 2、LocaleResolver 的方法名必须为localeResolver
  • 3、默认LocaleResolver
  • 4、指定默认的locale
  • 5、localeChangeInterceptor指定传参
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档