Mr.*_*mes 13 unicode jsf character-encoding primefaces mojibake
当我还是用PrimeFaces V2.2.1,我能键入Unicode输入诸如与PrimeFaces输入组件中国如<p:inputText>和<p:editor>,并检索在管理bean方法好形状的输入.
但是,在我升级到PrimeFaces v3.1.1后,所有这些字符都变成了Mojibake或问号.只有拉丁语输入才能正常,中文,阿拉伯语,希伯来语,西里尔语等字符会变得格格不入.
这是怎么造成的,我该如何解决?
Bal*_*usC 24
通常,在创建/恢复视图时,JSF/Facelets会将请求参数字符编码默认设置为UTF-8.但是,如果在创建/恢复视图之前请求了任何请求参数,那么设置正确的字符编码为时已晚.请求参数将仅被解析一次.
从2.x升级后它在PrimeFaces 3.x中失败是由isAjaxRequest()PrimeFaces中的新覆盖PrimePartialViewContext检查请求参数引起的:
@Override
public boolean isAjaxRequest() {
return getWrapped().isAjaxRequest()
|| FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().containsKey("javax.faces.partial.ajax");
}
Run Code Online (Sandbox Code Playgroud)
默认情况下isAjaxRequest()(Mojarra/MyFaces之一,如上面的PrimeFaces代码所获得的那样getWrapped())检查请求头如下,这不会影响请求参数编码,因为获取请求头时将不会解析请求参数:
if (ajaxRequest == null) {
ajaxRequest = "partial/ajax".equals(ctx.
getExternalContext().getRequestHeaderMap().get("Faces-Request"));
}
Run Code Online (Sandbox Code Playgroud)
但是,在创建/恢复视图之前,isAjaxRequest()可以由任何阶段侦听器或系统事件侦听器或某些应用程序工厂调用.因此,当您使用PrimeFaces 3.x时,将在设置正确的字符编码之前解析请求参数,因此使用服务器的默认编码,通常是ISO-8859-1.这会弄乱一切.
有几种方法可以解决它:
使用使用UTF-8 设置的servlet过滤器ServletRequest#setCharacterEncoding().设置响应编码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);
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
您只需要考虑HttpServletRequest#setCharacterEncoding()只设置POST请求参数的编码,而不是GET请求参数的编码.对于GET请求参数,您仍需要在服务器级别配置它.
如果您碰巧使用JSF实用程序库OmniFaces,那么已经提供了这样的过滤器,即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>
Run Code Online (Sandbox Code Playgroud)
重新配置服务器以使用UTF-8而不是ISO-8859-1作为默认编码.GlassFish中的情况下,这将是添加以下条目的事<glassfish-web-app>了的/WEB-INF/glassfish-web.xml文件:
<parameter-encoding default-charset="UTF-8" />
Run Code Online (Sandbox Code Playgroud)
Tomcat不支持它.它URIEncoding在<Context>条目中具有属性,但这仅适用于GET请求,而不适用于POST请求.
将其报告为PrimeFaces的错误.有没有真正的任何正当理由,以检查HTTP请求是通过检查的请求参数,而不是请求头一样,你会为标准JSF和例如jQuery的做一个Ajax请求?PrimeFaces的core.jsJavaScript正在这样做.如果它将其设置为请求标头会更好XMLHttpRequest.
也许你会在调查这个问题时偶然发现互联网上某处的"解决方案".这些解决方案不会在这种特定情况下起作用.说明如下.
设置XML prolog:
<?xml version='1.0' encoding='UTF-8' ?>
Run Code Online (Sandbox Code Playgroud)
这只会告诉XML解析器在构建XML源代码之前使用UTF-8解码XML源代码.在JSF 视图构建期间,Facelts实际使用的XML解析器是SAX .这部分与HTTP请求/响应编码完全无关.
设置HTML元标记:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
Run Code Online (Sandbox Code Playgroud)
当通过http(s)://URI 通过HTTP提供页面时,将忽略HTML元标记.仅当页面由客户端保存为本地磁盘系统上的HTML文件,然后由file://浏览器中的URI 重新打开时,才会使用它.
设置HTML表单接受charset属性:
<h:form accept-charset="UTF-8">
Run Code Online (Sandbox Code Playgroud)
现代浏览器忽略这一点 这仅在Microsoft Internet Explorer浏览器中有效.即便如此,它也是错误地做错了.永远不要使用它.所有真正的Web浏览器都将使用Content-Type响应头中指定的charset属性.只要您没有指定accept-charset属性,即使MSIE也会以正确的方式执行.
设置JVM参数:
-Dfile.encoding=UTF-8
Run Code Online (Sandbox Code Playgroud)
这仅供Oracle(!)JVM用于读取和解析Java源文件.
| 归档时间: |
|
| 查看次数: |
11994 次 |
| 最近记录: |