Как обрабатывать исключения из генерирующего изображения сервлета? - PullRequest
4 голосов
/ 17 мая 2010

У меня есть простое (Servlet, JSP и JSTL) веб-приложение, основной функцией которого является отображение изображений, полученных с внутреннего сервера. Сервлет контроллера перенаправляет пользователя в JSP, который, в свою очередь, использует другой сервлет для отображения результирующего изображения на том же JSP. Далее в JSP есть строка, похожая на:

<a href="<c:out value='${imageURL}'/>"><img src="<c:out value='${imageURL}'/>" alt="image view" border="1"></a>

, который вызывает GET-запрос к сервлету, генерирующему изображение, вызывая его генерацию изображения.

Мой вопрос: как мне обрабатывать исключения, выдаваемые этим генерирующим изображение сервлетом?

У меня уже есть определенная страница ошибки (в web.xml) для обработки ServletException в моем веб-приложении, но это не работает для этого генерирующего изображения сервлета, и в результате в журналах сервера Tomcat появляются следующие ошибки:

SEVERE: Exception Processing ErrorPage[exceptionType=javax.servlet.ServletException, location=/WEB-INF/ExceptionPage.jsp]
java.lang.IllegalStateException: Cannot reset buffer after response has been committed

Каково мое решение в этой ситуации?

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

Ответы [ 5 ]

3 голосов
/ 17 мая 2010

Вы не можете изменить ответ для перенаправления на страницу ошибки при отправке ответа. Уже слишком поздно менять весь ответ. Вы не можете запросить те, что уже отправлены байты обратно со стороны клиента. Вот что означает IllegalStateException. Это точка невозврата.

Лучшее, что вы можете сделать, - это просто зарегистрировать исключение или переписать код, чтобы он не записывал бит в ответ (также не устанавливая заголовки ответа), пока бизнес-логика не завершила свою задачу еще. Как только вы определили, что бизнес-логика не выдает никаких исключений, начните писать (и, следовательно, косвенно также фиксировать) ответ. Если бизнес-логика вызвала исключение, в то время как ответ еще не затронут, тогда вы можете просто безопасно выбросить его, чтобы он оказался на странице ошибки. Хотя в случае с сервлетом изображения вы также можете вместо этого направить стандартный ответ 404.gif в ответ. Это потому, что вы не можете отобразить другую HTML-страницу (ошибку) в элементе <img> и также не можете изменить URL-адрес родительской страницы JSP / HTML, так как это касается другого запроса.

1 голос
/ 17 мая 2010

Похоже, у вас проблема в ExceptionPage.jsp, а не в коде вашего сервлета.

А это

java.lang.IllegalStateException: Не удается сбросить буфер после ответа совершено

Означает, что вы уже пытались отправить ответ. Возможно, вы открыли выходной поток напрямую и записали в него некоторые данные. После того, как вы это сделали, вы не можете попытаться установить заголовки и тому подобное в ответе (они уже находятся на пути к клиенту).

Вам нужно улучшить государственное управление. Лучший способ сделать это - отделить предварительную обработку запроса от генерации ответа. Как только вы пишете ответ, вы можете только сделать или умереть. Для этого убедитесь, что вы не перехватываете IOException из выходных данных ответа, переносите их в ServletException и перенаправляете на страницу ошибок. Вы действительно не можете обработать их в контексте текущего запроса.

1 голос
/ 17 мая 2010

Согласно API сервлета, ни один сервлет не должен вызывать getWriter () и getOutputStream () для того же объекта ответа, поскольку это вызывает исключение IllegalStateException. Обычно это источник этого исключения. Если вы выводите двоичные данные, такие как и файл изображения, вы должны использовать getOutputStream ().

0 голосов
/ 17 мая 2010

Вы должны перехватить исключение и переслать запрос с помощью RequestDispatcher на нужную страницу:

  public void doGet(HttpServletRequest request, 
                HttpServletResponse response) 
throws ServletException, IOException  {

// The following piece of code results in NumberFormatException which will
// be detected by the container. The RequestDispatcher object will forward
// the same request to the other resource, here the file: forwardedJSP.jsp 
try  {
  int test = Integer.parseInt("abc");
} catch (NumberFormatException nfe) {
    RequestDispatcher rd = request.getRequestDispatcher("/forwardedJSP.jsp"); 
    rd.forward(request, response); 
}}
0 голосов
/ 17 мая 2010

Сначала определите, почему выбрасывается исключение из незаконного государства. Вместо того, чтобы иметь дело с брошенным исключением, вы, вероятно, просто хотите исправить свой код, чтобы он исчез.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...