Springboot 多语
spring多语的使用,需要将名称为messageSource的bean放到ioc容器中,可以使用配置文件或者数据库的方式实现多语
1.基于配置文件的方式
Server层
@Service
public class ServiceTest implements ApplicationContextAware { //用autowired直接从容器中获取也可以
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
public String message() {
//name 是多语的key 第三个参数是获取那个多语文件 如果是null 默认为 zh_CN
//org.springframework.context.support.AbstractMessageSource.getMessageInternal locale = Locale.getDefault(); 默认的返回值 zh_CN
String message = applicationContext.getMessage ("name", null, null);
String messagePersonalIntroduction = applicationContext.getMessage ("personal_introduction", null, null);
//personal_introduction:{0},{1},{0} 第二个参数 对应多语的占位符 第三个参数是获取message_en_GB.properties 配置文件
String messagePersonalIntroductionGb = applicationContext.getMessage ("personal_introduction", new String[]{"test1", "test2"}, new Locale ("en_GB"));
return message + "-----" + messagePersonalIntroduction + "-----" + messagePersonalIntroductionGb ;
}
}
配置层
@Configuration
public class ConfigurationMessageSource {
//将名称为messageSource的bean放到容器中
@Bean
public MessageSource messageSource() {
//基于配置文件的方式,获取多语
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource ();
messageSource.setBasename ("messages");
//多语的编码
messageSource.setDefaultEncoding ("UTF-8");
//每隔多久访问配置文件,当更新配置文件的时候,会动态更新,如果不定义时间,只要更改就会更新多语,影响性能
messageSource.setCacheMillis(1000);
return messageSource;
}
}
配置文件
image.png
message_zh_CN.properties文件,修改配置是会动态更新
name=姓名测试zhCN
personal_introduction=个人介绍:{0},{1},{0}
2.基于数据库的方式
//将名称为messageSource的bean放到容器中
@Component("messageSource")
//类要继承StaticMessageSource ,这个类可以通过编程的方式提供国际化功能
public class MessageSourceFromDb extends StaticMessageSource implements InitializingBean {
@Autowired
private TestMapper testMapper;
@Override
//使用InitializingBean的方式,是因为这个时候数据源已经初始化好了,保证可以从数据库中获取多语信息
public void afterPropertiesSet() throws Exception {
//从数据库中获取信息
List<Test> tests = testMapper.queryAllTests ();
//此处我们在当前bean初始化之后,模拟从db中获取国际化信息,然后调用addMessage来配置国际化信息
this.addMessage("desc", Locale.SIMPLIFIED_CHINESE, "我是从db来的信息");
this.addMessage("desc", Locale.UK, "MessageSource From Db");
}
}
调用和配置文件方式一致
@Service
public class ServiceTest implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
public String message() {
//desc的value是数据库获取的
String desc = applicationContext.getMessage ("desc", null, null);
return desc;
}
如何动态更新message
@Autowired
//从容器中获取MessageSourceFromDb
MessageSourceFromDb messageSource;
@Autowired
private TestMapper testMapper;
public void updateMessage() {
//testMapper.update (); 更新数据库操作 伪代码
//将数据库的同时更新到内存,这样保证了项目重启初始化阶段会从数据库拿到最新的数据放到内存中
messageSource.addMessage ("desc", Locale.SIMPLIFIED_CHINESE, "更新后的数据");
}
基于数据库的方式,在动态更新的时候,内存和数据库同时更新,要考虑数据库更新失败的情况,国际化基本都是后台管理,不存在高并发的情况,可以用锁的方式,保持内存和数据库一致.
3.为什么要把名称为messageSource的bean放到容器中
@Override
public String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale) {
//getMessageSource 是从容器中通过名称过去的,bean的名称就是messageSource
return getMessageSource().getMessage(code, args, defaultMessage, locale);
}
网友评论