Spring系列第26篇:国际化详解

本文详细介绍了Java面试中可能遇到的Spring国际化配置问题,包括ResourceBundleMessageSource的使用,动态参数处理,ReloadableResourceBundleMessageSource的缓存策略,以及如何通过StaticMessageSource从数据库获取国际化信息。还涵盖了Bean命名规则和自定义bean使用国际化的方法。
摘要由CSDN通过智能技术生成

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门,即可获取!

com/javacode2018/lesson002/demo19/

message.properties

name=您的姓名

personal_introduction=默认个人介绍:{0},{1}

这个文件名称没有指定Local信息,当系统找不到的时候会使用这个默认的

message_zh_CN.properties:中文【中国】

name=姓名

personal_introduction=个人介绍:{0},{1},{0}

message_en_GB.properties:英文【英国】

name=Full name

personal_introduction=personal_introduction:{0},{1},{0}

spring中注册国际化的bean

注意必须是MessageSource类型的,bean名称必须为messageSource,此处我们就使用ResourceBundleMessageSource这个类

package com.javacode2018.lesson002.test19.demo1;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.context.support.ResourceBundleMessageSource;

@Configuration

public class MainConfig1 {

@Bean

public ResourceBundleMessageSource messageSource() {

ResourceBundleMessageSource result = new ResourceBundleMessageSource();

//可以指定国际化化配置文件的位置,格式:路径/文件名称,注意不包含【语言_国家.properties】含这部分

result.setBasenames(“com/javacode2018/lesson002/demo19/message”); //@1

return result;

}

}

@1:这个地方的写法需要注意,可以指定国际化化配置文件的位置,格式:路径/文件名称,注意不包含**【语言_国家.properties】**含这部分

来个测试用例

package com.javacode2018.lesson002.test19;

import com.javacode2018.lesson002.test19.demo1.MainConfig1;

import org.junit.Test;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.util.Locale;

public class MessageSourceTest {

@Test

public void test1() {

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();

context.register(MainConfig1.class);

context.refresh();

//未指定Locale,此时系统会取默认的locale对象,本地默认的值中文【中国】,即:zh_CN

System.out.println(context.getMessage(“name”, null, null));

System.out.println(context.getMessage(“name”, null, Locale.CHINA)); //CHINA对应:zh_CN

System.out.println(context.getMessage(“name”, null, Locale.UK)); //UK对应en_GB

}

}

运行输出

您的姓名

您的姓名

Full name

第一行未指定Locale,此时系统会取默认的locale对象,本地默认的值中文【中国】,即:zh_CN,所以会获取到message_zh_CN.properties中的内容。

后面2行,都指定了Locale对象,找到对应的国际化文件,取值。

动态参数使用

注意配置文件中的personal_introduction,个人介绍,比较特别,包含了{0},{1},{0}这样一部分内容,这个就是动态参数,调用getMessage的时候,通过第二个参数传递过去,来看一下用法:

@Test

public void test2() {

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();

context.register(MainConfig1.class);

context.refresh();

//未指定Locale,此时系统会取默认的,本地电脑默认的值中文【中国】,即:zh_CN

System.out.println(context.getMessage(“personal_introduction”, new String[]{“spring高手”, “java高手”}, Locale.CHINA)); //CHINA对应:zh_CN

System.out.println(context.getMessage(“personal_introduction”, new String[]{“spring”, “java”}, Locale.UK)); //UK对应en_GB

}

运行输出

默认个人介绍:spring高手,java高手

personal_introduction:spring,java,spring

监控国际化文件的变化


ReloadableResourceBundleMessageSource这个类,功能和上面案例中的ResourceBundleMessageSource类似,不过多了个可以监控国际化资源文件变化的功能,有个方法用来设置缓存时间:

public void setCacheMillis(long cacheMillis)

-1:表示永远缓存

0:每次获取国际化信息的时候,都会重新读取国际化文件

大于0:上次读取配置文件的时间距离当前时间超过了这个时间,重新读取国际化文件

还有个按秒设置缓存时间的方法setCacheSeconds,和setCacheMillis类似

下面我们来案例

package com.javacode2018.lesson002.test19.demo2;

import org.springframework.context.MessageSource;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.context.support.ReloadableResourceBundleMessageSource;

@Configuration

public class MainConfig2 {

@Bean

public MessageSource messageSource() {

ReloadableResourceBundleMessageSource result = new ReloadableResourceBundleMessageSource();

result.setBasenames(“com/javacode2018/lesson002/demo19/message”);

//设置缓存时间1000毫秒

result.setCacheMillis(1000);

return result;

}

}

message_zh_CN.properties中新增一行内容

address=上海

对应的测试用例

@Test

public void test3() throws InterruptedException {

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();

context.register(MainConfig2.class);

context.refresh();

//输出2次

for (int i = 0; i < 2; i++) {

System.out.println(context.getMessage(“address”, null, Locale.CHINA));

TimeUnit.SECONDS.sleep(5);

}

}

上面有个循环,当第一次输出之后,修改一下message_zh_CN.properties中的address为上海松江,最后运行结果如下:

上海

上海松江

使用注意:线上环境,缓存时间最好设置大一点,性能会好一些。

国际化信息存在db中


上面我们介绍了一个类:StaticMessageSource,这个类它允许通过编程的方式提供国际化信息,我们通过这个类来实现从db中获取国际化信息的功能。

这个类中有2个方法比较重要:

public void addMessage(String code, Locale locale, String msg);

public void addMessages(Map<String, String> messages, Locale locale);

通过这两个方法来添加国际化配置信息。

下面来看案例

自定义一个StaticMessageSource类

package com.javacode2018.lesson002.test19.demo3;

import org.springframework.beans.factory.InitializingBean;

import org.springframework.context.support.StaticMessageSource;

import java.util.Locale;

public class MessageSourceFromDb extends StaticMessageSource implements InitializingBean {

@Override

public void afterPropertiesSet() throws Exception {

//此处我们在当前bean初始化之后,模拟从db中获取国际化信息,然后调用addMessage来配置国际化信息

this.addMessage(“desc”, Locale.CHINA, “我是从db来的信息”);

this.addMessage(“desc”, Locale.UK, “MessageSource From Db”);

}

}

上面的类实现了spring的InitializingBean接口,重写了接口中干掉afterPropertiesSet方法,这个方法会在当前bean初始化之后调用,在这个方法中模拟从db中获取国际化信息,然后调用addMessage来配置国际化信息

来个spring配置类,将MessageSourceFromDb注册到spring容器

package com.javacode2018.lesson002.test19.demo3;

import org.springframework.context.MessageSource;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

@Configuration

public class MainConfig3 {

@Bean

public MessageSource messageSource(){

return new MessageSourceFromDb();

}

}

上测试用例

@Test

public void test4() throws InterruptedException {

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();

context.register(MainConfig3.class);

context.refresh();

System.out.println(context.getMessage(“desc”, null, Locale.CHINA));

System.out.println(context.getMessage(“desc”, null, Locale.UK));

}

运行输出

我是从db来的信息

MessageSource From Db

bean名称为什么必须是messageSource


上面我容器启动的时候会调用refresh方法,过程如下:

org.springframework.context.support.AbstractApplicationContext#refresh

内部会调用

org.springframework.context.support.AbstractApplicationContext#initMessageSource

这个方法用来初始化MessageSource,方法内部会查找当前容器中是否有messageSource名称的bean,如果有就将其作为处理国际化的对象

如果没有找到,此时会注册一个名称为messageSource的MessageSource

自定义bean中使用国际化


自定义的bean如果想使用国际化,比较简单,只需实现下面这个接口,spring容器会自动调用这个方法,将MessageSource注入,然后我们就可以使用MessageSource获取国际化信息了。

public interface MessageSourceAware extends Aware {

void setMessageSource(MessageSource messageSource);

}

总结

本文介绍了国际化的使用,涉及到了java中的Locale类,这个类用来表示语言国家信息,获取国际化信息的时候需要携带这个参数,spring中通过MessageSource接口来支持国际化的功能,有3个常用的实现类需要了解,StaticMessageSource支持硬编码的方式配置国际化信息。

如果需要spring支撑国际化,需要注册一个bean名称为messageSource的MessageSource,这个一定要注意。

到此,上面面试的3个问题,大家都能轻松应对了。

案例源码


https://gitee.com/javacode2018/spring-series

路人甲java所有案例代码以后都会放到这个上面,大家watch一下,可以持续关注动态。

Spring系列


  1. Spring系列第1篇:为何要学spring?

  2. Spring系列第2篇:控制反转(IoC)与依赖注入(DI)

  3. Spring系列第3篇:Spring容器基本使用及原理

  4. Spring系列第4篇:xml中bean定义详解(-)

  5. Spring系列第5篇:创建bean实例这些方式你们都知道?

  6. Spring系列第6篇:玩转bean scope,避免跳坑里!

  7. Spring系列第7篇:依赖注入之手动注入

  8. Spring系列第8篇:自动注入(autowire)详解,高手在于坚持

  9. Spring系列第9篇:depend-on到底是干什么的?

  10. Spring系列第10篇:primary可以解决什么问题?

  11. Spring系列第11篇:bean中的autowire-candidate又是干什么的?

  12. Spring系列第12篇:lazy-init:bean延迟初始化

  13. Spring系列第13篇:使用继承简化bean配置(abstract & parent)

  14. Spring系列第14篇:lookup-method和replaced-method比较陌生,怎么玩的?

  15. Spring系列第15篇:代理详解(Java动态代理&cglib代理)?

  16. Spring系列第16篇:深入理解java注解及spring对注解的增强(预备知识)

  17. Spring系列第17篇:@Configration和@Bean注解详解(bean批量注册)

  18. Spring系列第18篇:@ComponentScan、@ComponentScans详解(bean批量注册)

  19. Spring系列第18篇:@import详解(bean批量注册)

  20. Spring系列第20篇:@Conditional通过条件来控制bean的注册

  21. Spring系列第21篇:注解实现依赖注入(@Autowired、@Resource、@Primary、@Qulifier)

  22. Spring系列第22篇:@Scope、@DependsOn、@ImportResource、@Lazy 详解

  23. Spring系列第23篇:Bean生命周期详解

  24. Spring系列第24篇:父子容器详解

  25. Spring系列第25篇:@Value【用法、数据来源、动态刷新】

更多好文章


  1. Java高并发系列(共34篇)

  2. MySql高手系列(共27篇)

  3. Maven高手系列(共10篇)

  4. Mybatis系列(共12篇)

  5. 聊聊db和缓存一致性常见的实现方式

总结

至此,文章终于到了尾声。总结一下,我们谈论了简历制作过程中需要注意的以下三个部分,并分别给出了一些建议:

  1. 技术能力:先写岗位所需能力,再写加分能力,不要写无关能力;
  2. 项目经历:只写明星项目,描述遵循 STAR 法则;
  3. 简历印象:简历遵循三大原则:清晰,简短,必要,要有的放矢,不要海投;

以及最后为大家准备的福利时间:简历模板+Java面试题+热门技术系列教程视频

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门,即可获取!
n、@ImportResource、@Lazy 详解]( )

  1. Spring系列第23篇:Bean生命周期详解

  2. Spring系列第24篇:父子容器详解

  3. Spring系列第25篇:@Value【用法、数据来源、动态刷新】

更多好文章


  1. Java高并发系列(共34篇)

  2. MySql高手系列(共27篇)

  3. Maven高手系列(共10篇)

  4. Mybatis系列(共12篇)

  5. 聊聊db和缓存一致性常见的实现方式

总结

至此,文章终于到了尾声。总结一下,我们谈论了简历制作过程中需要注意的以下三个部分,并分别给出了一些建议:

  1. 技术能力:先写岗位所需能力,再写加分能力,不要写无关能力;
  2. 项目经历:只写明星项目,描述遵循 STAR 法则;
  3. 简历印象:简历遵循三大原则:清晰,简短,必要,要有的放矢,不要海投;

以及最后为大家准备的福利时间:简历模板+Java面试题+热门技术系列教程视频

[外链图片转存中…(img-5DOksi2p-1714766572646)]

[外链图片转存中…(img-icI0UPnZ-1714766572647)]

[外链图片转存中…(img-4SoNzf87-1714766572647)]

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门,即可获取!

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值