採用 Spring MVC 內建 LocaleChangeInterceptor 攔截語言切換請求,將用戶選擇的 Locale 存入 Session,JSP/模板通過 ResourceBundle 讀取對應屬性文件實現動態文本切換。
<!-- spring-mvc.xml -->
<mvc:interceptors>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="langType"/> <!-- 請求參數名,默認 locale -->
</bean>
</mvc:interceptors>
<!-- SessionLocaleResolver 將 Locale 存入 Session -->
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
<property name="defaultLocale" value="zh_CN"/>
</bean>
LocaleChangeInterceptor 攔截含 langType 參數的請求,解析值(如 zh/en),調用 localeResolver.setLocale(request, response, new Locale("zh", "CN")) 存入 Session(屬性名 SESSION_LOCALE)。
放置於 src/main/resources(類路徑根目錄):
messages.properties(默認/回退)messages_zh_CN.properties(中文簡體)messages_en_US.properties(英文)# messages_zh_CN.properties
welcome=歡迎登錄
username=用戶名
password=密碼
login=登錄
# messages_en_US.properties
welcome=Welcome
username=Username
password=Password
login=Login
@Controller
@RequestMapping("/index")
public class IndexController {
@RequestMapping("/findex")
public String findex(HttpServletRequest request,
@RequestParam String langType,
@RequestParam String page) {
Locale locale;
switch (langType) {
case "zh": locale = Locale.SIMPLIFIED_CHINESE; break;
case "en": locale = Locale.US; break;
default: locale = Locale.getDefault();
}
// 手動設置 Session Locale(LocaleChangeInterceptor 會自動處理,此處演示原理)
request.getSession().setAttribute(
SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME, locale);
return "/front/" + page + ".jsp";
}
}
實際項目中,**無需手動 Controller**,直接在頁面鏈接帶參數即可:<a href="?langType=en&page=Home">EN</a>,攔截器自動完成切換。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="fmt" uri="https://java.sun.com/jsp/jstl/fmt" %>
<fmt:setBundle basename="messages" var="msg"/>
<html>
<head><title><fmt:message key="welcome" bundle="${msg}"/></title></head>
<body>
<a href="?langType=en&page=Home">EN</a> |
<a href="?langType=zh&page=Home"><fmt:message key="chinese" bundle="${msg}"/></a>
<h1><fmt:message key="welcome" bundle="${msg}"/></h1>
<form>
<label><fmt:message key="username" bundle="${msg}"/></label>
<input name="username"/><br/>
<label><fmt:message key="password" bundle="${msg}"/></label>
<input type="password" name="password"/><br/>
<button><fmt:message key="login" bundle="${msg}"/></button>
</form>
</body>
</html>
JSTL <fmt:message> 自動根據 Session 中的 Locale 選擇資源文件。若無 JSTL,可用原生方式:
<%
Locale locale = (Locale) session.getAttribute(SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME);
ResourceBundle bundle = ResourceBundle.getBundle("messages", locale);
%>
<%= bundle.getString("welcome") %>
<!-- Freemarker 配置 -->
<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/WEB-INF/ftl/"/>
<property name="freemarkerSettings">
<props>
<prop key="locale">zh_CN</prop> <!-- 默認 -->
</props>
</property>
</bean>
模板中使用:${msg.welcome}(需配置 MessageSource Bean 並暴露給模板)。
| 問題 | 原因 | 解決 |
|---|---|---|
| 切換語言不生效 | 未配置 SessionLocaleResolver 或攔截器順序錯誤 | 確保 localeResolver Bean 存在;攔截器在 mvc:interceptors 首位 |
| 中文亂碼 | 屬性文件編碼非 UTF-8 / JSP pageEncoding 缺失 | IDEA 設置 Properties 文件編碼 UTF-8;JSP 頁面指令 pageEncoding="UTF-8" |
| 參數名衝突 | 業務參數也叫 locale/langType | 自定義 paramName:<property name="paramName" value="lang"/> |
| Session 丟失 Locale | Session 過期/未開啟 | 檢查 web.xml session-timeout;確保請求經過 DispatcherServlet |
Spring MVC 國際化核心三件套:LocaleChangeInterceptor(參數解析)、SessionLocaleResolver(Session 存儲)、ResourceBundle/MessageSource(資源加載)。配合 JSTL fmt 標籤或模板引擎整合,即可實現零侵入式多語言切換。生產環境建議將資源文件外部化至配置中心(Apollo/Nacos),支援熱更新無需重啟。