Мы разрабатываем некоторые веб-приложения JSF с помощью PrimeFaces.
В inputText
можно скопировать/вставить текст с символом, отличным от UTF-8, например `` (Вот символ), и сохранить страницу. Но в отрисованном HTML есть ошибка:
Ошибка: запрещенная кодовая точка U+fffe.
Браузер не показывает (скрывает) ошибку, а показывает символ, отличный от UTF-8 (работает как в обычном случае)!
Но после того, как эта страница будет отправлена с сервера в браузер в ответе Ajax, браузер показывает ошибку в консоли! И пользователь может увидеть ошибку!
Сообщение консоли:
Ошибка синтаксического анализа XML: неправильно сформирован
Как лучше всего справиться с этой ошибкой?
У меня много плохих идей. :)
Подтвердите ввод перед сохранением!
''
может вызвать непонимание со стороны пользователя. Есть много плохих персонажей, похожих на персонажей с правым акцентом.inputText
компонентах один за другим.Возможно, я смогу найти Javascript, который анализирует ответы Ajax, и исправить его.
«Минимальное» воспроизведение:
Я думаю, основная проблема в том, что Ajax использует XML. И в UTF-8 есть много символов, которые недопустимы в XML.
Как я могу быстро проверить свою строку в Java, если есть недопустимые символы?
Некоторые другие события
Есть странное поведение. Символ U+0002 удален автором JSF.
С U+FFFE характер другой. Я написал валидатор, и он выдает ValidatorException, но на этапе renderResponse появился символ U+FFFE.
Я думаю, что эта ошибка модхарры может быть очень идентичной:
Я сделал свою репродукцию с дикими мухами и праймфейсами.
Это похоже на BOM, который должен отображаться в UTF8.
`` (U+FFFE, не определено) или `` (U+FEFF, неразрывное пространство нулевой ширины, или знак порядка байтов)?
«символ, отличный от UTF-8» — такого понятия не существует. UTF-8 — это просто кодировка Unicode. На самом деле вы имеете в виду «символ, отличный от Юникода», и действительно, U+FFFE не определен в Юникоде, но он полностью кодируется в UTF-8 как байты 0xEF 0xBF 0xBE
. Кроме того, U+FFFE является недопустимым символом в XML, в спецификации очень четко указано, какие именно символы Юникода разрешены: «любой символ Юникода, за исключением суррогатных блоков, FFFE и FFFF». Поэтому просто отфильтруйте их из своей строки.
Я воспроизвел это. Проблема двойная. Это действительно ошибка в Mojarra, которая, в свою очередь, выявила еще одну ошибку в обработчике Ajax PrimeFaces. Я создал новую задачу на стороне Мохарры: https://github.com/eclipse-ee4j/mojarra/issues/5464.
Я думаю, что эта ошибка модхарры может быть очень идентичной:
https://github.com/eclipse-ee4j/mojarra/issues/4516
Да, в самом деле. Пару лет назад я исправил аналогичную проблему для реализации Mojarra, однако она касалась другого диапазона Юникода.
На данный момент вы можете обойти эту проблему, используя MyFaces вместо Mojarra (я подтвердил, что в MyFaces он работает нормально) или используя Standard Faces Ajax вместо PrimeFaces Ajax следующим образом:
<p:commandButton value = "Click" action = "#{hello.ajax}">
<f:ajax execute = "@form" render = "@form" />
</p:commandButton>
Тем не менее,
символ, отличный от UTF-8
если бы это действительно не был символ UTF-8 (U означает Unicode), он не был бы указан на веб-сайте, посвященном символам Unicode...;)
Не касаясь конкретной проблемы, я заметил, что шаблон XHTML в вашем репродукторе https://github.com/halcsi19790320/ajax-utf8-problem/blob/main/src/main/webapp/main.xhtml имеет много ненужных тегов/атрибутов, которые вы, скорее всего, пытались использовать для решения проблемы.
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html ...accept-charset = "utf-8">
<h:head>
<meta http-equiv = "Content-Type" content = "text/html; charset=utf-8" />
</h:head>
Могу заверить, что ничего из этого не имеет отношения к делу. XML-пролог не нужен ни для Facelets, ни для средней IDE. Тип документа XHTML не нужен, если клиент в конечном итоге получает простую HTML-страницу. Устаревший атрибут accept-charset
игнорируется современными браузерами (последним, кто воспринял его всерьез, был Internet Explorer). <meta http-equiv>
игнорируется, когда HTML-страница обслуживается по протоколу http(s)://
, а не по протоколу, например. file://
. Следующий шаблон HTML5 содержит меньше шума и отлично работает:
<!DOCTYPE html>
<html ...>
<h:head>
</h:head>
См. также Поддержка JavaServer Faces 2.2 и HTML5, почему до сих пор используется XHTML и принцип KISS.
Спасибо, остальные замечания тоже. Джакарта, лица HtmlUtils вырезали множество непечатаемых символов, я думаю, что можно решить лучше. Нет? «Плохие» символы — это просто u+FFFE и u+FFFF? Или они есть?
Я много думал, что может быть лучшим решением перед патчем prime/jsf... 1. Конвертер, который обрезает все входные эти символы, отличные от XML, или 2. Валидатор по умолчанию + фильтр, такой как ошибка mojarra, который удаляет эти символы из частичного ответ?
В конце концов, это действительно ошибка в Мохарре. Смотрите обновленный ответ.
И последний аспект. После этого решения недопустимые бесполезные символы XML могут быть установлены для поддержки bean-компонентов, сущностей и таблиц БД из компонентов ввода на основе строк. Я правда, что они удалены из частичного ответа, но после сохранения, ajax get и ajax post эти символы удаляются невидимыми с сервера (второе сохранение удаляет их). Если я использую валидатор, я не могу писать неправильные символы в сообщении, а затем сохранить сообщение, исчезающее (поскольку они исключены). Я думаю, что лучший способ справиться с этим - ServletFilter, который удаляет все «плохие» символы из requestMap или преобразователя строк jsf. Каково твое мнение?
Для этого вы можете использовать глобальный преобразователь строк Faces.
Пожалуйста, отредактируйте свой вопрос, чтобы предоставить минимально воспроизводимый пример.