SpringBoot基础系列手把手实

SpringBoot国际化支持实例开发

国际化的支持,对于app开发的小伙伴来说应该比价常见了;作为java后端的小伙伴,一般来讲接触国际化的机会不太多,毕竟业务开展到海外的企业并没有太多

SpringBoot提供了国际化的支持,网上也有相关的教程,然而实际体验的时候,发现并没有预期的那么顺利;本文将介绍一下SpringBoot如何支持国家化,以及在支持的过程中,一些注意事项

I.项目环境1.项目依赖

本项目借助SpringBoot2.2.1.RELEASE+maven3.5.3+IDEA进行开发

开一个web服务用于测试

dependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-thymeleaf/artifactId/dependency/dependencies2.配置文件

配置文件中,指定国际化的参数,thmeleaf的配置信息

application.yml

spring:messages:basename:i18n/messages/messagesencoding:UTF-8fallbackToSystemLocale:falsethymeleaf:mode:HTMLencoding:UTF-8servlet:content-type:text/htmlcache:false3.国际化信息文件

上面的配置spring.messages.basename指定国际化配置文件的目录与前缀,取值为i18n/messages/messages

所以在资源目录下,新建文件i18n/messages,国际化文件名为messages-xxx.properties,项目结果如

对应的信息如简体中文messages_zh_CN.properties

=成功=內部异常name=用户名pwd=密码

英文messages_en_US.properties

=success=unexpectedexceptionname=usernamepwd=password

繁体messages_zh_TW.properties

=成功=內部異常name=用戶名pwd=密碼

说明

注意spring.messages.basename这个配置的取值为国际化文件的目录+文件名前缀,比如上面若少了最后一层的messages,会提示取不到配置

其次在IDEA中,选中国家化文件之后,点击下方的ResourceBundle,可以进入如上图中更友好的编辑框,支持一次修改多个语言的信息

II.国际化支持

前面是国际化的基本配置,那么如何根据前面配置中的key,获取不同语言的value呢?

1.MessageSource

在SpringBoot中主要借助MessageSource来获取不同语言的value信息

如一个最基本的封装

publicclassMsgUtil{privatestaticMessageSourcemessageSource;publicstaticvoidinti(MessageSourcemessageSource){MsgUtil.messageSource=messageSource;}/***获取单个国际化翻译值*/publicstaticStringget(StringmsgKey){try{returnmessageSource.getMessage(msgKey,null,LocaleContextHolder.getLocale());}catch(Exceptione){returnmsgKey;}}}2.测试demo

接下来写一个基础的测试demo,根据传参来修改LocalContextHolder中的值,从而实现不同语言的切换

Controller

SpringBootApplicationpublicclassApplication{publicApplication(MessageSourcemessageSource){MsgUtil.inti(messageSource);}publicstaticvoidmain(String[]args){SpringApplication.run(Application.class);}

Data

Accessors(chain=true)publicstaticclassRspWrapperT{privateintcode;privateStringmsg;privateTdata;}

GetMapping(path="change")

ResponseBodypublicStringchangeLocal(Stringlanguage){String[]s=language.split("_");LocaleContextHolder.setLocale(newLocale(s[0],s[1]));RspWrapperres=newRspWrapper().setCode().setMsg(MsgUtil.get("")).setData(true);returnJSON.toJSONString(res);}}

演示如下

3.子线程支持

上面虽然可以根据请求参数来切换语言,但是有个问题,如果在子线程中进行国际化支持,则会不生效

GetMapping(path="change2")

ResponseBodypublicStringchangeLocal(Stringlanguage){String[]s=language.split("_");LocaleContextHolder.setLocale(newLocale(s[0],s[1]));RspWrapperres=newRspWrapper().setCode().setMsg(MsgUtil.get("")).setData(true);returnJSON.toJSONString(res);}

如下图,即便修改了language,返回都是默认的中文

针对这种解决办法是在设置Locale时,指定第二个可继承参数为true

GetMapping(path="change3")

ResponseBodypublicStringchangeLocal(Stringlanguage){String[]s=language.split("_");LocaleContextHolder.setLocale(newLocale(s[0],s[1]));RspWrapperres=newRspWrapper().setCode().setMsg(MsgUtil.get("")).setData(true);returnJSON.toJSONString(res);}4.Cookies方式缓存国际化信息

上面虽说支持了根据传参来设置国际化,但是需要每次传参都带上这个参数language=zh_CN,还需要我们自己来解析这个请求参数,我们可以考虑借助拦截器来实现统一的Local设置

这个拦截器可以自己按照上面的方式写,当然更推荐的是直接使用已封装好的

ConfigurationpublicclassAutoConfigimplementsWebMvcConfigurer{/***这个如果不存在,则会抛异常:nestedexceptionisjava.lang.UnsupportedOperationException:CannotchangeHTTPacceptheader-useadifferentlocaleresolutionstrategy**

return*/

BeanpublicLocaleResolverlocaleResolver(){//也可以换成SessionLocalResolver,区别在于国际化的应用范围CookieLocaleResolverlocaleResolver=newCookieLocaleResolver();localeResolver.setDefaultLocale(Locale.SIMPLIFIED_CHINESE);returnlocaleResolver;}/***根据请求参数,来设置本地化**

return*/

BeanpublicLocaleChangeInterceptorlocaleChangeInterceptor(){LocaleChangeInterceptorlocaleChangeInterceptor=newLocaleChangeInterceptor();//Defaultsto"locale"ifnotsetlocaleChangeInterceptor.setParamName("language");returnlocaleChangeInterceptor;}

OverridepublicvoidaddInterceptors(InterceptorRegistryinterceptorRegistry){interceptorRegistry.addInterceptor(localeChangeInterceptor());}}

请注意上面的localResolver,当我们不注册这个bean的时候,运行则会抛出异常nestedexceptionisjava.lang.UnsupportedOperationException:CannotchangeHTTPacceptheader-useadifferentlocaleresolution

上面的实例中,采用的是CookieLocaleResolver,因此会在cookie中缓存语言信息,一次修改,后续都会生效

测试如下

GetMapping(path="say")

ResponseBodypublicStringsay(Stringname){RspWrapperres=newRspWrapper().setCode().setMsg(MsgUtil.get("")).setData(MsgUtil.get("name")+":"+name);returnJSON.toJSONString(res);}

GetMapping(path="say2")

ResponseBodypublicStringsay2(Stringname){RspWrapperres=newRspWrapper().setCode().setMsg(MsgUtil.get("")).setData(MsgUtil.get("name")+":"+name);returnJSON.toJSONString(res);}

主要一个地方设置了语言,后续的访问不带语言参数时,都会复用之前设置的语言,这样使用来说就更简洁了

5.页面元素国际化

上面介绍的是返回的json串支持国际化,另外一个场景就是我们返回的页面,希望渲染的数据也可以实现国际化支持

在上文的基础上实现这个也没什么难度了

在资源目录下,新建目录templates,新建模板文件index.html

!DOCTYPEhtmlhtmlxmlns:th="



转载请注明地址:http://www.sanbaicaoasb.com/scls/8428.html
  • 上一篇文章:
  • 下一篇文章:
  • 热点文章

    • 没有热点文章

    推荐文章

    • 没有推荐文章