Spring MVC国际化三种方案

  对开发者来说是国际化,对使用者来说是本地化。
  SpringMVC 的国际化是建立在Java国际化的基础之上,也是通过提供不同国家/语言环境的消息资源,然后通过ResourceBundle加载指定Local对应的资源文件,再取得该资源文件中指定key对应的消息。

国际化相关知识

Spring MVC 国际化步骤:

  1. 给系统加载国际化资源文件。
  2. 输出国际化。

Spring MVC 国际化消息有两种方式:

  1. 视图页面上输出国际化信息,需要使用SpringMVC的标签库。
  2. Controller 的处理方法中输出国际化信息,需要使用org.springframework.web.servlet.support.RequestContextgetMessage()方法来完成。

国际化的通用做法是通过读取用户浏览器请求头中Accept-Language属性值,该属性提供了关于用户浏览器的信息,根据该信息为用户选择语言区域;还可以根据HttpSession或者Cookie为用户选择语言区域。

Spring MVC 提供了一个语言区域解析接口LocalResolver,该接口的常用实现类都在org.springframework.web.servlet.i18n包下面,包括:

  1. AcceptHeaderLocaleResolver
  2. SessionLocaleResolver
  3. CookieLocaleResolver

基于浏览器请求的国际化实现

  基于浏览器请求的国际化即根据浏览器请求的消息头中的Accept-Language属性来选择区域性语言,默认装配 AcceptHeaderLocaleResolver来处理来解析语言区区域。
  AcceptHeaderLocaleResolver是默认的,是最容易使用的语言解析器,会读取浏览器的Accept-Language属性来确定使用哪个区域语言。该解析器不用显式配置。而sessioncookie需要手动显示配置。

示例代码

通过一个登录页面来演示Spring MVC 的国际化。

  1. 构建前端登录页面loginForm.jsp,引入spring标签库。
    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
    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
    <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>基于浏览器的国际化</title>
    </head>
    <body>
    <h3><spring:message code = "title" /></h3>
    <form:form action="/springmvc_01_2/user/login" method="post" modelAttribute="user">
    <table>
    <tr>
    <td><spring:message code="loginname" /></td>
    <td><form:input path="loginname" /></td>
    </tr>
    <tr>
    <td><spring:message code="password" /></td>
    <td><form:input path="password" /></td>
    </tr>
    <tr>
    <td><input type="submit" value="<spring:message code="submit" />" /></td>
    </tr>
    </table>
    </form:form>
    </body>
    </html>
  2. 构建登录成功后的返回页面success.jsp
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
    <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>登录成功</title>
    </head>
    <body>
    <spring:message code="welcome" arguments="${requestScope.user.username}" />
    </body>
    </html>
  3. 创建两个语言资源文件,properties 文件,UTF-8编码; 此两个文件放到项目资源目录(config)里。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    //文件名:message_en_US.properties
    loginname = Login name:
    password = Password:
    submit = Submit
    welcome = Welcome {0} access this website
    title = Login Page
    username = admin

    //文件名:message_zh_CN.properties
    loginname = 登录名:
    password = 密码:
    submit = 提交
    welcome = 欢迎 {0} 访问本站
    title = 登录页面
    username = 管理员
  4. springmvc.xml配置文件添加bean,告诉那些是语言资源文件。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    <!-- 国际化 : 
    根据value查找以该值开头的.properties资源文件
    资源文件名构造:value值_请求语言.properties
    -->
    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
    <!-- 国际化资源文件名, 要以配置多个值 -->
    <property name="basenames">
    <list>
    <value>message</value>
    <!-- <value>language</value> -->
    </list>
    </property>
    <!-- 支持UTF-8的中文 -->
    <property name="cacheSeconds" value="0"/>
    <property name="defaultEncoding" value="UTF-8"/>
    </bean>

    <!-- 拦截器配置 -->
    <mvc:interceptors>
    <!-- 国际化操作拦截器 -->
    <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"></bean>
    </mvc:interceptors>
  5. 后端添加User实体类。
    1
    2
    3
    4
    5
    6
    7
    8
    public class User {

    private String username;
    private String loginname;
    private String password;

    --- set/get方法---
    }
  6. 后端Controller层添加处理方法。
    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
    @Controller
    @RequestMapping("/user")
    public class LoginController {

    @RequestMapping("/loginV")
    public String loginView(Model model) {
    User user = new User();
    model.addAttribute("user", user);
    return "loginForm";
    }

    @RequestMapping(value = "/login", method = { RequestMethod.POST })
    public String login(@ModelAttribute @Validated User user, HttpServletRequest request, Model model) {

    String loginName = user.getLoginname();
    String password = user.getPassword();

    if (loginName != null && loginName.equals("root")
    && password != null && password.equals("root123")) {
    RequestContext requestContext = new RequestContext(request);
    String username = requestContext.getMessage("username");
    user.setUsername(username);
    model.addAttribute("user", user);
    return "success";
    }else {
    return "error";
    }
    }
    }
  7. 验证国际化结果。
    切换浏览器的语言顺序,发送请求。

基于Session的国际化实现

显式配置SessionLocaleResolver语言解析器,会替换掉默认的AcceptHeaderLocaleResolver解析器。SpringMVC会从HttpSession域中获取用户所设置的语言来确定使用那个语言区域。

示例代码

  1. 前端添加用户可选择语言。
    两个超级链接,分别用于切换中文和英文语言环境,超级连接带参数request_local,传递语言类型。

    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
    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
    <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>基于浏览器的国际化</title>
    </head>
    <body>
    <a href="${pageContext.request.contextPath}/user/loginV?request_local=zh_CN">中文</a> | <a href="${pageContext.request.contextPath}/user/loginV?request_local=en_US">English</a>
    <h3><spring:message code = "title" /></h3>
    <form:form action="/springmvc_01_2/user/login" method="post" modelAttribute="user">
    <table>
    <tr>
    <td><spring:message code="loginname" /></td>
    <td><form:input path="loginname" /></td>
    </tr>
    <tr>
    <td><spring:message code="password" /></td>
    <td><form:input path="password" /></td>
    </tr>
    <tr>
    <td><input type="submit" value="<spring:message code="submit" />" /></td>
    </tr>
    </table>
    </form:form>
    </body>
    </html>
  2. 构建登录成功后的返回页面success.jsp
    同上:示例代码-2

  3. 添加区域语言资源文件
    同上: 示例代码-3

  4. 在文件springmvc.xml里显式配置SessionLocaleResolver

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    <!-- 显式配置SessionLocaleResolver语言解析器, 替换掉默认的localResolver -->
    <bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver"></bean>

    <!-- 国际化 :
    根据value查找以该值开头的.properties资源文件
    资源文件名构造:value值_请求语言.properties
    -->
    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
    <!-- 国际化资源文件名, 要以配置多个值 -->
    <property name="basenames">
    <list>
    <value>message</value>
    <!-- <value>language</value> -->
    </list>
    </property>
    <!-- 支持UTF-8的中文 -->
    <property name="cacheSeconds" value="0"/>
    <property name="defaultEncoding" value="UTF-8"/>
    </bean>

    <mvc:interceptors>
    <!-- 国际化操作拦截器 -->
    <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"></bean>
    </mvc:interceptors>
  5. 添加实体类
    同上:示例代码-5

  6. 后端代码识别用户选择的语言

    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
    @Controller
    @RequestMapping("/user")
    public class LoginController {

    @RequestMapping("/loginV")
    public String loginView(Model model, String request_local, HttpServletRequest request) {

    if (request_local != null) {
    if (request_local.equals("zh_CN")) {
    //中文环境
    Locale locale = new Locale("zh", "CN");
    request.getSession().setAttribute(SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME, locale);
    } else if (request_local.equals("en_US")) {
    //英文环境
    Locale locale = new Locale("en", "US");
    request.getSession().setAttribute(SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME, locale);
    } else {
    //默认环境
    request.getSession().setAttribute(SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME,
    LocaleContextHolder.getLocale());
    }
    }

    User user = new User();
    model.addAttribute("user", user);
    return "loginForm";
    }

    @RequestMapping(value = "/login", method = { RequestMethod.POST })
    public String login(@ModelAttribute @Validated User user, HttpServletRequest request, Model model) {

    String loginName = user.getLoginname();
    String password = user.getPassword();

    if (loginName != null && loginName.equals("admin") && password != null && password.equals("123")) {
    RequestContext requestContext = new RequestContext(request);
    String username = requestContext.getMessage("username");
    user.setUsername(username);
    model.addAttribute("user", user);
    return "success";
    } else {
    return "error";
    }
    }
    }
  7. 验证
    单击超级链接,传递request_locale参数,后台根据该参数进行语言环境切换。

基于Cookie的国际化实现

显式配置CookieLocaleResolver语言区域解析器,后台根据所选择的语言参数响应对应的语言环境。

示例代码

  1. 前端登录页面、成功页面、区域语言资源文件、实体类java文件同上。
  2. 在文件springmvc.xml里显式配置CookieLocaleResolver
    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
    <!-- 显式配置SessionLocaleResolver语言解析器, 替换掉默认的localResolver -->
    <!-- <bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver"></bean> -->

    <!-- 显式配置CookieLocaleResolver语言解析器, 替换掉默认的localResolver -->
    <bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver"></bean>

    <!-- 国际化 :
    根据value查找以该值开头的.properties资源文件
    资源文件名构造:value值_请求语言.properties
    -->
    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
    <!-- 国际化资源文件名, 要以配置多个值 -->
    <property name="basenames">
    <list>
    <value>message</value>
    <!-- <value>language</value> -->
    </list>
    </property>
    <!-- 支持UTF-8的中文 -->
    <property name="cacheSeconds" value="0"/>
    <property name="defaultEncoding" value="UTF-8"/>
    </bean>

    <mvc:interceptors>
    <!-- 国际化操作拦截器 -->
    <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"></bean>
    </mvc:interceptors>
  3. 后端代码识别用户选择的语言
    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
    @Controller
    @RequestMapping("/user")
    public class LoginController {

    @RequestMapping("/loginV")
    public String loginView(Model model, String request_local,
    HttpServletRequest request,
    HttpServletResponse response) {

    if (request_local != null) {
    if (request_local.equals("zh_CN")) {
    //中文环境
    Locale locale = new Locale("zh", "CN");
    (new CookieLocaleResolver()).setLocale(request, response, locale);
    } else if (request_local.equals("en_US")) {
    //英文环境
    Locale locale = new Locale("en", "US");
    (new CookieLocaleResolver()).setLocale(request, response, locale);
    } else {
    //默认环境
    (new CookieLocaleResolver()).setLocale(request, response, LocaleContextHolder.getLocale());
    }
    }

    User user = new User();
    model.addAttribute("user", user);
    return "loginForm";
    }

    @RequestMapping(value = "/login", method = { RequestMethod.POST })
    public String login(@ModelAttribute @Validated User user, HttpServletRequest request, Model model) {

    String loginName = user.getLoginname();
    String password = user.getPassword();

    if (loginName != null && loginName.equals("admin") && password != null && password.equals("123")) {
    RequestContext requestContext = new RequestContext(request);
    String username = requestContext.getMessage("username");
    user.setUsername(username);
    model.addAttribute("user", user);
    return "success";
    } else {
    return "error";
    }
    }
    }

  4. 验证语言切换
    点击超级链接切换语言环境,查看请求头和响应头中的Language参数值。
作者

光星

发布于

2018-02-10

更新于

2022-06-17

许可协议

评论