区域设置

Spring 架构的大部分组件都支持国际化,Spring Web MVC 框架也不例外。DispatcherServlet 允许你根据客户端的语言环境自动解析消息。这是通过 LocaleResolver 对象实现的。spring-doc.cadn.net.cn

当请求进入时,DispatcherServlet 会查找一个区域设置解析器(locale resolver),如果找到,就会尝试使用它来设置区域设置(locale)。通过使用 RequestContext.getLocale() 方法,你始终可以获取由区域设置解析器所解析出的区域设置。spring-doc.cadn.net.cn

除了自动的区域设置解析之外,您还可以将一个拦截器附加到处理器映射上(有关处理器映射拦截器的更多信息,请参见拦截),以便在特定情况下(例如,基于请求中的某个参数)更改区域设置。spring-doc.cadn.net.cn

区域设置解析器(Locale resolvers)和拦截器(interceptors)定义在 org.springframework.web.servlet.i18n 包中,并以常规方式在您的应用上下文中进行配置。Spring 中包含了以下几种区域设置解析器。spring-doc.cadn.net.cn

时区

除了获取客户端的区域设置(locale)之外,通常还需要了解其时区。 LocaleContextResolver 接口对 LocaleResolver 进行了扩展, 允许解析器提供一个更丰富的 LocaleContext,其中可能包含时区信息。spring-doc.cadn.net.cn

当可用时,可以通过使用 TimeZone 方法获取用户的RequestContext.getTimeZone()。时区信息会自动被任何注册到 Spring 的 Converter 中的日期/时间 FormatterConversionService 对象所使用。spring-doc.cadn.net.cn

头部解析器

此区域设置解析器会检查客户端(例如,Web 浏览器)发送的请求中的 accept-language 头部。通常,该头部字段包含客户端操作系统的区域设置。请注意,此解析器不支持时区信息。spring-doc.cadn.net.cn

此区域设置解析器会检查客户端上可能存在的 Cookie,以查看是否指定了 Locale(区域设置)或 TimeZone(时区)。如果已指定,则使用其中的详细信息。通过此区域设置解析器的属性,您可以指定 Cookie 的名称以及最大有效期。以下示例定义了一个 CookieLocaleResolver Bean:spring-doc.cadn.net.cn

@Configuration
public class WebConfiguration {

	@Bean
	public LocaleResolver localeResolver() {
		CookieLocaleResolver localeResolver = new CookieLocaleResolver("clientlanguage");
		localeResolver.setCookieMaxAge(Duration.ofSeconds(100000));
		return localeResolver;
	}
}
@Configuration
class WebConfiguration {

	@Bean
	fun localeResolver(): LocaleResolver = CookieLocaleResolver("clientlanguage").apply {
		setCookieMaxAge(Duration.ofSeconds(100000))
	}
}
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver">

	<constructor-arg index="0" value="clientlanguage"/>

	<!-- in seconds. If set to -1, the cookie is not persisted (deleted when browser shuts down) -->
	<property name="cookieMaxAge" value="100000"/>

</bean>

会话解析器

SessionLocaleResolver 允许你从与用户请求相关联的会话中获取 LocaleTimeZone。与 CookieLocaleResolver 不同,该策略将用户本地选择的区域设置存储在 Servlet 容器的 HttpSession 中。因此,这些设置对每个会话而言都是临时的,并在会话结束时丢失。spring-doc.cadn.net.cn

请注意,这与外部会话管理机制(例如 Spring Session 项目)没有直接关系。此 SessionLocaleResolver 会针对当前的 HttpSession 评估并修改相应的 HttpServletRequest 属性。spring-doc.cadn.net.cn

区域设置拦截器

你可以通过将 LocaleChangeInterceptor 添加到某个 HandlerMapping 的定义中,来启用区域设置(locale)的切换功能。它会检测请求中的一个参数,并据此更改区域设置,调用分发器(dispatcher)应用上下文中的 setLocaleLocaleResolver 方法。下面的示例表明,所有对 *.view 资源的请求,只要包含名为 siteLanguage 的参数,就会改变区域设置。例如,请求 URL domain.com/home.view?siteLanguage=nl 会将网站语言更改为荷兰语。以下示例展示了如何拦截并处理区域设置:spring-doc.cadn.net.cn

@Configuration
public class WebConfiguration {

	@Bean
	public LocaleResolver localeResolver() {
		return new CookieLocaleResolver();
	}

	@Bean
	public SimpleUrlHandlerMapping urlMapping() {
		SimpleUrlHandlerMapping urlHandlerMapping = new SimpleUrlHandlerMapping();
		LocaleChangeInterceptor interceptor = new LocaleChangeInterceptor();
		interceptor.setParamName("siteLanguage");
		urlHandlerMapping.setInterceptors(interceptor);
		urlHandlerMapping.setUrlMap(Map.of("/**/*.view", "someController"));
		return urlHandlerMapping;
	}
}
@Configuration
class WebConfiguration {

	@Bean
	fun localeResolver(): LocaleResolver {
		return CookieLocaleResolver()
	}

	@Bean
	fun urlMapping() = SimpleUrlHandlerMapping().apply {
		setInterceptors(LocaleChangeInterceptor().apply {
			paramName = "siteLanguage"
		})
		urlMap = mapOf("/**/*.view" to "someController")
	}
}
<bean id="localeChangeInterceptor"
	  class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
	<property name="paramName" value="siteLanguage"/>
</bean>

<bean id="localeResolver"
	  class="org.springframework.web.servlet.i18n.CookieLocaleResolver"/>

<bean id="urlMapping"
	  class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
	<property name="interceptors">
		<list>
			<ref bean="localeChangeInterceptor"/>
		</list>
	</property>
	<property name="mappings">
		<value>/**/*.view=someController</value>
	</property>
</bean>