Это вызвано Tomcat, но основной проблемой является спецификация Java Servlet 4, которая неверна и устарела.
Изначально HTML 4.0.1 говорил, что application/x-www-form-urlencoded
кодированные октеты должны быть декодированы как US-ASCII . Спецификация сервлета изменила это, сказав, что, если кодировка запроса не указана, октеты должны быть декодированы как ISO-8859-1. Tomcat просто следует спецификации сервлета.
В спецификации сервлета Java есть две проблемы. Во-первых, современная интерпретация application/x-www-form-urlencoded
заключается в том, что закодированные октеты должны быть декодированы с использованием UTF-8 . Вторая проблема заключается в том, что привязка декодирования октетов к кодировке ресурсов смешивает два уровня декодирования.
Еще раз посмотрите на это POST
содержание:
fullName=Fl%C3%A1vio+Jos%C3%A9
Вы заметите, что это ASCII !! Не имеет значения, считаете ли вы кодировку HTTP-запроса POST
равной ISO-8859-1
, UTF-8
или US-ASCII
- вы все равно получите те же символы Unicode до декодирования октеты! Какая кодировка используется для декодирования октетов кодирования, является совершенно отдельной.
В качестве еще одного примера, скажем, я загружаю текстовый файл instructions.txt
, который четко помечен как ISO-8859-1 и содержит URI https://example.com/example.jsp?fullName=Fl%C3%A1vio+Jos%C3%A9
. То, что текстовый файл имеет кодировку ISO-8859-1
, означает ли это, что мне нужно декодировать %C3%A
с использованием ISO-8859-1? Конечно, нет! Кодировка, используемая для декодирования символов URI , представляет собой отдельный уровень декодирования поверх типа содержимого charset ! Точно так же октеты значений, закодированных в application/x-www-form-urlencoded
, должны быть декодированы с использованием UTF-8, независимо от основной кодировки ресурса.
Существует несколько обходных путей, некоторые из которых можно найти, просмотрев часто задаваемые вопросы по кодировке символов Tomcat, чтобы «везде использовать UTF-8» .
Установите кодировку символа запроса в вашем файле web.xml
.
Добавьте в файл WEB-INF/web.xml
следующее:
<request-character-encoding>UTF-8</request-character-encoding>
Этот параметр не зависит от реализации контейнера сервлета и определен в спецификации сервлета. (Вы также можете поместить его в файл conf/web.xml
Tomcat, если хотите использовать глобальные настройки и не хотите изменять конфигурацию Tomcat.)
Установите SetCharacterEncodingFilter
в файле web.xml
.
Tomcat имеет собственный эквивалент: используйте org.apache.catalina.filters.SetCharacterEncodingFilter
в файле WEB-INF/web.xml
, как указано выше в разделе часто задаваемых вопросов Tomcat, и как показано в https://stackoverflow.com/a/37833977/421049,, приведенном ниже:
<filter>
<filter-name>setCharacterEncodingFilter</filter-name>
<filter-class>org.apache.catalina.filters.SetCharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>setCharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Это заставит ваше веб-приложение работать только на Tomcat, поэтому лучше поместить его в установочный файл Tomcat conf/web.xml
, как упоминалось выше. Фактически установки Tomcat conf/web.xml
имеют эти два раздела, но закомментированы; просто раскомментируйте их, и все должно работать.
Принудительная кодировка символов запроса в UTF-8 в JSP или сервлете.
Вы можете принудительно ввести кодировку символов запроса сервлета в UTF-8, где-то в начале JSP:
<% request.setCharacterEncoding("UTF-8"); %>
Но это уродливо, громоздко, подвержено ошибкам и идет вразрез с современными лучшими практиками - больше не следует использовать JSP-скриптлеты.
Надеемся, что мы сможем получить более новую спецификацию Java-сервлета, чтобы удалить любые отношения между набором ресурсов и декодированием application/x-www-form-urlencoded
октетов и просто заявить, что application/x-www-form-urlencoded
октеты должны быть декодированы как UTF-8, как это принято в современной практике. уточнено по последним спецификациям W3C и WHATWG.
Обновление: Я обновил часто задаваемые вопросы Tomcat по Проблемы кодировки символов с этой информацией.