Введение
Обычно 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()
может вызываться любым слушателем фазы или системным событиемслушатель или какая-либо фабрика приложений до представление было создано / восстановлено.Таким образом, когда вы используете 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 , такой фильтр уже имеется в наличии 1049 *.Просто установите его, как показано ниже в 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?JavaScript-код PrimeFaces core.js
делает это.Было бы лучше, если бы он установил его в качестве заголовка запроса XMLHttpRequest
.
Решения, которые НЕ работают
Возможно, вы наткнетесь наниже «решения» где-то в интернете, пока исследуем эту проблему.Эти решения никогда не будут работать в этом конкретном случае.Объяснение приведено ниже.
Настройка пролога XML:
<?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 через http(s)://
URI.Он используется только в том случае, когда клиент сохраняет страницу в виде файла HTML на локальной дисковой системе, а затем повторно открывает URI file://
в браузере.
Настройка HTML-формы принимает атрибут charset:
<h:form accept-charset="UTF-8">
Современные браузеры игнорируют это.Это действует только в браузере Microsoft Internet Explorer.Даже тогда он делает это неправильно.Никогда не используйте это.Вместо этого все настоящие веб-браузеры будут использовать атрибут charset, указанный в заголовке Content-Type
ответа.Даже MSIE будет делать это правильно, если вы не укажете атрибут accept-charset
.
Установка аргумента JVM:
-Dfile.encoding=UTF-8
Это используется толькоOracle (!) JVM для чтения и анализа исходных файлов Java.