Spring Boot Web开发之国际化配置的几个坑

    xiaoxiao2022-07-07  217

    使用工具IDEA 今天学习到使用spring Boot 进行自动国际化配置。 使用的Spring Boot版本是2.0.9.RELEASE

    按照视频教程进行各项配置跟源码解析。了解了国际化运作的基本原理。

    我们没有Spring Boot进行自动配置的时候要做的事情有3步

    1:编写国际化配置文件。 2:使用ResourceBundleMessageSource管理国际化资源文件 3:在页面使用fmt:message取出国际化内容。 但是用了spring Boot 之后他帮我们默认做好配置,我们就只用进行配置文件的撰写还有国际化信息解析器的开发就行了。 第一步,编写资源配置文件

    password=密码~ username=用户名~

    第二步 我们来看看spring Boot是怎么管理国际化资源文件的。

    @Bean public MessageSource messageSource() { MessageSourceProperties properties = this.messageSourceProperties(); ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); if (StringUtils.hasText(properties.getBasename())) { messageSource.setBasenames(StringUtils.commaDelimitedListToStringArray(StringUtils.trimAllWhitespace(properties.getBasename()))); } if (properties.getEncoding() != null) { messageSource.setDefaultEncoding(properties.getEncoding().name()); } messageSource.setFallbackToSystemLocale(properties.isFallbackToSystemLocale()); Duration cacheDuration = properties.getCacheDuration(); if (cacheDuration != null) { messageSource.setCacheMillis(cacheDuration.toMillis()); } messageSource.setAlwaysUseMessageFormat(properties.isAlwaysUseMessageFormat()); messageSource.setUseCodeAsDefaultMessage(properties.isUseCodeAsDefaultMessage()); return messageSource; }

    从配置文件中不难看出,它从properties,配置类中取出 Basename,这个basename 就是用来存放国际化信息资源文件的位置的。让我们来进去看看它的默认配置跟它所绑定的前缀;

    MessageSourceProperties properties = this.messageSourceProperties();这行代码调用下述方法返回属性配置类,并绑定配置文件前缀。

    @Bean @ConfigurationProperties( prefix = "spring.messages" ) public MessageSourceProperties messageSourceProperties() { return new MessageSourceProperties(); }

    在MessageSourceProperties 这个类中

    public class MessageSourceProperties { private String basename = "messages"; private Charset encoding; @DurationUnit(ChronoUnit.SECONDS) private Duration cacheDuration; private boolean fallbackToSystemLocale; private boolean alwaysUseMessageFormat; private boolean useCodeAsDefaultMessage; public MessageSourceProperties() { this.encoding = StandardCharsets.UTF_8; this.fallbackToSystemLocale = true; this.alwaysUseMessageFormat = false; this.useCodeAsDefaultMessage = false; }

    不难发现basename的默认配置就是message 这意味着,只要在classpath下,用message的基础名就可以无需任何配置完成国际化。 但是我配好这些之后,发现在页面端无法获取国际化资源文件。在页面端一直显示??login.username_zh_CN??

    我在网上一顿百度一顿Google,debug调试,并没有发现什么问题。最后发现,SpringBoot 2大版本跟1点几版本有个区别, 不再是之前版本的基础名+配置文件中的key值了。我之前写的是#{login.username},导致一直获取不到值。

    <div > <span>[[#{username}]]</span> <input type="text" name="username" value="haha"> </div>

    spring Boot默认配置的国际化信息解析器,是根据你的请求头中的 Accept-Language: zh-CN,zh;q=0.9 来确定你的语言的。 如果想要通过请求中携带参数的形式来进行解析的话,我们可以自己配置一个国际化解析器。并加入到组件中。 spring boot进行配置的时候,检测到用户自己已经配置了一个解析器,他就不会再进行默认配置了。 我们自己的国际化解析器必须实现LocaleResolver 接口。 国际化解析器的实现是依靠了Locale对象,这个对象有个2个参数的构造方法,一个是语言,一个是地区。 返回这个对象,spring mvc就可以根据这个对象进行读取相应的资源文件。

    public class MyLocaleResolver implements LocaleResolver { @Override public Locale resolveLocale(HttpServletRequest request) { String i18n_language = request.getParameter("l"); //获得请求头携带的参数,l是参数名 Locale locale = new Locale("zh","CN" ); //new一个默认的Locale对象,我默认了中国 if(!StringUtils.isEmpty(i18n_language)) { //判断请求是否携带了这个参数,有的话就根据参数进行解析 String[] language = i18n_language.split("_"); locale = new Locale(language[0], language[1]); } return locale; } @Override public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) { }

    然后就是将他加入到spring容器中了。随便写一个类加上@Configuration 注解,在其中写一个方法返回我们的国际化解析器就行了。

    @Bean public LocaleResolver localeResolver(){ return new MyLocaleResolver(); }

    不过这里也有一个坑比较隐蔽。 我们的Spring Boot 对组件中有无用户自己配置的组件进行判断的时候,其实就判断了组件的id,所以我们的方法名必须得跟spring boot 默认配置文件中的一致,否则它就认为我们没有进行配置,任然将默认配置的拿过来用。 其实这也可以理解,因为名字换了,spring mvc就找不到该对象了,这个国际化解析器,以前是要注入视图解析器解析器中的,注入的方式只能通过id,所以id肯定不能变。 这是springBoot的默认配置

    @Bean @ConditionalOnMissingBean @ConditionalOnProperty( prefix = "spring.mvc", name = {"locale"} ) public LocaleResolver localeResolver() { if (this.mvcProperties.getLocaleResolver() == org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties.LocaleResolver.FIXED) { return new FixedLocaleResolver(this.mvcProperties.getLocale()); } else { AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver(); localeResolver.setDefaultLocale(this.mvcProperties.getLocale()); return localeResolver; } }

    到这里终于算是把springBoot的国际化配置都走了一遍了。

    最后愿所有自学者都能学有所成。

    最新回复(0)