Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java EE (J2EE) и Spring > Servlet Filter глючит установка кодировки


Автор: dimanenok 10.4.2009, 11:32
Есть проблема которая ставит меня в тупик. Уже кажется все перепробовал.
Есть jsp страница, которая по факту в UTF-8 кодировке. 
Сервлет фильтр просто устанавливает хедер -

HttpServletResponse resp = (HttpServletResponse)response;
                if (contentType.indexOf("text/html") > -1) {
                    resp.setHeader("Content-Type", "text/html;charset=UTF-8");
                }


И все было хорошо - приходят данные в UTF-8 с заголовком 
Content-Type: text/html;charset=UTF-8

Но недавно размер jsp страницы превысил какойто весьма небольшой порог и метод 
resp.setHeader("Content-Type", "text/html;charset=UTF-8"); перестал работать. Тоесть данные приходят в UTF-8 но в заголовке шлется
Content-Type: text/html;charset=ISO-8859-1
Более того - в самом фильтре после установки resp.setHeader("Content-Type", "text/html;charset=UTF-8"); метод -
resp.getContentType() возвращает -
text/html;charset=ISO-8859-1
Несколько раз проверял - если я делаю jsp страничку чуть меньше (я это делаю тем что убираю несколько - неважно каких - строк из файла локализации который выводится в форме JavaScript массива) - то все нормально! И 
resp.getContentType() возвращает -
Content-Type: text/html;charset=UTF-8 после setHeader.

Что я уже пробовал - 
1) Пробовал добавлять 
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> на страницу - никакой реакции.
2) Пробовал ставить на странице -
<%@ page contentType="text/html; charset=UTF-8" %>
Эта штука меняет высылаемый хедер на UTF-8 но параллельно с этим она перекодирует то что уже и так в UTF-8 еще раз в UTF-8.
По видимому этот тег при парсинге интерпретирует контент который на самом деле в UTF-8 как контент в ISO-8859-1 и еще раз перекодирует в UTF-8 - получается билеберда, а мне нужно только поменять заголовок не меняя контента.
3) Пробовал вызывать 
resp.setHeader("Content-Type", "text/html;charset=UTF-8");
в самом коде JSP страницы - тоесть до возврата из chain.doFilter(request, response); 
- там этот метод работает, но почемуто также как и тег <%@ page contentType="text/html; charset=UTF-8" %> - меняет и хедер и контент.

Помогите разобраться с этой чертовщиной!

Автор: skhilkov 10.4.2009, 12:38
Цитата

<%@ page contentType="text/html; charset=UTF-8" %>
Эта штука меняет высылаемый хедер на UTF-8 но параллельно с этим она перекодирует то что уже и так в UTF-8 еще раз в UTF-8.

Есть предположение что контент у вас не utf8.... может быть страницу в каком-нить другом редакторе открыли, или еще что... Не знаю, конечно, но вот эта штука у меня везде работает железно...
если не трудно, киньте файл сюда(не содержимое, а оригинальный файл), если, конечно не секретно...

Автор: dimanenok 10.4.2009, 13:36
Цитата(skhilkov @ 10.4.2009,  12:38)
Цитата

<%@ page contentType="text/html; charset=UTF-8" %>
Эта штука меняет высылаемый хедер на UTF-8 но параллельно с этим она перекодирует то что уже и так в UTF-8 еще раз в UTF-8.

Есть предположение что контент у вас не utf8.... может быть страницу в каком-нить другом редакторе открыли, или еще что... Не знаю, конечно, но вот эта штука у меня везде работает железно...
если не трудно, киньте файл сюда(не содержимое, а оригинальный файл), если, конечно не секретно...

Вот тут моя JSP страница + русскоязычный файл локализации + Еще фильтр на всякий случай -
увидете там в коде как она его выводит - 

<%
ResourceBundle messages = ResourceBundle.getBundle("Messages",new Locale((String)session.getAttribute("selectedLocale")));
...
%>

Выложил сюда -
http://slil.ru/27436623

Проблема перестает воспроизводиться если из Messages_ru.properties например удалить любые - не важно какие - 2 строки, тогда правильно работает resp.setHeader("Content-Type", "text/html;charset=UTF-8"); и все хорошо.

PS: Может можно на этот форум напрямую файлы заливать, но не важно...

Автор: dimanenok 10.4.2009, 17:51
Я выложил, предположение оправдалось??
!HELP! smile  smile  smile 

Автор: Samotnik 11.4.2009, 15:22
метод какой ?  GET  POST ?

Автор: dimanenok 11.4.2009, 15:44
Цитата(Samotnik @ 11.4.2009,  15:22)
метод какой ?  GET  POST ?

GET /RTCrystalWeb2/main.jsp HTTP/1.1

Автор: Samotnik 11.4.2009, 15:59
так ...  значит  могу предложить 
1-  
Код

request.setCharacterEncoding("UTF-8");

2 - 
Код

<%@page pageEncoding="UTF-8"%>

3 - 
Код

<html>
<head>
  <META http-equiv="Content-Type" content="text/html;charset=UTF-8"> 

4 - 
Код

<%@page contentType="text/html;charset=UTF-8"%>

Но это уже ты все перепробовал 
кстати, на оффсайте написано 
Цитата

Currently viewing the 256 characters starting at 20a0

может в этом и проблема ?

Автор: dimanenok 13.4.2009, 19:56
Цитата(Samotnik @ 11.4.2009,  15:59)
Но это уже ты все перепробовал
кстати, на оффсайте написано 
Цитата

Currently viewing the 256 characters starting at 20a0

может в этом и проблема ?

Видел "Currently viewing the 256 characters starting at 20a0" на офсайте, но не понял как это может быть связано с проблемой?

Вобщем проблема разрешилась. Путь по которому я двигался - 
Да, тег <%@ page contentType="text/html; charset=utf-8" %> работает и работал - проблема была в том как работает JSTL локализация.
Изначально ресурс с русскими буквами считывался в UTF-8, ничего с ним не делалось а после возврата из
chain.doFilter(request, response);
я ставил -
resp.setHeader("Content-Type", "text/html; charset=UTF-8");
хедер добавлялся, и все было ОК.
Проблема была изза того что после того как ресурс вырос почемуто перестал работать -
resp.setHeader("Content-Type", "text/html; charset=UTF-8");
Но фактически никто не обязывает его работать потомучто вообще операция
resp.setHeader("Content-Type", "text/html; charset=UTF-8"); после chain.doFilter(request, response); некорректна, иными словами -

Код

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
...
resp.setHeader("Content-Type", "text/html; charset=UTF-8");
chain.doFilter(request, response); 
...
}

- можно, а
Код

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
...
chain.doFilter(request, response); 
resp.setHeader("Content-Type", "text/html; charset=UTF-8");
...
}

- типа некорректно. 

Вобщем я сделал в фильтре -
Код

            HttpServletResponse resp = (HttpServletResponse)response;
            if (resp != null && resp.getCharacterEncoding() != null) {
                resp.setCharacterEncoding("utf-8");
            }
            chain.doFilter(request, response);


Результат оказался такой - обычный русский текст отображался нормально а теги <fmt:message key="..."/> - крокозябрами. Как я выяснил - все изза того что <fmt:message key="..."/> считает что все файлы локализации заданы в iso-8859-1 а не UTF-8. Соответственно если у страницы кодировка не указана или указана как iso-8859-1 что эквивалентно, тогда <fmt:message key="..."/> соответственно не считает нужным ничего делать с данными - считывает в кодировке iso-8859-1 и передает не изменяя. Тогда по умолчанию отображается страница в iso-8859-1 кодировке (потому что такой шлется дефолтный чарсет в контенттайпе) - если в браузере руками поменять на utf-8 отобразится русский текст. Если же мы поставили кодировку страницы utf-8 - неважно как - 
resp.setCharacterEncoding("utf-8");
или 
<%@page contentType="text/html;charset=UTF-8"%>
то <fmt:message key="..."/> начинает конвертить то что уже и так в UTF-8 еще раз в UTF-8. Как это делается - есть в файле локализации буква 'о' записанная как D0BE, коль скоро система считает что это все в iso-8859-1 то интерпретирует это как 2 символа в кодировке iso-8859-1 с кодами D0 и BE. Потом ковертит 2 символа в UTF-8 - как это делает - коды у iso-8859-1 и начальные коды UTF-8 как известно совпадают, только юникод это 2 байта, соответственно получаются 2 юникодных символа с кодами 00D0 и 00BE, получается безвыходная ситуация. Чтоб этого безобразия избежать - пришлось использовать небезизвестную штуку -
C:\Program Files\Java\jdk1.6.0_03\bin>native2ascii.exe -encoding UTF-8 Messages_ru.properties Messages_ru2.properties

Остается только вопрос - нафига так сделано что приходится использовать native2ascii. Почему в J2EE нельзя - 
а) Создавая локаль указывать в какой кодировке записан файл ресурса, или если это возможно то както очень заморочено, и никто не знает
б) Или указывать после считывания ответа в фильтре -
resp.setHeader("Content-Type", "text/html;charset=UTF-8"); - чтобы выставлялся хедер и не менялся контент -
 (фактически это получается что работает для маленьких респонсов а для больших не работает).

Впрочем все это вопросы уже не сюда..

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)