• 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国际化多语言支持教程

  • 相关阅读:
    iOS 8以后 定位手动授权问题
    IOS int NSInteger NSNumber区分
    Java基础知识(JAVA集合框架之List与Set)
    Java基础知识(JAVA基本数据类型包装类)
    Java基础知识(JAVA中String、StringBuffer、StringBuilder类的区别)
    Java基础知识(重载和覆盖)
    Java基础知识(抽象类和接口)
    host文件
    天猫页面显示错位
    专题8:javascript函数详解
  • 原文地址:https://www.cnblogs.com/mzq123/p/11936356.html
Copyright © 2020-2023  润新知