Кодировка UTF-8 параметров GET в JSF

У меня есть форма поиска в 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 + "&amp;faces-redirect=true";

}

Это работает хорошо, пока все, что связано с строкой "searchQuery", находится в латинском-1, оно не работает, если оно находится за пределами латинского-1.

Например, поиск "bodø" будет автоматически закодирован как "bod% F8". Однако поиск "KraJong" не будет работать, поскольку он не может кодировать "Ð".

Теперь я попробовал несколько разных подходов к решению этого вопроса, но ни один из них не работает.

  • Я пробовал кодировать сам метод searchQuery, используя URLEncode, но это приводит только к двойному кодированию, поскольку% кодируется как% 25.
  • Я попытался использовать java.net.URI для получения кодировки, но дает тот же результат, что и URLEncode.
  • Я попытался включить UTF-8 в Tomcat, используя URIEncoding = "UTF-8" в коннекторе, но это только ухудшает эту проблему, так как символы не-ascii не работают вообще.

Так на мои вопросы:

  • Могу ли я изменить способ, которым JSF 2 кодирует параметры GET?
  • Если я не могу изменить способ, которым JSF 2 кодирует параметры GET, могу ли я включить кодировку и сделать это вручную?
  • Я делаю что-то там, где здесь странно? Это похоже на то, что должно поддерживаться из коробки, но я не могу найти других с той же проблемой.

Ответ 1

Я думаю, что вы столкнулись с ошибкой в ​​регистре в JSF. Строка запроса кодируется URL-адресом ExternalContext#encodeRedirectURL(), которая использует кодировку символов ответа, полученную с помощью ExternalContext#getResponseCharacterEncoding(). Однако, хотя JSF по умолчанию использует UTF-8 как кодировку символов ответа, это устанавливается только в том случае, если представление действительно нужно визуализировать, а не когда ответ должен быть перенаправлен, поэтому кодировка символов ответа по-прежнему возвращает платформу по умолчанию ISO-8859-1, который заставляет ваши символы кодироваться в URL с использованием этой неправильной кодировки.

Я сообщил об этом как issue 2440. В то же время лучше всего явно указать кодировку символов ответа заранее.

FacesContext.getCurrentInstance().getExternalContext().setResponseCharacterEncoding("UTF-8");

Обратите внимание, что это все еще требует, чтобы сам контейнер использовал одну и ту же кодировку символов для декодирования URL-адреса запроса, поэтому вам обязательно нужно установить URIEncoding="UTF-8" в конфигурации Tomcat. Это больше не испортит персонажей, так как теперь они будут действительно UTF-8.

Ответ 2

Единственная кодировка символов, принятая для URL-адресов и заголовков HTTP, - 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 + "&amp;faces-redirect=true";

}

И тогда он должен работать для любого персонажа, который вы используете.