JSF/Facelets 默认使用 UTF-8 解码 HTTP 请求参数。GlassFish 本身默认使用 ISO-8859-1 解码 HTTP 请求参数。HTTP 请求参数只能解析和解码一次,每当代码第一次请求请求参数时就会发生这种情况request.getParameter("name")
。因此,如果在 JSF 将请求参数编码设置为 UTF-8之前第一次请求请求参数,那么它将(错误地)使用 ISO-8859-1 进行解析。
当 JSF 在恢复视图阶段需要设置请求参数编码时,如下所示,
request.setCharacterEncoding("UTF-8");
当请求参数已经被解析时,GlassFish 会准确地显示这个警告。
不希望的结果是,所有这些 HTTP 请求参数都可能最终出现在Mojibake中。表单数据最初是使用 UTF-8 提交和编码的。如果您使用不同的字符集(如 ISO-8859-1)解码 UTF-8 数据,则 8 位及以上范围内的字符(通常是那些“特殊字符”,如é
、à
、ö
等)将被损坏并最终在é
, Ã
,ö
等
从技术上讲,正确的解决方案是在JSF 设置正确的编码之前不请求 HTTP 请求参数。您基本上需要检查在 JSF 的恢复视图阶段之前运行的所有代码,例如 servlet 过滤器、阶段侦听器等,如果它们没有这样做的话。
如果您似乎找不到它,或者代码超出您的控制范围,那么您可以告诉 GlassFish 使用 UTF-8 来解码 HTTP 请求参数,这样 JSF 想要获取时就不需要更改它他们。您可以通过将以下条目添加到文件<glassfish-web-app>
中来做到这一点/WEB-INF/glassfish-web.xml
:
<parameter-encoding default-charset="UTF-8"/>
sun-web.xml
(注意:文件和根条目之前<sun-web-app>
分别被调用过)
应该注意的是,这是 GlassFish 特有的,当您将 web 应用程序部署到不同的服务器时,这一切都不起作用。规范的独立于服务器的方法是创建一个servlet 过滤器,它在方法中基本上完成以下工作doFilter()
:
request.setCharacterEncoding("UTF-8");
chain.doFilter(request, response);
并确保它在需要收集任何 HTTP 请求参数的任何其他过滤器之前被映射。
更新:至于GlassFish为什么提前设置,可能是PrimeFaces造成的。另请参阅此相关问题:通过 PrimeFaces 输入组件检索的 Unicode 输入变得损坏。