Jsf 通过PrimeFaces输入组件检索的Unicode输入已损坏
当我还在使用PrimeFacesV2.2.1时,我能够使用PrimeFaces输入组件(如Jsf 通过PrimeFaces输入组件检索的Unicode输入已损坏,jsf,unicode,primefaces,character-encoding,mojibake,Jsf,Unicode,Primefaces,Character Encoding,Mojibake,当我还在使用PrimeFacesV2.2.1时,我能够使用PrimeFaces输入组件(如和)键入unicode输入,如中文,并在managed bean方法中以良好的状态检索输入 然而,在我升级到PrimeFacesV3.1.1之后,所有这些字符都变成了Mojibake或问号。只有拉丁语输入是正确的,它是汉语、阿拉伯语、希伯来语、西里尔语等格式错误的字符 这是如何造成的?我如何解决它?引言 通常,在创建/恢复视图时,JSF/Facelets会在默认情况下将请求参数character encod
和
)键入unicode输入,如中文,并在managed bean方法中以良好的状态检索输入
然而,在我升级到PrimeFacesV3.1.1之后,所有这些字符都变成了Mojibake或问号。只有拉丁语输入是正确的,它是汉语、阿拉伯语、希伯来语、西里尔语等格式错误的字符
这是如何造成的?我如何解决它?引言
通常,在创建/恢复视图时,JSF/Facelets会在默认情况下将请求参数character encoding设置为UTF-8。但是,如果在创建/恢复视图之前请求了任何请求参数,那么设置正确的字符编码就太晚了。请求参数将只解析一次
素数编码失败
从2.x升级后,它在PrimeFaces 3.x中失败是由于PrimeFaces中新的isAjaxRequest()
override'PrimePartialViewContext
检查请求参数:
@Override
public boolean isAjaxRequest() {
return getWrapped().isAjaxRequest()
|| FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().containsKey("javax.faces.partial.ajax");
}
默认情况下,isAjaxRequest()
(Mojarra/MyFaces之一,正如上面的PrimeFaces代码通过getWrapped()
获得的那样)检查请求头,如下所示,这不会影响请求参数编码,因为在获得请求头时不会解析请求参数:
if (ajaxRequest == null) {
ajaxRequest = "partial/ajax".equals(ctx.
getExternalContext().getRequestHeaderMap().get("Faces-Request"));
}
但是,在创建/恢复视图之前,任何阶段侦听器或系统事件侦听器或某些应用程序工厂都可以调用isAjaxRequest()
。因此,当您使用PrimeFaces 3.x时,将在设置正确的字符编码之前解析请求参数,因此使用服务器的默认编码,通常是ISO-8859-1。这会把一切搞砸的
解决
有几种方法可以解决此问题:
@WebFilter("/*")
public class CharacterEncodingFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
chain.doFilter(request, response);
}
// ...
}
您只需要考虑到HttpServletRequest#setCharacterEncoding()
只设置请求后参数的编码,而不设置GET请求参数的编码。对于GET请求参数,您仍然需要在服务器级别对其进行配置
如果您碰巧使用了JSF实用程序库,那么已经提供了这样一个过滤器。只需将其安装在web.xml
中,作为第一个筛选器条目:
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.omnifaces.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Tomcat不支持它。它在
条目中具有URIEncoding
属性,但这仅适用于GET请求,而不适用于POST请求
core.js
JavaScript就是这样做的。如果将其设置为XMLHttpRequest
的请求头,效果会更好不起作用的解决方案 在调查这个问题时,也许你会在互联网上的某个地方偶然发现以下“解决方案”。这些解决方案在这种特定情况下是行不通的。解释如下
- 设置XML prolog:
现代浏览器忽略了这一点。这仅在Microsoft Internet Explorer浏览器中有效。即便如此,它也做得不对。永远不要使用它。所有真正的WebBrowser将改为使用响应的<?xml version='1.0' encoding='UTF-8' ?>
标题中指定的字符集属性。只要您不指定内容类型
属性,即使是MSIE也会以正确的方式执行此操作accept charset
- 设置JVM参数:
这仅由Oracle(!)JVM用于读取和解析Java源文件-Dfile.encoding=UTF-8
p:commandButton
。你的调查证明了这一点。这是一个严重的错误,因为每次单击“保存”按钮都会复制错误的编码字符。很抱歉回复太晚。我今天刚刚测试了您的解决方案。第二种解决方案不能解决问题。我还尝试使用过滤器
,但效果不太好。目前,我的应用程序中有两个过滤器:PrimeFaces的Fileupload过滤器和我自己的过滤器。我将HttpServletRequest#setCharacterEncoding()
添加到我自己的过滤器中。如果在调用另一个筛选器之前调用PrimeFaces的筛选器,是否会导致问题?您的新问题似乎只与使用System.out.println()
打印提交的数据有关。stdout(系统输出将写入的地方)是否也配置为使用UTF-8?在Eclipse中,您可以在窗口>首选项>常规>工作空间>文本文件编码中进行设置。请注意,不需要同时使用筛选器和服务器配置。两者中的一个就足够了。DB持久性问题似乎只与JDBC连接使用的字符编码有关。它是否也配置为使用UTF-8?例如,众所周知MySQL错误地使用了客户端平台编码。无论如何,要解决这个问题和任何未来的问题,请阅读@BalusC:事实上,我遵循了这篇文章,并使用UTF-8字符集重新创建了整个数据库。但是,我被困在必须为JDBC连接设置useUnicode=yes&characterEncoding=UTF-8
的部分。我已经使用GlassFish管理控制台创建了我的JDBC连接池和JDBC资源。您能告诉我如何将上述两个属性应用于JDBC连接吗?
<h:form accept-charset="UTF-8">
-Dfile.encoding=UTF-8