Spring 框架入门教程
1. 1. Spring 框架 2. 2. Spring 5 3. 3. Spring WebFlux 4. 4. 先介绍一下 Spring 5. 5. 什么是 Spring 依赖注入 6. 6. 什么是 Spring IoC 容器 和 Bean 7. 7. Spring Bean 的生命周期 8. 8. Spring REST 开发 9. 9. Spring REST XML 10. 10. Spring RestTemplate 开发 11. 11. Spring AOP 切面编程 12. 12. Spring AOP 方法调优 13. 13. Spring 注解详解 14. 14. Spring 核心注解之 @Autowired 15. 15. Spring 核心注解之 @RequestMapping 16. 16. Spring MVC 开发样例 17. 17. Spring MVC 开发指南 18. 18. Spring MVC 异常处理机制 19. 19. Spring MVC Validator 20. 20. Spring MVC 拦截器 21. 21. Spring MVC 文件上传 22. 22. Spring MVC 国际化(i18n) 23. 23. Spring MVC Hibernate MqSQL 24. 24. Spring ORM 25. 25. Spring ORM JPA 26. 26. Spring Data JPA 27. 27. Spring 事务管理 28. 28. 常用的 Spring JdbcTemplate 29. 29. Spring Security 简介 30. 30. Spring Security 教程 31. 31. Spring Security UserDetailsService 32. 32. Spring MVC 登录注销简单案例 33. 33. Spring Security Roles 34. 34. Spring Boot Tutorial 35. 35. Spring Boot Components 36. 36. Spring Boot CLI Hello World 37. 37. Spring Boot Initilizr Web 38. 38. Spring Boot Initilizr IDE 39. 39. Spring Boot Initilizr CLI 40. 40. Spring Boot Initilizr Tools 41. 41. Spring Boot MongoDB 42. 42. Spring Boot Redis Cache 43. 43. Spring Boot 常见面试问题 44. 44. Spring Batch 45. 45. Spring Batch 批处理示例 46. 46. Spring AMQP 47. 47. Spring RabbitMQ 48. 48. Spring AMQP RabbitMQ 49. 49. Apache ActiveMQ 安装与启动 50. 50. Spring ActiveMQ 教程 51. 51. Spring ActiveMQ 示例 52. 52. Spring JDBC 53. 53. Spring DataSource JNDI 54. 54. Spring Hibernate 55. 55. Spring Primefaces JPA 56. 56. Spring Primefaces MongoDB 57. 57. Spring Primefaces Hibernate 58. 58. SpringRoo Primefaces Hibernate 59. 59. Spring JSF 60. 60. Spring JDF Hibernate 61. 61. Spring Data MongoDB 62. 62. Spring 常见面试问题

22. Spring MVC 国际化(i18n)

欢迎使用springinternationalization(i18n)教程。任何用户遍布全球的网络应用程序,国际化(i18n)或本地化(L10n)对于更好的用户交互非常重要。

大多数web应用程序框架都提供了基于用户区域设置来本地化应用程序的简单方法。Spring也遵循这种模式,通过使用Spring拦截器、区域解析程序和针对不同地区的资源包,为国际化(i18n)提供了广泛的支持。

关于java中i18n的一些早期文章。

  • Java国际化示例
  • Struts2国际化示例

Spring国际化i18n

让我们创建一个简单的Spring Mvc项目,在这个项目中,我们将使用request参数获取用户区域设置,并在此基础上设置来自特定于语言环境的资源包的响应页面标签值。

在Spring工具套件中创建一个Spring Mvc项目,以获得应用程序的基本代码。如果您不熟悉Spring工具套件或Spring Mvc项目,请阅读Spring MVC示例.

我们的最终项目本地化变化如下图。我们将逐一研究应用程序的所有部分。

springi18n Maven配置

我们的SpringMVCpom.xml文件如下所示。


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.journaldev</groupId>
	<artifactId>spring</artifactId>
	<name>Springi18nExample</name>
	<packaging>war</packaging>
	<version>1.0.0-BUILD-SNAPSHOT</version>
	<properties>
		<java-version>1.6</java-version>
		<org.springframework-version>4.0.2.RELEASE</org.springframework-version>
		<org.aspectj-version>1.7.4</org.aspectj-version>
		<org.slf4j-version>1.7.5</org.slf4j-version>
	</properties>
	<dependencies>
		<!-- Spring -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${org.springframework-version}</version>
			<exclusions>
				<!-- Exclude Commons Logging in favor of SLF4j -->
				<exclusion>
					<groupId>commons-logging</groupId>
					<artifactId>commons-logging</artifactId>
				 </exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
				
		<!-- AspectJ -->
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjrt</artifactId>
			<version>${org.aspectj-version}</version>
		</dependency>	
		
		<!-- Logging -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>${org.slf4j-version}</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>jcl-over-slf4j</artifactId>
			<version>${org.slf4j-version}</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>${org.slf4j-version}</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.15</version>
			<exclusions>
				<exclusion>
					<groupId>javax.mail</groupId>
					<artifactId>mail</artifactId>
				</exclusion>
				<exclusion>
					<groupId>javax.jms</groupId>
					<artifactId>jms</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.jdmk</groupId>
					<artifactId>jmxtools</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.jmx</groupId>
					<artifactId>jmxri</artifactId>
				</exclusion>
			</exclusions>
			<scope>runtime</scope>
		</dependency>

		<!-- @Inject -->
		<dependency>
			<groupId>javax.inject</groupId>
			<artifactId>javax.inject</artifactId>
			<version>1</version>
		</dependency>
				
		<!-- Servlet -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.5</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>jsp-api</artifactId>
			<version>2.1</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>
	
		<!-- Test -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.7</version>
			<scope>test</scope>
		</dependency>        
	</dependencies>
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-eclipse-plugin</artifactId>
                <version>2.9</version>
                <configuration>
                    <additionalProjectnatures>
                        <projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
                    </additionalProjectnatures>
                    <additionalBuildcommands>
                        <buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
                    </additionalBuildcommands>
                    <downloadSources>true</downloadSources>
                    <downloadJavadocs>true</downloadJavadocs>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.5.1</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                    <compilerArgument>-Xlint:all</compilerArgument>
                    <showWarnings>true</showWarnings>
                    <showDeprecation>true</showDeprecation>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.2.1</version>
                <configuration>
                    <mainClass>org.test.int1.Main</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

大部分代码都是由STS自动生成的,除了我已经更新了Spring版本以使用最新的版本作为4.0.2.RELEASE。我们可以删除依赖项或更新其他依赖项的版本,但为了简单起见,我保留了它们。

Spring资源包

为了简单起见,假设我们的应用程序只支持两个语言环境’;英语法国. 如果没有指定用户区域设置,我们将使用英语作为默认区域设置。让我们为这两个将在JSP页面中使用的语言环境创建spring资源包。

消息_英语属性代码:


label.title=Login Page
label.firstName=First Name
label.lastName=Last Name
label.submit=Login

消息_fr.属性代码:


label.title=Connectez-vous page
label.firstName=Pru00E9nom
label.lastName=Nom
label.submit=Connexion

注意,我在法语语言环境资源包中对特殊字符使用unicode,以便在发送到客户机请求的HTML响应中正确地解释它。

另一个需要注意的重要点是,这两个资源包都位于应用程序的类路径中,它们的名称的模式为“;messages{locale}.properties”;。稍后我们将了解为什么这些很重要。

SpringI18N控制器类

我们的控制器类非常简单,它只记录用户区域设置并返回主页.jsp页面作为响应。


package com.journaldev.spring;

import java.util.Locale;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * Handles requests for the application home page.
 */
@Controller
public class HomeController {
	
	private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
	
	/**
	 * Simply selects the home view to render by returning its name.
	 */
	@RequestMapping(value = "/", method = RequestMethod.GET)
	public String home(Locale locale, Model model) {
		logger.info("Welcome home! The client locale is {}.", locale);
	
		return "home";
	}
	
}

JSP i18n第18页

我们的主页.jsp页面代码如下所示。


<%@taglib uri="https://www.springframework.org/tags" prefix="spring"%>
<%@ page session="false"%>
<html>
<head>
<title><spring:message code="label.title" /></title>
</head>
<body>
	<form method="post" action="login">
		<table>
			<tr>
				<td><label> <strong><spring:message
								code="label.firstName" /></strong>
				</label></td>
				<td><input name="firstName" /></td>
			</tr>
			<tr>
				<td><label> <strong><spring:message
								code="label.lastName" /></strong>
				</label></td>
				<td><input name="lastName" /></td>
			</tr>
			<tr>
				<spring:message code="label.submit" var="labelSubmit"></spring:message>
				<td colspan="2"><input type="submit" value="${labelSubmit}" /></td>
			</tr>
		</table>
	</form>
</body>
</html>

唯一值得一提的是Spring:消息使用给定代码检索消息。确保Spring标记库是使用taglib jsp指令.Spring负责加载适当的资源包消息,并使其可供JSP页面使用。

springinternationalization i18n–;Bean配置文件

Spring Bean配置文件是所有神奇发生的地方。这就是Spring框架的优点,因为它帮助我们更加关注业务逻辑,而不是为琐碎的任务编写代码。让我们看看我们的Spring Bean配置文件是什么样子的,我们将看一下每一个bean。

servlet-上下文.xml代码:


<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="https://www.springframework.org/schema/mvc"
	xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:beans="https://www.springframework.org/schema/beans"
	xmlns:context="https://www.springframework.org/schema/context"
	xsi:schemaLocation="https://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
		https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
		https://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

	<!-- DispatcherServlet Context: defines this servlet"s request-processing 
		infrastructure -->

	<!-- Enables the Spring MVC @Controller programming model -->
	<annotation-driven />

	<!-- Handles HTTP GET requests for /resources/** by efficiently serving 
		up static resources in the ${webappRoot}/resources directory -->
	<resources mapping="/resources/**" location="/resources/" />

	<!-- Resolves views selected for rendering by @Controllers to .jsp resources 
		in the /WEB-INF/views directory -->
	<beans:bean
	>
		<beans:property name="prefix" value="/WEB-INF/views/" />
		<beans:property name="suffix" value=".jsp" />
	</beans:bean>

	<beans:bean id="messageSource"
	>
		<beans:property name="basename" value="classpath:messages" />
		<beans:property name="defaultEncoding" value="UTF-8" />
	</beans:bean>

	<beans:bean id="localeResolver"
	>
		<beans:property name="defaultLocale" value="en" />
		<beans:property name="cookieName" value="myAppLocaleCookie"></beans:property>
		<beans:property name="cookieMaxAge" value="3600"></beans:property>
	</beans:bean>

	<interceptors>
		<beans:bean
		>
			<beans:property name="paramName" value="locale" />
		</beans:bean>
	</interceptors>

	<context:component-scan base-package="com.journaldev.spring" />

</beans:beans>
  1. 注解驱动的tag支持控制器编程模型,没有它,Spring将不会将HomeController识别为客户端请求的处理程序。
  2. 上下文:组件扫描提供一个包,Spring将在其中查找带注解的组件并将其自动注册为Spring Bean。
  3. 消息源bean被配置为为为我们的应用程序启用i18n。基名属性用于提供资源包的位置。classpath:messages means that resource bundles are located in the classpath and follows name pattern as messages_{locale}.properties. defaultEncoding property is used to define the encoding used for the messages.
  4. 局部求解器豆子类型org.springframework.web.servlet.i18n.CookieLocaleResolver is used to set a cookie in the client request so that further requests can easily recognize the user locale. For example, we can ask user to select the locale when he launches the web application for the first time and with the use of cookie, we can identify the user locale and automatically send locale specific response. We can also specify the default locale, cookie name and maximum age of the cookie before it gets expired and deleted by the client browser.

    如果应用程序维护用户会话,则还可以使用org.springframework.web.servlet.i18n.SessionLocaleResolver as localeResolver to use a locale attribute in the user’s session. The configuration is similar to CookieLocaleResolver.

    
    <bean id="localeResolver"
    >
    	<property name="defaultLocale" value="en" />
    </bean>
    

    如果我们不注册任何本地解算器;,接受者头部局部清除器默认情况下将使用,它通过检查accept-language header in the client HTTP request.

  5. org.springframework.web.servlet.i18n.LocaleChangeInterceptor interceptor is configured to intercept the user request and identify the user locale. The parameter name is configurable and we are using request parameter name for locale as “locale”. Without this interceptor, we won’t be able to change the user locale and send the response based on the new locale settings of the user. It needs to be part of 拦截器元素,否则Spring不会将其配置为拦截器。

如果您想知道告诉springframework加载上下文配置的配置,那么它存在于MVC应用程序的部署描述符中。


<servlet>
	<servlet-name>appServlet</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	<init-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
	</init-param>
	<load-on-startup>1</load-on-startup>
</servlet>
		
<servlet-mapping>
	<servlet-name>appServlet</servlet-name>
	<url-pattern>/</url-pattern>
</servlet-mapping>

我们可以通过更改web.xml文件配置。

我们的springi18n应用程序已经准备好了,只需将其部署到任何servlet容器中即可。通常我将其作为WAR文件导出到一个独立的tomcatweb服务器webapps目录中。

以下是我们的应用程序主页的屏幕截图。

默认主页(英语语言环境):

将Locale作为参数传递(fr Locale):

无区域设置的进一步请求:

如上图所示,我们没有在客户端请求中传递区域设置信息,但我们的应用程序仍然标识用户区域设置。现在您一定已经猜到了,这是因为我们在Spring Bean配置文件中配置的CookieLocaleResolver bean。但是你可以检查你的浏览器cookies数据来确认它。我正在使用chrome,下面的图片显示了应用程序存储的cookie数据。

请注意,cookie过期时间为一小时,即3600秒,由cookieMaxAge属性配置。

如果您检查服务器日志,您可以看到语言环境正在被记录。


INFO : com.journaldev.spring.HomeController - Welcome home! The client locale is en.
INFO : com.journaldev.spring.HomeController - Welcome home! The client locale is fr.
INFO : com.journaldev.spring.HomeController - Welcome home! The client locale is fr.

这就是springi18n示例应用程序的全部内容,请从下面的链接下载示例项目,并使用它来了解更多信息。