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

时间:2019-11-26
本文章向大家介绍SpringBoot源码学习系列之Locale自动配置,主要包括SpringBoot源码学习系列之Locale自动配置使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

@
MessageSourceAutoConfiguration是国际化语言i18n的自动配置类

MessageSourceAutoConfiguration.ResourceBundleCondition 源码:

protected static class ResourceBundleCondition extends SpringBootCondition {
        //定义一个map缓存池
        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()) {
                    //匹配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,这个自动配置类还是比较容易理解的,所以本博客列举一些注意要点

1、spring.messages.cache-duration

  • spring.messages.cache-duration在2.2.1版本,指定的是s为单位,找到SpringBoot的MessageSourceAutoConfiguration自动配置类

2、LocaleResolver 的方法名必须为localeResolver

  • 如下代码,LocaleResolver 的方法名必须为localeResolver,否则会报错
@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

4、指定默认的locale

  • WebMvcAutoConfiguration的自动配置
    配置了locale属性的时候,还是选用AcceptHeaderLocaleResolver作为默认的LocaleResolver
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国际化多语言支持教程

原文地址:https://www.cnblogs.com/mzq123/p/11936356.html