• (十七)admin-boot项目之国际化支持


    (十七)国际化支持

    项目地址:https://gitee.com/springzb/admin-boot
    如果觉得不错,给个 star

    简介:
    这是一个基础的企业级基础后端脚手架项目,主要由springboot为基础搭建,后期整合一些基础插件例如:redis、xxl-job、flowable、minioio、easyexcel、skyWalking、rabbitmq

    国际化支持原理

    WebMvcAutoConfiguration 类中

    1、WebMvcAutoConfiguration 是SpringBoot中的 Web方面的自动配置类。
    2、当用户没有创建自己的 localeResolver 时,这个配置方法就会生效,从而产生一个localeResolver。(配置自己的localeResolver时,Bean名必须为localeResolver)。
    3、spring.web.locale-resolver、spring.mvc.locale-resolver 的配置属性都有两个值可供选择。(fixed、accept_header)。
    4、选择属性值 fixed,表示 Locale 区域对象是 固定的。
    5、当属性值为fixed,应该搭配spring.web.locale、spring.mvc.locale 这两个配置属性一起使用,给出固定的Locale 区域对象。
    6、假如属性值为fixed,又没有搭配上面两个属性之一,则因为上面两个属性没有默认值,则Locale 区域对象将会使用运行主机的默认语言环境生成一个Locale 区域对象。
    6、从以下的方法的执行流程可以看出,spring.web.locale-resolver 优先级比 spring.mvc.locale-resolver 高一些。
    7、因为spring.web.locale-resolver、spring.mvc.locale-resolver 它们的 默认值 都为 accept_header,所以,只要不更改配置,默认就不是固定的Locale 区域对象。就会继续执行最下面的部分。

    8、此时spring.web.locale、spring.mvc.locale 这两个配置属性,假如存在,就会成为AcceptHeaderLocaleResolver 的默认的Locale 区域对象。 并在请求响应的请求头中没有Accept-Language这个属性时,成为AcceptHeaderLocaleResolver返回的Locale 区域对象。

    9、AcceptHeaderLocaleResolver 会根据请求响应的请求头中的Accept-Language属性,来返回特定的Locale 区域对象。

    一、代码实现

    MyLocaleResolver自定义解析器

    package cn.mesmile.admin.common.i18n;
    
    import cn.hutool.core.util.StrUtil;
    import cn.mesmile.admin.common.constant.AdminConstant;
    import org.springframework.web.servlet.LocaleResolver;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.util.Locale;
    
    /**
     *
     * @author zb
     * @description 自定义 语言解析器
     */
    public class MyLocaleResolver implements LocaleResolver {
    
        /**
         * 自定义国际化解析,优先以 链接参数为准
         * 然后 Accept-Language 请求头为二级优先
         */
        @Override
        public Locale resolveLocale(HttpServletRequest request) {
            int languageArraySize = 2;
            // 从请求头上获取  Accept-Language 上获取
            Locale locale = request.getLocale();
            //获取请求参数中的语言参数  admin_language    zh-CN   en-US
            String language = request.getParameter(AdminConstant.ADMIN_LANGUAGE);
            //如果请求的链接中携带了 国际化的参数
            if (StrUtil.isNotEmpty(language)){
                // zh-CN   en-US
                String[] languageArray = language.split("-");
                if (languageArray.length == languageArraySize){
                    // 国家 地区
                    return new Locale(languageArray[0], languageArray[1]);
                }
            }
            return locale == null ? Locale.getDefault() : locale;
        }
    
        @Override
        public void setLocale(HttpServletRequest request, HttpServletResponse httpServletResponse, Locale locale) {
            
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    I18nConfig 配置解析器

    package cn.mesmile.admin.common.i18n;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.LocaleResolver;
    
    /**
     * @author zb
     * @Description
     */
    @Configuration
    public class I18nConfig {
    
        @Bean
        public LocaleResolver localeResolver(){
            return new MyLocaleResolver();
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    ResourceI18nUtil工具类

    package cn.mesmile.admin.common.utils;
    
    import cn.hutool.extra.spring.SpringUtil;
    import org.springframework.context.MessageSource;
    import org.springframework.context.MessageSourceResolvable;
    import org.springframework.context.i18n.LocaleContextHolder;
    
    /**
     * @author zb
     * @Description
     */
    public class ResourceI18nUtil {
    
        public static MessageSource getMessageSource() {
            return SpringUtil.getBean(MessageSource.class);
        }
    
        /**
         * 通过定义key 获取value
         * @param key key
         * @return value
         */
        public static String getValueByKey(String key){
            return getMessageSource().getMessage(key, null, LocaleContextHolder.getLocale());
        }
    
        /**
         * 通过定义key 获取value
         * @param key key
         * @param args 填补参数
         * @return value
         */
        public static String getValueByKey(String key, Object... args){
            return getMessageSource().getMessage(key, args, LocaleContextHolder.getLocale());
        }
    
        /**
         * 通过定义key 获取value
         * @param key key
         * @param defaultMessage 默认消息
         * @param args 填补参数
         * @return value
         */
        public static String getValueDefaultByKey(String key,String defaultMessage,Object... args){
            return getMessageSource().getMessage(key, args, defaultMessage, LocaleContextHolder.getLocale());
        }
    
        /**
         * 通过定义key 获取value
         * @param key key
         * @param defaultMessage 默认消息
         * @return value
         */
        public static String getValueDefaultByKey(String key,String defaultMessage){
            return getMessageSource().getMessage(key, null, defaultMessage,LocaleContextHolder.getLocale());
        }
    
        /**
         * 通过定义key 获取value
         * @param resolvable resolvable
         * @return value
         */
        public static String getValueByResolvable(MessageSourceResolvable resolvable){
            return getMessageSource().getMessage(resolvable, LocaleContextHolder.getLocale());
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68

    编写对应配置文件

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0oTySeYQ-1660448006374)(image/image_q_og0mgr0w.png)]

    修改application.yml配置文件

      # 资源信息
    spring:
      messages:
        # 国际化资源文件路径
        basename: i18n.messages
        encoding: UTF-8
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    二、测试

    package cn.mesmile.admin.modules.system.controller;
    
    import cn.mesmile.admin.common.result.R;
    import cn.mesmile.admin.common.utils.ResourceI18nUtil;
    import io.swagger.annotations.Api;
    import io.swagger.annotations.ApiImplicitParam;
    import io.swagger.annotations.ApiImplicitParams;
    import io.swagger.annotations.ApiOperation;
    import lombok.extern.slf4j.Slf4j;
    import org.checkerframework.checker.i18nformatter.I18nFormatUtil;
    import org.springframework.context.i18n.LocaleContextHolder;
    import org.springframework.web.bind.annotation.*;
    
    import javax.servlet.http.HttpServletRequest;
    import java.util.Locale;
    
    /**
     * @author zb
     * @Description
     */
    @Api(tags = "用户登录测试接口")
    @Slf4j
    @RequestMapping("/api/v1/hello")
    @RestController
    public class HelloController {
    
        @GetMapping("/i18")
        public R get(){
            // 参数优先 admin_language   默认根据请求头判断 Accept-Language
            String username = ResourceI18nUtil.getValueByKey("user.login.username");
            return R.data(username);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-31msP6Np-1660448006375)(image/image_pSneRArh7z.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QdFAqiLL-1660448006375)(image/image_3OjJeeudW2.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0UBFWn1N-1660448006376)(image/image_uYgvM8b7wl.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xbCtP9ou-1660448006376)(image/image_qfPGripmhy.png)]

  • 相关阅读:
    Java学习禁忌
    MySQL进阶篇4——锁+InnoDB引擎+MySQL管理
    81. 搜索旋转排序数组 II
    JAVA设计模式之桥接模式
    不是计算机专业自学 “ 软件测试 ” 好找工作吗?
    如何靠写代码赚钱?
    微服务 Spring Cloud 5,一图说透Spring Cloud微服务架构
    Google Earth Engine(GEE)——ui.util.debounce的使用
    第六课 ceph基础学习-Ceph的管理监控和故障排查
    聊聊预训练模型的微调
  • 原文地址:https://blog.csdn.net/suprezheng/article/details/126329869