spring mvc拦截器通过解析url参数(如lang=zh_cn)、cookie或请求头识别语言,设置locale并注入视图上下文,不修改html响应体,仅透传语言标识供模板引擎或前端使用。

Spring MVC 拦截器怎么识别并切换语言请求
HTML 页面本身没有中间件概念,所谓“通过中间件拦截语言请求”,实际是指后端(如 Spring MVC)用拦截器统一处理带语言标识的请求,并据此动态加载对应语言资源或路由。关键不是拦截 HTML,而是拦截 HTTP 请求头、URL 参数或 Cookie 中的语言线索。
常见错误现象:Accept-Language 被直接当作最终语言码使用(比如取 zh-CN 就直接加载 zh-CN.json),结果用户选了繁体中文却 fallback 到简体;或者拦截器没区分静态资源路径,把 /static/js/app.js 也扔进语言逻辑里,徒增开销。
- 优先检查 URL 参数
lang=ja→ 再查 Cookie 中的preferred-lang→ 最后 fallback 到request.getLocale()(它比navigator.language更可靠,因由服务器解析Accept-Language) - 拦截器必须排除静态资源路径:正则匹配
^/(css|js|images|fonts)/或配置mvc:resources使其不进入拦截链 - 不要在拦截器里做 JSON 语言包读取或渲染——那是前端职责;拦截器只负责设置语言上下文(如往
Model放lang值,或往HttpServletRequestattribute 中存currentLang) - 若配合数据库多语言数据源(如中英文分库),拦截器可在此刻切换
DataSource,但需确保事务和连接池兼容
拦截器如何把语言信息透传给前端 HTML
光在后端识别语言不够,前端 HTML 必须拿到这个决策结果,才能正确加载语言包、设置 document.documentElement.lang、触发 data-i18n 渲染。不能靠 JS 再去查 navigator.language,那会和后端不一致。
使用场景:SSR 场景下首屏直出多语言内容,或前后端分离时需让前端知道服务端最终选定的语言码。
- 方案一(推荐):后端在响应 HTML 时,注入一个全局变量,例如
<script>window.__LANG__ = "zh-Hans";</script>
,前端初始化 i18n 时优先读它 - 方案二:通过
直接写死根节点 lang,同时在上加data-lang="zh-Hans"供 JS 读取 - 方案三(慎用):返回 HTTP 响应头
X-Content-Language: zh-Hans,前端用fetch()读 header —— 但普通 HTML 加载不会触发 fetch,仅适用于 AJAX 场景 - 绝对避免:用
document.cookie写语言码再让 JS 读取,Cookie 有大小限制且可能被禁用
为什么不能在拦截器里直接改 HTML 响应体
有人想在拦截器的 afterCompletion 里用正则替换响应 HTML 中的文字,这是高危操作。HTML 不是纯文本,DOM 结构、注释、<script></script> 内容、CDN 路径都可能被误伤。
性能影响明显:每次响应都要流式读取、字符串替换、重写输出流,吞吐量直接掉 30%+;更严重的是,GZIP 压缩后的 HTML 无法直接正则替换,必须先解压再压,CPU 爆满。
- 真正该做的,是让拦截器把语言信息交给视图层(Thymeleaf / JSP / FreeMarker),由模板引擎在渲染时插入对应语言包键名,例如
<h1 th:text="#{home.welcome}"></h1> - 如果用纯静态 HTML + 前端 i18n,拦截器只需确保返回的 HTML 中包含正确的
window.__LANG__和lang属性,其余交给前端 JS - 若强行修改响应体,遇到
<textarea>含<script>标签</script></textarea>这类结构,正则必挂,且 XSS 风险陡增
前端 JS 怎么和后端拦截器协同避免语言错乱
最大的坑是前后端语言决策不同步:后端选了 ja,前端却因为 localStorage 里残留的 en 又切回英文,页面一半日文一半英文。
容易被忽略的地方:切换语言时,前端发请求告诉后端新选择,后端拦截器要同步更新 Cookie 或 Session,否则刷新页面就回退;但这个请求本身又得带当前语言上下文,否则拦截器不知道该存哪个。
- 前端语言切换按钮点击后,先发 POST 到
/api/lang,body 含{"lang": "ja"},后端拦截器在此接口里写入 Cookie 并返回成功 - 然后前端再执行
location.reload(),让拦截器在新请求中读到刚写的 Cookie,完成闭环 - 不要用 GET 请求改语言(如
/setlang?lang=ja),既不安全也不符合 REST,还容易被爬虫误刷 - 所有 AJAX 请求(包括语言包
fetch('/locales/ja.json'))应带上当前语言标识,比如加请求头X-Request-Language: ja,方便后端日志追踪和灰度发布
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











