1. LocaleContextResolver功能简介
org.springframework.web.servlet.LocaleContextResolver是 Spring MVC 中用于解析和管理用户 Locale(语言环境) 的核心接口。
//LocaleContextResolver 接口定义
public interface LocaleContextResolver extends LocaleResolver {
LocaleContext resolveLocaleContext(HttpServletRequest var1);
void setLocaleContext(HttpServletRequest var1, @Nullable HttpServletResponse var2, @Nullable LocaleContext var3);
}
//LocaleResolver 定义
public interface LocaleResolver {
Locale resolveLocale(HttpServletRequest var1);
void setLocale(HttpServletRequest var1, @Nullable HttpServletResponse var2, @Nullable Locale var3);
}
它的主要作用是:
解析请求中的 Locale 信息
从 HTTP 请求中提取用户指定的语言/地区信息(如 URL 参数、请求头、Cookie 等)。维护 Locale 上下文
将解析后的 Locale 信息存储在当前线程的上下文中(LocaleContext
),确保整个请求链(如 Controller、视图渲染)使用一致的 Locale。支持多级存储策略
提供多种实现类,支持基于请求头、会话(Session)、Cookie 或固定值的 Locale 解析。
常见 LocaleContextResolver
实现类:
实现类 | 特点 |
---|---|
AcceptHeaderLocaleResolver |
从 HTTP 请求头 Accept-Language 解析 Locale。 |
SessionLocaleResolver |
从Session中解析Locale;将 Locale 存储在用户 Session 中,适合需要持久化语言偏好的场景。 |
CookieLocaleResolver |
从Cookie中解析Locale;将 Locale 存储在 Cookie 中,适合无状态或分布式系统。 |
FixedLocaleResolver |
固定使用一个 Locale(如开发环境调试)。 |
典型使用场景
场景 | 描述 |
---|---|
国际化支持 | 根据用户选择的语言显示不同的界面内容(如中英文切换)。 |
动态语言切换 | 用户通过 URL 参数(如 ?lang=zh-CN )或按钮切换语言。 |
自动语言检测 | 通过浏览器的 Accept-Language 请求头自动识别用户语言偏好。 |
持久化语言偏好 | 使用 Cookie 或 Session 保存用户的语言选择,避免重复传递参数。 |
2. 用法演示
下面用一个例子演示使用 LocaleContextResolver
实现多语言切换功能,根据当前语言环境返回国际化消息,动态适配用户的语言偏好。
2.1 完整代码
step1. 配置 LocaleContextResolver
和拦截器
import java.util.Locale;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
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;
@Configuration
public class WebLocalConfig implements WebMvcConfigurer {
// 1. 配置 MessageSource(用于加载国际化资源文件)
@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:CustomMessages"); // 指定国际化资源文件的前缀
messageSource.setDefaultEncoding("UTF-8"); // 设置编码
return messageSource;
}
// 2. 配置 LocaleResolver(用于解析语言环境)
// 这里使用 LocaleContextResolver 的实现类 SessionLocaleResolver
@Bean
public LocaleResolver localeResolver() {
// 使用 Session 存储 Locale,避免每次请求传递参数
SessionLocaleResolver resolver = new SessionLocaleResolver();
//设置默认语言为中文(zh_CN)
resolver.setDefaultLocale(Locale.CHINA);
return resolver;
}
// 3. 配置 LocaleChangeInterceptor(用于通过 URL 参数切换语言)
@Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
// 通过 URL 参数(如 xxx?lang=zh-CN)切换语言
LocaleChangeInterceptor interceptor = new LocaleChangeInterceptor();
interceptor.setParamName("lang");// 设置参数名
return interceptor;
}
//4. 将 LocaleChangeInterceptor 添加到拦截器中,使其生效
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
}
}
step2.根据Locale解析对应的国际化语言
Service 层使用 LocaleContextHolder
获取上下文中的 Locale,并根据Locale解析对应的国际化语言
import java.util.Locale;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;
@Service
public class MessageService {
@Autowired
private MessageSource messageSource;
public String getLocalizedMessage(String code) {
// 从 LocaleContext 中获取当前线程的 Locale
Locale currentLocale = LocaleContextHolder.getLocale();
// 打印当前语言环境
System.out.println("Current Locale: " + currentLocale);
System.out.println("Trying to get message for code: " + code); // 打印 key
//根据 Locale 从对应的资源文件中加载code的值
return messageSource.getMessage(code, null, currentLocale);
}
}
step3. 新建测试Controller
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class GreetingController {
@Autowired
private MessageService messageService;
@GetMapping("GreetingController/greet")
public String greet() {
// 获取国际化消息
return messageService.getLocalizedMessage("greeting.message");
}
}
step4. 配置国际化资源文件
- CustomMessages_zh_CN.properties(中文)
greeting.message=你好,世界
- CustomMessages_en_US.properties (英文)
greeting.message=hello,world
资源位置:
src/main/resources/ ├── CustomMessages_en_US.properties // 英文 ├── CustomMessages_zh_CN.properties // 中文
step5. 测试
case1. 不设定 lang参数,默认为中文。
- 浏览器访问:http://127.0.0.1:8080/GreetingController/greet,输入如下:
case2. lang参数设为 zh_CN,输出结果为中文
case3. lang参数设为 en_US,输出结果为英文
2.2 代码流程简介
上述流程的核心原理简述:
- LocaleContextResolver 负责从请求中解析出
Locale
(如 URL 参数、请求头、Session、Cookie 等)。这里用的实现类为SessionLocaleResolver, 即WebLocalConfig#localeResolver方法中配置。 - 解析出的
Locale
会通过LocaleContextHolder.setLocale(...)
设置到当前线程的上下文中。 - 后续的组件(这里对应MessageService,也能是Controller或视图)可以直接从
LocaleContextHolder.getLocale()
获取当前的Locale
,实现上下文一致性。
通过 LocaleContextResolver
,Spring MVC 提供了灵活的国际化支持机制。开发者可以根据业务需求选择不同的 Resolver 实现,结合 LocaleChangeInterceptor
实现语言切换,使用LocaleContextHolder维护
整个请求生命周期中 Locale
上下文的一致性,从而实现灵活的国际化支持。