Пример учебника по обработке исключений и ошибок в сервлетах

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

Исключение сервлета

Если вы обратите внимание, методы doGet() и doPost() выбрасывают исключения javax.servlet.ServletException и IOException, давайте посмотрим, что происходит, когда мы выбрасываем эти исключения из нашего приложения. Я напишу простой сервлет, который будет выбрасывать ServletException.

package com.journaldev.servlet.exception;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/MyExceptionServlet")
public class MyExceptionServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		throw new ServletException("GET method is not supported.");
	}

}

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

Ошибка сервлета

I am sure you must have seen 404 error when you are trying to hit a URL that doesn’t exists. Let’s see how our servlet container responds to 404 error. If we send request for an invalid URL, we get response HTML like below image. Again it’s a generic HTML generated by server on our application behalf and hold little to no value to the user.

Исключение и обработка ошибок сервлета

API сервлета предоставляет поддержку для пользовательских сервлетов исключений и обработчиков ошибок, которые мы можем сконфигурировать в дескрипторе развертывания. Вся цель этих сервлетов – обрабатывать исключение или ошибку, возникшие в приложении, и отправлять полезный HTML-ответ пользователю. Мы можем предоставить ссылку на домашнюю страницу приложения или некоторые детали, чтобы пользователь знал, что пошло не так. Так что сначала нам нужно создать пользовательский сервлет исключений и обработчик ошибок. Мы можем иметь несколько сервлетов обработки исключений и ошибок для приложения, но для простоты я создам один сервлет и буду использовать его как для исключений, так и для ошибок. AppExceptionHandler.java

package com.journaldev.servlet.exception;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/AppExceptionHandler")
public class AppExceptionHandler extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		processError(request, response);
	}

	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		processError(request, response);
	}

	private void processError(HttpServletRequest request,
			HttpServletResponse response) throws IOException {
		// Анализ исключения сервлета
		Throwable throwable = (Throwable) request
				.getAttribute("javax.servlet.error.exception");
		Integer statusCode = (Integer) request
				.getAttribute("javax.servlet.error.status_code");
		String servletName = (String) request
				.getAttribute("javax.servlet.error.servlet_name");
		if (servletName == null) {
			servletName = "Unknown";
		}
		String requestUri = (String) request
				.getAttribute("javax.servlet.error.request_uri");
		if (requestUri == null) {
			requestUri = "Unknown";
		}
		
		// Установить тип содержимого ответа
	      response.setContentType("text/html");
	 
	      PrintWriter out = response.getWriter();
	      out.write("Exception/Error Details");
	      if(statusCode != 500){
	    	  out.write("

Error Details

"); out.write("Status Code:"+statusCode+"
"); out.write("Requested URI:"+requestUri); }else{ out.write("

Exception Details

"); out.write("
  • Servlet Name:"+servletName+"
  • "); out.write("
  • Exception Name:"+throwable.getClass().getName()+"
  • "); out.write("
  • Requested URI:"+requestUri+"
  • "); out.write("
  • Exception Message:"+throwable.getMessage()+"
  • "); out.write("
"); } out.write("

"); out.write("Home Page"); out.write(""); } }

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

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://java.sun.com/xml/ns/javaee" xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
  <display-name>ServletExceptionHandling</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
  </welcome-file-list>
  
  <error-page>
  	<error-code>404</error-code>
  	<location>/AppExceptionHandler</location>
  </error-page>
  
  <error-page>
  <exception-type>javax.servlet.ServletException</exception-type>
  <location>/AppExceptionHandler</location>
  </error-page>
</web-app>

Как видите, очень легко указать обработчики исключений для приложения с использованием элемента error-page. Каждый элемент error-page должен содержать элемент error-code или exception-type. Мы определяем обработчик исключений в элементе location. Согласно предыдущей конфигурации, если приложение выдает ошибку 404 или ServletException, ее будет обрабатывать сервлет AppExceptionHandler. Когда возникает такое исключение или ошибка, контейнер сервлетов вызывает соответствующий HTTP-метод сервлета обработки и передает объекты запроса и ответа. Обратите внимание, что я предоставил реализацию как методов doGet(), так и doPost(), чтобы он мог обрабатывать запросы GET и POST с использованием общего метода для их обработки. Прежде чем контейнер сервлетов вызовет сервлет для обработки исключения, он устанавливает некоторые атрибуты в запросе, чтобы получить полезную информацию об исключении. Некоторые из них: javax.servlet.error.exception, javax.servlet.error.status_code, javax.servlet.error.servlet_name и javax.servlet.error.request_uri. Для исключения код статуса всегда 500, что соответствует “Внутренняя ошибка сервера”, для других типов ошибок мы получаем различные коды ошибок, такие как 404, 403 и т. д. С использованием кода состояния наша реализация представляет разные типы HTML-ответов пользователю и предоставляет гиперссылку на домашнюю страницу приложения. Теперь, когда мы обратимся к нашему сервлету, вызывающему ServletException, мы получим ответ, подобный изображенному ниже. Если мы попытаемся получить доступ к недопустимому URL, что приведет к ответу 404, мы получим ответ, подобный изображенному ниже. Не так ли это выглядит хорошо и помогает пользователю легко понять, что произошло, а также предоставляет им способ перейти к правильному местоположению? Кроме того, это позволяет избежать отправки чувствительной информации приложения пользователю. Всегда следует иметь обработчики исключений для веб-приложения. Если вы хотите обрабатывать исключения времени выполнения и все остальные исключения в единственном обработчике исключений, вы можете указать exception-type как Throwable.

<error-page>
  <exception-type>java.lang.Throwable</exception-type>
  <location>/AppExceptionHandler</location>
</error-page>

Если есть несколько записей страницы ошибок, допустим, одна для Throwable и одна для IOException, а приложение генерирует FileNotFoundException, то оно будет обработано обработчиком ошибок IOException. Вы также можете использовать страницу JSP в качестве обработчика исключений, просто укажите местоположение файла jsp, а не сопоставление сервлета. Это все, что касается обработки исключений сервлета в веб-приложении, надеюсь, вам понравилось.

Скачать Пример проекта по обработке исключений сервлета

Проверьте другие статьи в этой серии:

  1. Java веб-приложение
  2. Учебник по сервлетам Java
  3. Управление сессиями в Java
  4. Фильтр сервлетов
  5. Слушатели сервлетов
  6. Куки в сервлетах
  7. Пример загрузки и скачивания файлов сервлета

Source:
https://www.digitalocean.com/community/tutorials/servlet-exception-and-error-handling-example-tutorial