Ввод Unicode, полученный через компоненты ввода PrimeFaces, поврежден

Когда я все еще использовал PrimeFaces v2.2.1, я мог набирать ввод Unicode, например китайский, с компонентом ввода PrimeFaces, таким как<p:inputText> а также<p:editor>и получить входные данные в хорошем состоянии в методе управляемого компонента.

Однако после того, как я обновился до PrimeFaces v3.1.1, все эти символы стали Mojibake или вопросительными знаками. Хорошо вводится только латинский ввод, это искаженные символы китайского, арабского, иврита, кириллицы и т. Д.

Как это вызвано и как я могу решить это?

Ответы на вопрос(1)

Решение Вопроса
Введение

са в UTF-8 по умолчанию уже при создании / восстановлении представления. Но если какой-либо параметр запроса был запрошендо представление было создано / восстановлено, тогда уже слишком поздно, чтобы установить правильную кодировку символов. Параметры запроса будут проанализированы только один раз.

Ошибка кодировки PrimeFaces

То, что это не удалось в PrimeFaces 3.x после обновления с 2.x, вызвано новымisAjaxRequest() переопределить в PrimeFacesPrimePartialViewContext который проверяет параметр запроса:

@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 вам все равно необходимо настроить его на уровне сервера.

Если вам случится использовать служебную библиотеку JSFOmniFacesтакой фильтр уже предоставляется из коробки,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 JavaScript делает это. Было бы лучше, если бы он установил его как заголовок запроса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 на локальной дисковой системе, а затем открывает ееfile:// URI в браузере.

Настройка 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.

 Matt Handy23 мар. 2012 г., 14:11
Спасибо за этот великий пост. Я столкнулся с этой проблемой вчера и уже изолировал ееp:commandButton прежде чем найти решение фильтра. Ваше расследование доказало это. Это серьезная ошибка, поскольку неправильно закодированные символы дублируются при каждом нажатии кнопки сохранения.
 BalusC18 июн. 2012 г., 21:24
Ваша новая проблема, кажется, связана исключительно с использованиемSystem.out.println() распечатать представленные данные. Это стандартный вывод (там, гдеSystem.out напишу в) тоже настроен на использование UTF-8? В Eclipse вы можете установить его вОкно> Настройки> Общие> Рабочая область> Кодировка текстового файла, Обратите внимание, что с помощьюобе фильтр и конфигурация сервера не нужны. Достаточно одного из обоих.
 Mr.J4mes18 июн. 2012 г., 14:11
Извините за задержку с ответом. Я только что проверил ваши решения сегодня. Второе решение не решает проблему. Я также пытался использоватьfilter но это не сработало. В настоящее время в моем приложении есть 2 фильтра: Fileupload Filter от PrimeFaces и мой собственный фильтр. я добавилHttpServletRequest#setCharacterEncoding() в мой собственный фильтр. Если фильтр PrimeFaces вызывается раньше другого, вызовет ли он проблему?
 BalusC18 июн. 2012 г., 23:19
Проблема с сохранением БД, по-видимому, связана исключительно с кодировкой символов, используемой соединением JDBC. Он также настроен на использование UTF-8? Например, известно, что MySQL неправильно использует кодировку клиентской платформы. В любом случае, чтобы исправить это и любые будущие проблемы, пожалуйста, прочитайтеbalusc.blogspot.com/2009/05/...
 Mr.J4mes18 июн. 2012 г., 23:36
@BalusC: На самом деле, я следил за этим постом и заново создал всю базу данных, используя кодировку UTF-8. Тем не менее, я застрял в той части, где я должен установитьuseUnicode=yes&characterEncoding=UTF-8 для соединения JDBC. Я создал свой пул соединений JDBC и ресурс JDBC, используя консоль администратора GlassFish. Не могли бы вы сказать мне, как я могу применить вышеупомянутые 2 свойства к моим соединениям JDBC?

Ваш ответ на вопрос