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请求参数可能最终会以乱码的形式出现。表单数据最初是使用UTF-8提交和编码的。如果您使用与ISO-8859-1等不同的字符集解码UTF-8数据,则8位范围及其后面的字符(通常是那些"特殊字符",如é
、à
、ö
等)将被损坏并最终出现为é
、Ã
、ö
等。
从技术上讲,正确的解决方案是在JSF设置正确的编码之前不请求HTTP请求参数。您基本上需要检查在JSF的恢复视图阶段之前运行的所有代码,例如servlet过滤器、阶段监听器等,是否正在执行该操作。
如果您似乎找不到它,或者代码超出了您的控制范围,那么您可以告诉GlassFish使用UTF-8来解码HTTP请求参数,这样当JSF想要获取它们时就不需要更改。您可以通过将以下条目添加到/WEB-INF/glassfish-web.xml
文件的<glassfish-web-app>
中来实现:
<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输入会变得损坏。