Java и Tomcat: пару слов о работе с HTML формами

21 Окт
2011

Как известно, любая HTML форма содержит поля. Некоторые из них заполняются пользователем, в другие (поля типа hidden) разработчики помещают служебную информацию. При отправке HTML формы все поля (ключи и значения) должны быть закодированы в формате x-www-form-urlencoded.

Замечу, что в случае закачки файлов на сервер все происходит немного подругому, но здесь я этот случая рассматривать не буду.
Кодированием полей занимается сама форма перед отправкой. Поля могут быть текстовыми и содержать кириллицу. Формат x-www-form-urlencoded не фиксирует кодировку текста, передаваемого в полях формы. А браузеры используют либо кодировку страницы, на которой лежит форма, либо кодировку, указанную в атрибуте «accept-charset» у формы.

И вот тут то и возникает проблема, которой посвящена данная статья. Значение используемой кодировки не передается на сервер! Поле accept-charset у HTTP request при отправке формы всегда совпадает со аналогичным значением на странице, на которой форма расположена.
Сервлет Tomcat, отвечающий за об обработку формы, считает в этом случае кодировку полей неопределенной (функция ServletRequest.getCharacterEncoding() возвращает null). А т.к. текст декодировать все равно надо (в JavaVM все строки хранятся в UTF-16) — при вызове HttpServletRequest.getParameter(xxx) происходит преобразование символов исходя из предположения, что они имеют кодировку ISO-8859-1.

Правильное решение следующее — написать фильтр, перехватывающие все запросы к приложению или некую их группу, в котором явно установить кодировку вызвав функцию HttpServletRequest.setCharacterEncoding().

public class PreProcessFilter implements Filter {
              @Override
               public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException {
                            request.setCharacterEncoding("UTF-8");
                            chain.doFilter(request, response);
              }
}


В фильтре данный метод нужно вызывать еще и потому, что он должен быть вызван до первого чтения параметров HTTP запроса.

Кстати, похожая проблема возникает и с русскими символами в URL. Причем на них по какой-то причине функция setCharacterEncoding() не действует. Зато зафиксировать кодировку можно в файле настроек Tomcat — server.xml. Для этого нужно найти в данном файле элемент, описывающий требуемую endpoint. Как правило, его получить следующим XPath-запросом: /Server/Service/Connector[@protocol=«HTTP/1.1»]. После чего нужно установить у него атрибут URIEncoding=«UTF-8».

Источники информации:
HTML Forms — Processing form data
URL — rfc1738
Wiki про URL encoding — он же Percent-encoding
Описание Tomcat ServletRequest
Атрибут accept-charset HTML формы
Описание Tomcat server.xml
По материалам Хабрахабр.



загрузка...

Комментарии:

Наверх