基于URL映射的SpringBoot国际化与本地化实现问题
基于URL路径实现Spring Boot国际化Locale切换
我正在项目中实现国际化与本地化功能,希望通过URL路径映射(如/en、/ja、/fr)来切换Locale。目前查到的方案大多是用LocaleChangeInterceptor的setParamName("lang")方法,通过请求参数切换,比如:
http://localhost:8081/index?lang=fr
但我想要实现的是基于URL路径的切换,比如http://localhost:8081/index/en。
以下是我当前的配置代码:
@Configuration public class MessageConfig implements WebMvcConfigurer { @Bean public LocaleResolver localeResolver() { SessionLocaleResolver slr = new SessionLocaleResolver(); slr.setDefaultLocale(Locale.JAPAN); slr.setLocaleAttributeName("session.current.locale"); slr.setTimeZoneAttributeName("session.current.timezone"); return slr; } @Bean public LocaleChangeInterceptor localChangeInterceptor() { LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor(); localeChangeInterceptor.setParamName("lang"); return localeChangeInterceptor; } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(localChangeInterceptor()); } @Bean public MessageSource messageSource() { ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); messageSource.setBasenames("language/messages"); messageSource.setDefaultEncoding("UTF-8"); return messageSource; } }
资源文件结构为language目录下,包含默认的messages.properties,以及对应英文、日文等语言的messages_en.properties、messages_ja.properties等国际化资源文件。
实现基于URL路径的Locale切换方案
1. 自定义拦截器解析路径中的语言标识
默认的LocaleChangeInterceptor仅支持从请求参数提取语言,我们需要自定义拦截器,从URL路径中解析语言代码:
public class PathLocaleChangeInterceptor extends LocaleChangeInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException { String requestURI = request.getRequestURI(); String[] pathSegments = requestURI.split("/"); // 假设语言标识在路径最后一位,可根据业务调整位置 if (pathSegments.length > 1) { String langCode = pathSegments[pathSegments.length - 1]; // 验证语言代码有效性,避免非法值 if (Arrays.asList("en", "ja", "fr").contains(langCode)) { request.setAttribute(getParamName(), langCode); } } return super.preHandle(request, response, handler); } }
2. 更新配置类替换拦截器
修改MessageConfig,用自定义拦截器替换默认的LocaleChangeInterceptor:
@Configuration public class MessageConfig implements WebMvcConfigurer { @Bean public LocaleResolver localeResolver() { SessionLocaleResolver slr = new SessionLocaleResolver(); slr.setDefaultLocale(Locale.JAPAN); slr.setLocaleAttributeName("session.current.locale"); slr.setTimeZoneAttributeName("session.current.timezone"); return slr; } @Bean public LocaleChangeInterceptor pathLocaleChangeInterceptor() { PathLocaleChangeInterceptor localeInterceptor = new PathLocaleChangeInterceptor(); localeInterceptor.setParamName("lang"); return localeInterceptor; } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(pathLocaleChangeInterceptor()); } @Bean public MessageSource messageSource() { ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); messageSource.setBasenames("language/messages"); messageSource.setDefaultEncoding("UTF-8"); return messageSource; } }
3. 配置通用路径映射(可选)
如果希望所有请求都支持路径后缀带语言标识,可以在控制器中配置通用转发逻辑:
@Controller public class LangForwardController { @GetMapping("/{lang}/**") public String forwardToActualPath(@PathVariable String lang, HttpServletRequest request) { // 移除路径中的语言标识,转发到实际接口 String actualPath = request.getRequestURI().replaceFirst("/" + lang, ""); return "forward:" + actualPath; } }
4. 验证效果
访问http://localhost:8081/index/en,拦截器会提取en并设置Locale为英文,系统自动加载messages_en.properties的资源;访问http://localhost:8081/index/ja则切换为日文环境。
内容的提问来源于stack exchange,提问作者Daryll David Dagondon
相关产品推荐
相关产品推荐

