Добавление cookie в ответ в Java после сброса заголовка? - PullRequest
0 голосов
/ 29 января 2010

У меня есть пользовательский тег, который выполняет некоторую обработку, а затем устанавливает cookie. Однако печенье не было установлено, и я не мог понять, почему. Другой разработчик отметил, что поскольку мы используем систему шаблонов, то есть точку, в которой оценивается тег, заголовок ответа уже сброшен как часть включения. Поскольку заголовок был отправлен, добавление cookie не представляется возможным (однако при попытке сделать это не выдается никаких исключений состояния). Это можно обойти? Может ли это звучать так?

Ответы [ 4 ]

1 голос
/ 29 января 2010

Как и другие люди говорили, вы действительно хотите избежать этого в первую очередь. Вам может понравиться хорошая модель MVC, где у вас есть несколько сервлетов, которые выполняют вашу тяжелую работу, например, базы данных, куки и все такое, а затем передают управление JSP, который фактически отображает ответ. Поскольку JSP не вызывается для генерации HTML до тех пор, пока ваши сервлеты не будут созданы, вы не должны испытывать такое горе.

Это отстойно, что setCookie не сообщает вам, когда он терпит неудачу, но также имеет смысл, что, вероятно, вы не хотите, чтобы он ломал всю вашу страницу. ServletResponse.isCommitted () скажет вам, если заголовки уже записаны, и, следовательно, если ваш вызов setCookie () не удастся.

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

doFilter(request, response, chain)
{
  BufferedResponse bufferedResponse = new BufferedResponse(response);
  try
  {
     // pass control to the next filter or to the JSP/servlet servicing the request
     chain.doFilter(request, bufferedResponse);
  }
  finally
  {
     bufferedResponse.flush();
  }
}

BufferedResponse должен был бы реализовать HttpServletResponse и в основном хранить все в памяти, пока вы явно не очистите его. В этот момент будут записаны заголовки, файлы cookie и тело буферизованного ответа.

Это будет полностью работать, но это заставит ваш веб-сервер использовать кучу дополнительной памяти, поскольку он должен буферизовать все тело ответа в памяти для каждого запроса. Кроме того, ваши страницы будут загружаться медленнее, так как сервер не может начать отправку чего-либо в браузер клиента, пока ваша страница не будет полностью завершена. Плохой юджу, мой друг.

0 голосов
/ 29 января 2010

Я думаю, что возможный обходной путь - испустить JavaScript для установки cookie. Есть конечно очевидные проблемы с этим методом. Аналогичным трюком будет включение веб-жука размером 1x1 пикселя, который при загрузке устанавливает cookie.

Я предлагаю, чтобы JSP (и аналогичные) занимались только созданием представления страницы. А также поддерживает очень небольшое состояние сеанса.

0 голосов
/ 29 января 2010

HTTP также знает, что нижние колонтитулы добавляются после тела и обрабатываются как заголовки (в том же формате). К сожалению, HttpServletResponse не имеет метода addFooter (например, Resin API имеет). Без API это было бы сложно. Нет возможности просто добавить его в тело - это будет проанализировано как тело, а не нижний колонтитул. К сожалению.

Если вы пишете html для браузера, возможно, вы можете включить фрагмент javascript в конце страницы (до </html>), чтобы установить cookie.

0 голосов
/ 29 января 2010

Хорошо, файл cookie HTTP является частью заголовка HTTP, так что это определенно будет вашей проблемой. И по этой причине вы просто не можете написать cookie после очистки заголовков HTTP.

Есть ли какая-то конкретная причина, по которой вы очищаете и не используете буферизацию ответов? В качестве альтернативы попробуйте изменить заголовок и добавить cookie, прежде чем он будет очищен.

...