• 【SpringMVC】面向全球的用户,我们该怎么办


    前段时间我们跟韩国的客户谈一个项目,自然而然的就遇到了国际化的问题,所以针对国际化的学习,记录一下便于后期使用。

    目的

    假如我有一个网站,默认是中文的,如下图所示:
    中文客户界面
    点击English网站语言切换成英文的,如下所示:
    英文客户界面

    怎么做到的

    细心的网友可能通过上边的图片能发现点细节。就是路径后边带着lang参数。没错我这个示例就是通过这个参数控制的。我们一步步解刨下怎么实现的。
    新建一个简单的web工程,使用springboot初始化功能就行。

    依赖

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-thymeleafartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    自动装配

    package com.example.config;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.LocaleResolver;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
    import org.springframework.web.servlet.i18n.SessionLocaleResolver;
    
    import java.util.Locale;
    
    @Configuration
    public class I18nConfig implements WebMvcConfigurer
    {
        @Bean
        public LocaleResolver localeResolver()
        {
            // 指定Session解析器
            SessionLocaleResolver slr = new SessionLocaleResolver();
            // 默认中文语言
            slr.setDefaultLocale(Locale.SIMPLIFIED_CHINESE);
            return slr;
        }
    
        @Bean
        public LocaleChangeInterceptor localeChangeInterceptor()
        {
            // 拦截请求参数,确定其国际化参数
            LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
            // 参数名,根据lang进行切换国际化解析器
            lci.setParamName("lang");
            return lci;
        }
    
        @Override
        public void addInterceptors(InterceptorRegistry registry)
        {
            registry.addInterceptor(localeChangeInterceptor());
        }
    }
    
    • 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

    18n配置文件

    messages.properties

    #表单
    login.email=email
    login.pwd=password
    login.btn=login
    
    • 1
    • 2
    • 3
    • 4

    messages_us_US.properties

    #表单
    login.email=email
    login.pwd=password
    login.btn=login
    
    • 1
    • 2
    • 3
    • 4

    messages_zh_CN.properties

    #表单
    login.email=邮箱
    login.pwd=密码
    login.btn=登录
    
    • 1
    • 2
    • 3
    • 4

    index.html

    DOCTYPE html>
    <html lang="zh" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>Titletitle>
    head>
    <body>
    <form>
        <a href="./index?lang=zh_CN">中文a>
        <a href="./index?lang=us_US">Englisha>
        <br>
        <br>
        <span th:text="#{login.email}">span>
        <input type="text" name="email">
        <span th:text="#{login.pwd}">span>
        <input type="password" name="pwd">
        <input type="button" th:value="#{login.btn}">
    form>
    body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    控制器接口

    package com.example.web;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.MessageSource;
    import org.springframework.context.i18n.LocaleContextHolder;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    
    import java.util.Locale;
    
    @Controller
    public class IndexController {
    
        @Autowired
        private MessageSource messageSource;
    
        @GetMapping("/index")
        public String index(){
    
            // 演示后台怎么获取
            Locale locale = LocaleContextHolder.getLocale();
            String email = messageSource.getMessage("login.email", null, locale);
            String pwd = messageSource.getMessage("login.pwd", null, locale);
            return "index";
        }
    }
    
    • 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

    application.properties配置

    server.port=8080
    server.servlet.context-path=/i18n
    # 国际化文件名,最后的messages是指的文件名不是目录,否则会报错
    spring.messages.basename=static/i18n/messages
    
    • 1
    • 2
    • 3
    • 4

    启动程序

    package com.example;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class SpringI18nApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(SpringI18nApplication.class, args);
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    启动后,使用浏览器访问就是开头的界面了,做起来很简单。

    为什么

    见其外还得见其内,强大的SpringMVC是怎么做到的呢?
    首先我们在\org\springframework\web\servlet\DispatcherServlet.properties文件中可以看到,默认的国际化配置LocaleResolver为AcceptHeaderLocaleResolver。

    org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
    
    • 1

    LocaleResolve国际化解析器

    LocaleResolver用来确定用户的国际化区域,其具体实现如下:
    在这里插入图片描述

    MessageSource国际化消息源

    除了国际化解析器的以外,国际化还牵扯到一个MessageSource接口,用来装载国际化消息。
    主要配置如下:

    在这里插入图片描述

    主要参数配置

    public class MessageSourceProperties {
    
    	/**
    	 * 国际化文件名称,默认是messages在resources路径下
    	 * 可以配置全路径
    	 */
    	private String basename = "messages";
    
    	/**
    	 * 配置文件的编码格式
    	 */
    	private Charset encoding = StandardCharsets.UTF_8;
    
    	/**
    	 * 消息的缓存时间,默认永久有效
    	 */
    	@DurationUnit(ChronoUnit.SECONDS)
    	private Duration cacheDuration;
    
    	/**
    	 * 查找区域配置文件的选项
    	 * 如果禁用此选项,那么查找不到配置文件只能退到默认的配置文件
    	 */
    	private boolean fallbackToSystemLocale = true;
    
    	/**
    	 * 是否始终应用MessageFormat规则,甚至在没有参数的情况下解析消息
    	 */
    	private boolean alwaysUseMessageFormat = false;
    
    	/**
    	 * 是否采用消息代码替代抛出的NoSuchMessageException异常信息,
    	 * 推荐在开发期间使用
    	 */
    	private boolean useCodeAsDefaultMessage = false;
        ......
    
    }
    
    • 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

    结尾

    以后的国际化项目是不是都可以搞定了<_>。

    源码分享

  • 相关阅读:
    C语言06、指针
    数据结构与算法5-栈
    java计算机毕业设计房产销售平台源代码+程序+lw文档+mysql数据库+远程部署
    Java学习第七周
    软件工程专业如何论文选题?
    前端知识积累
    大数据与AI:解析智慧城市的幕后英雄
    基础篇-SpringBoot HTTP接口实战
    第五篇 《随机点名答题系统》——抽点答题详解(类抽奖系统、在线答题系统、线上答题系统、在线点名系统、线上点名系统、在线考试系统、线上考试系统)
    python爬虫(4)
  • 原文地址:https://blog.csdn.net/lzx5290/article/details/126297891