我在 JSF 中有一个搜索表单,它是使用 RichFaces 4 自动完成组件以及以下 JSF 2 页面和 Java bean 实现的。我使用 Tomcat 6 和 7 来运行该应用程序。
...
<h:commandButton value="#{msg.search}" styleClass="search-btn" action="#{autoCompletBean.doSearch}" />
...
在 AutoCompleteBean 中
public String doSearch() {
//some logic here
return "/path/to/page/with/multiple_results?query=" + searchQuery + "&faces-redirect=true";
}
只要“searchQuery”字符串中的所有内容都在 Latin-1 中,此方法就可以正常工作,如果在 Latin-1 之外,则此方法不起作用。
例如,搜索“bodø”将自动编码为“bod%F8”。然而,搜索“Kra Ðong”将不起作用,因为它无法编码“Д。
我现在尝试了几种不同的方法来解决这个问题,但都不起作用。
所以我的问题是:
ExternalContext#encodeRedirectURL()
进行 URL 编码,它使用由 ExternalContext#getResponseCharacterEncoding()
获得的响应字符编码。然而,虽然 JSF 默认使用 UTF-8 作为响应字符编码,但这仅在实际渲染视图时设置,而不是在重定向响应时设置,因此响应字符编码仍然返回平台默认值 ISO-8859-1
这会导致您的字符使用这种错误的编码进行 URL 编码。
我已将其报告为问题 2440。同时,您最好的选择是事先自己明确设置响应字符编码。
FacesContext.getCurrentInstance().getExternalContext().setResponseCharacterEncoding("UTF-8");
注意,这仍然要求容器本身使用相同的字符编码来解码请求URL,所以你当然需要在Tomcat的配置中设置
URIEncoding="UTF-8"
。这不会再弄乱字符,因为它们现在将是真正的 UTF-8。
HTTP URL 和标头接受的唯一字符编码是 US-ASCII,您需要对这些字符进行 URL 编码才能将它们发送回应用程序。在 Java 中执行此操作的最简单方法是:
public String doSearch() {
//some logic here
String encodedSearchQuery = java.net.URLEncoder.encode( searchQuery, "UTF-8" );
return "/path/to/page/with/multiple_results?query=" + encodedSearchQuery + "&faces-redirect=true";
}
然后它应该适用于您使用的任何角色。