@

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

SpringBoot源码学习系列之Locale自动配置的更多相关文章

  1. SpringBoot源码学习系列之异常处理自动配置

    SpringBoot源码学习系列之异常处理自动配置 1.源码学习 先给个SpringBoot中的异常例子,假如访问一个错误链接,让其返回404页面 在浏览器访问: 而在其它的客户端软件,比如postm ...

  2. SpringBoot源码学习系列之SpringMVC自动配置

    目录 1.ContentNegotiatingViewResolver 2.静态资源 3.自动注册 Converter, GenericConverter, and Formatter beans. ...

  3. SpringBoot源码学习系列之嵌入式Servlet容器

    目录 1.博客前言简单介绍 2.定制servlet容器 3.变换servlet容器 4.servlet容器启动原理 SpringBoot源码学习系列之嵌入式Servlet容器启动原理 @ 1.博客前言 ...

  4. SpringBoot源码学习系列之@PropertySource不支持yaml读取原因

    然后,为什么@PropertySource注解默认不支持?可以简单跟一下源码 @PropertySource源码: 根据注释,默认使用DefaultPropertySourceFactory类作为资源 ...

  5. SpringBoot源码学习系列之启动原理简介

    本博客通过debug方式简单跟一下Springboot application启动的源码,Springboot的启动源码是比较复杂的,本博客只是简单梳理一下源码,浅析其原理 为了方便跟源码,先找个Ap ...

  6. 源码学习系列之SpringBoot自动配置(篇一)

    源码学习系列之SpringBoot自动配置源码学习(篇一) ok,本博客尝试跟一下Springboot的自动配置源码,做一下笔记记录,自动配置是Springboot的一个很关键的特性,也容易被忽略的属 ...

  7. 源码学习系列之SpringBoot自动配置(篇二)

    源码学习系列之SpringBoot自动配置(篇二)之HttpEncodingAutoConfiguration 源码分析 继上一篇博客源码学习系列之SpringBoot自动配置(篇一)之后,本博客继续 ...

  8. SpringBoot源码解析系列文章汇总

    相信我,你会收藏这篇文章的 本篇文章是这段时间撸出来的SpringBoot源码解析系列文章的汇总,当你使用SpringBoot不仅仅满足于基本使用时.或者出去面试被面试官虐了时.或者说想要深入了解一下 ...

  9. Java并发包源码学习系列:阻塞队列BlockingQueue及实现原理分析

    目录 本篇要点 什么是阻塞队列 阻塞队列提供的方法 阻塞队列的七种实现 TransferQueue和BlockingQueue的区别 1.ArrayBlockingQueue 2.LinkedBloc ...

随机推荐

  1. MySQL高级查询之索引创建、删除、增加、修改、慢sql、explain解释sql

    day04数据库 昨日知识点回顾 1.单表操作 1.单表的操作 条件查询的优先级别: where > group by >having > order by > limit; ...

  2. 设计模式:规约模式(Specification-Pattern)

    "其实地上本没有路,走的人多了,也便成了路"--鲁迅<故乡> 这句话很好的描述了设计模式的由来.前辈们通过实践和总结,将优秀的编程思想沉淀成设计模式,为开发者提供了解决 ...

  3. C#线程学习笔记十:async & await入门三

    一.Task.Yield Task.Yield简单来说就是创建时就已经完成的Task,或者说执行时间为0的Task,或者说是空任务,也就是在创建时就将Task的IsCompeted值设置为0. 我们知 ...

  4. 代码的鲁棒性:链表中倒数第k个结点

    题目描述 输入一个链表,输出该链表中倒数第k个结点.例如:输入一个链表,输出该链表中倒数第k个结点.为了符合大多数人的习惯,本题从1开始计数,即链表的尾结点是倒数第1个结点.例如一个链表有6个结点,从 ...

  5. C#Protected和多态(虚方法)

    Protected 在基类中定义后,能被派生类调用,但是不能被其他类调用. virtual 在基类中定义后,在派生类中能被重写. using System; using System.Collecti ...

  6. Qt在Android平台上实现html转PDF的功能

    Qt for Android Qt for Android enables you to run Qt 5 applications Android devices. All Qt modules ( ...

  7. DDD 实战记录——实现「借鉴学习计划」

    「借鉴学习计划」的核心是:复制一份别人的学习计划到自己的计划中,并同步推送学习任务给自己,并且每个操作都要发送通知给对方. 它们的类图如下: 它们的关系是一对多: // Schedule entity ...

  8. HTTP 400 与 SpringMVC的 HttpPutFormContentFilter、FormContentFilter

    前端发送了一个http PUT请求,如下, json_xml: {,},,}},,},,}},},}},,},{,}],,},,}},,,,},,}},},}},,},{,}],,},,}},,},{ ...

  9. Java编程思想——第17章 容器深入研究(一)

    这一章将学习散列机制是如何工作的,以及在使用散列容器时怎么样编写hashCode()和equals()方法. 一.容器分类 先上两张图 来概况完整的容器分类 再细说都为什么会有那些特性. 二.Coll ...

  10. python3装饰器用法示例

    装饰器在编写后台的逻辑时有可能会用到,比方说一个场景:公司的员工想要登录自己公司的考勤记录系统去修改自己的考勤,以前是随便谁都有权限去修改,这样老板不同意了,现在,要在你登录前加一个权限验证的逻辑,如 ...