当前位置 : 主页 > 网络推广 > seo >

jsf – 通过PrimeFaces输入组件检索的Unicode输入已损坏

来源:互联网 收集:自由互联 发布时间:2021-06-16
当我仍然使用PrimeFaces v2.2.1时,我可以使用PrimeFaces输入组件(例如 p:inputText)来键入诸如中文的unicode输入.和 p:editor,并且在托管bean方法中检索输入形状良好. 但是,升级到PrimeFaces v3.1.1之后
当我仍然使用PrimeFaces v2.2.1时,我可以使用PrimeFaces输入组件(例如< p:inputText>)来键入诸如中文的unicode输入.和< p:editor>,并且在托管bean方法中检索输入形状良好.

但是,升级到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源文件.

网友评论