但是,升级到PrimeFaces v3.1.1之后,所有这些字符都会变成Mojibake或者问号.只有拉丁语的输入才能正常,中文,阿拉伯语,希伯来语,西里尔字体等字符变形.
这是怎么造成的,我该如何解决呢?
介绍通常,当创建/恢复视图时,JSF / Facelets将默认将请求参数字符编码设置为UTF-8.但是,如果在创建/恢复视图之前请求了任何请求参数,则设置正确的字符编码为时已晚.请求参数将被解析一次.
PrimeFaces编码失败
PrimeFaces的PrimePartialViewContext中的新的isAjaxRequest()覆盖是从2.x升级之后在PrimeFaces 3.x中失败的,它会检查请求参数:
@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的服务器的默认编码.这会乱七八糟的一切.
解决方案
有几种方法来解决它:
>使用servlet filter设置ServletRequest#setCharacterEncoding()
与UTF-8.通过ServletResponse#setCharacterEncoding()
设置响应编码是不必要的,因为它不会受到此问题的影响.
@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()仅设置POST请求参数的编码,而不是GET请求参数.对于GET请求参数,您仍然需要在服务器级配置它.
如果您碰巧使用JSF实用程序库OmniFaces,那么这个过滤器已经在框the CharacterEncodingFilter
中提供了.只需将它安装在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>
>重新配置服务器以使用UTF-8而不是ISO-8859-1作为默认编码.在Glassfish的情况下,这将是将以下条目添加到< glassfish-web-app>的/WEB-INF/glassfish-web.xml文件:
<parameter-encoding default-charset="UTF-8" />
Tomcat不支持它.它在< Context>中具有URIEncoding属性条目,但这仅适用于GET请求,而不适用于POST请求.
>将其报告为PrimeFaces的错误.通过检查一个请求参数而不是一个请求头来检查作为ajax请求的HTTP请求是否真的有正当的理由,就像标准的JSF和jQuery一样? PrimeFaces的core.js JavaScript正在做.如果将其设置为XMLHttpRequest的请求头,那将会更好.
不行的解决方案
也许你会在互联网上的某个地方的“解决方案”下面绊倒,同时调查这个问题.这些解决方案在这种具体情况下不会奏效.说明如下.
>设置XML规范:
<?xml version='1.0' encoding='UTF-8' ?>
这只是告诉XML解析器在构建XML树之前使用UTF-8对XML源进行解码.在JSF view build time中,Facelts实际使用的XML解析器是SAX.这部分与HTTP请求/响应编码完全无关.
>设置HTML元标记:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
当HTTP通过http(s):// URI提供页面时,HTML元标记被忽略.仅当客户端将页面保存为本地磁盘系统上的HTML文件,然后由浏览器中的文件// URI重新打开时,才会使用该页面.
>设置HTML表单接受charset属性:
<h:form accept-charset="UTF-8">
现代浏览器忽略这一点.这仅在Microsoft Internet Explorer浏览器中有效.即使这样做是错误的.永远不要使用它所有真正的web浏览器将改为使用响应的Content-Type头中指定的charset属性.只要你没有指定accept-charset属性,MSIE就可以正确的做到这一点.
>设置JVM参数:
-Dfile.encoding=UTF-8
这仅由Oracle(!)JVM用于读取和解析Java源文件.