Ответ 1
Введение
Обычно JSF/Facelets будет устанавливать кодировку символов параметра запроса в UTF-8 по умолчанию уже при создании/восстановлении представления. Но если какой-либо параметр запроса был запрошен до того, как представление было создано/восстановлено, то слишком поздно установить правильную кодировку символов. Параметры запроса будут анализироваться только один раз.
Ошибка кодирования PrimeFaces
Это не удалось в PrimeFaces 3.x после обновления из 2.x вызвано новым переопределением isAjaxRequest()
в PrimeFaces 'PrimePartialViewContext
, который проверяет параметр запроса:
@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()
может быть вызван любым слушателем фазы или прослушивателем системных событий или некоторым приложением factory до того, как представление было создано/восстановлено. Итак, когда вы используете PrimeFaces 3.x, параметры запроса будут проанализированы до того, как будет установлена правильная кодировка символов, и, следовательно, используйте кодировку по умолчанию для сервера, которая обычно является ISO-8859-1. Это все испортит.
Решение
Есть несколько способов исправить это:
-
Используйте фильтр сервлета, который устанавливает
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, такой фильтр уже предоставлен в поле,
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 не поддерживает его. Он имеет атрибут
URIEncoding
в записи<Context>
, но это относится только к запросам GET, а не к запросам POST. -
Сообщить об этом как об ошибке для PrimeFaces. Есть ли какая-либо законная причина, чтобы проверить, что HTTP-запрос является ajax-запросом, проверяя параметр запроса вместо заголовка запроса, как это было бы для стандартного JSF и, например, jQuery? Этот скрипт PrimeFaces '
core.js
делает это. Было бы лучше, если бы он установил его как заголовок запросаXMLHttpRequest
.
Решения, которые НЕ работают
Возможно, вы столкнетесь с ниже "решениями" где-то в Интернете, исследуя эту проблему. Эти решения никогда не будут работать в этом конкретном случае. Пояснение следует.
-
Настройка пролога:
<?xml version='1.0' encoding='UTF-8' ?>
Это только говорит парсеру XML использовать UTF-8 для декодирования источника XML, прежде чем создавать дерево XML вокруг него. Парсер XML, фактически используемый Facelts, SAX во время JSF показывает время сборки. Эта часть не имеет ничего общего с кодировкой HTTP-запроса/ответа.
-
Настройка метатега HTML:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
Метатег HTML игнорируется, когда страница передается через HTTP через URI
http(s)://
. Он использовался только тогда, когда страница была сохранена клиентом как файл HTML на локальной дисковой системе, а затем повторно открыта с помощью URIfile://
в браузере. -
Настройка HTML-формы принимает атрибут charset:
<h:form accept-charset="UTF-8">
Современные браузеры игнорируют это. Это имеет эффект только в браузере Microsoft Internet Explorer. Даже тогда это делает это неправильно. Никогда не используйте его. Все настоящие веб-браузеры будут использовать атрибут charset, указанный в заголовке
Content-Type
ответа. Даже MSIE сделает это правильно, пока вы не укажете атрибутaccept-charset
. -
Настройка аргумента JVM:
-Dfile.encoding=UTF-8
Это используется только JVM Oracle (!) для чтения и анализа исходных файлов Java.