Exceção do Servlet e Tutorial de Exemplo de Tratamento de Erros

Hoje vamos analisar a Exceção de Servlet e o Tratamento de Erro. Algum tempo atrás, escrevi um post sobre Tratamento de Exceções em Java, mas quando se trata de aplicativos web, precisamos de mais do que o tratamento normal de exceções em Java.

Exceção de Servlet

Se você observar, os métodos doGet() e doPost() lançam javax.servlet.ServletException e IOException. Vamos ver o que acontece quando lançamos essas exceções em nosso aplicativo. Vou escrever um servlet simples que lançará a 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.");
	}

}

Agora, quando invocamos este servlet através do navegador com o método GET, obtemos uma resposta como na imagem abaixo. Como o navegador entende apenas HTML, quando nosso aplicativo lança uma exceção, o contêiner servlet processa a exceção e gera uma resposta HTML. Essa lógica é específica para o contêiner servlet. Estou usando o Tomcat e recebendo esta página de erro. Se você usar outros servidores como JBoss ou Glassfish, poderá obter uma resposta HTML de erro diferente. O problema com esta resposta é que não tem valor para o usuário. Além disso, está mostrando as classes do nosso aplicativo e detalhes do servidor para o usuário, o que não faz sentido e não é bom do ponto de vista da segurança.

Erro no Servlet

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.

Exceção no Servlet e Tratamento de Erros

A API do Servlet oferece suporte a servlets personalizados para tratamento de exceções e erros, que podemos configurar no descritor de implantação. O objetivo desses servlets é lidar com a exceção ou erro gerado pela aplicação e enviar uma resposta HTML útil ao usuário. Podemos fornecer um link para a página inicial da aplicação ou alguns detalhes para informar ao usuário o que deu errado. Primeiramente, precisamos criar um servlet personalizado para tratamento de exceções e erros. Podemos ter vários servlets de tratamento de exceções e erros para a aplicação, mas para simplicidade, vou criar um único servlet e usá-lo para ambas as exceções e erros. 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 {
		// Analisar a exceção do servlet
		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";
		}
		
		// Definir o tipo de conteúdo da resposta
	      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(""); } }

Vamos ver como podemos configurá-lo no descritor de implantação e depois entender sua implementação e como funciona.

<?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>

Como você pode ver, é muito fácil especificar servlets de tratamento de exceções para a aplicação usando o elemento error-page. Cada elemento error-page deve ter o elemento error-code ou exception-type. Definimos o servlet de tratamento de exceções no elemento location. Com base na configuração acima, se a aplicação lançar um erro 404 ou ServletException, ele será tratado pelo servlet AppExceptionHandler. Quando tal exceção e cenário de erro aparecem, o contêiner de servlet invocará o método HTTP correspondente do servlet de Tratamento de Exceções e passará o objeto de solicitação e resposta. Observe que forneci a implementação tanto do método doGet() quanto do método doPost() para que ele possa lidar com solicitações GET e POST e usando um método comum para processá-las. Antes do contêiner de servlet invocar o servlet para lidar com a exceção, ele define alguns atributos na solicitação para obter informações úteis sobre a exceção, alguns deles são javax.servlet.error.exception, javax.servlet.error.status_code, javax.servlet.error.servlet_name e javax.servlet.error.request_uri. Para exceção, o código de status é sempre 500, que corresponde ao “Erro interno do servidor”, para outros tipos de erro, obtemos diferentes códigos de erro, como 404, 403 etc. Usando o código de status, nossa implementação apresenta diferentes tipos de resposta HTML ao usuário. Ele também fornece um hiperlink para a página inicial da aplicação. Agora, quando acessarmos nosso servlet que está lançando ServletException, receberemos uma resposta como a imagem abaixo. Se tentarmos acessar uma URL inválida que resultará em uma resposta 404, receberemos uma resposta como a imagem abaixo. Não parece bom e ajuda o usuário a entender facilmente o que aconteceu e fornece a eles um meio de ir para o local correto. Também evita enviar informações sensíveis da aplicação para o usuário. Devemos sempre ter manipuladores de exceção em vigor para nossa aplicação web. Se você quiser lidar com exceções de tempo de execução e todas as outras exceções em um único manipulador de exceções, você pode fornecer o tipo de exceção como Throwable.

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

Se houver várias entradas de páginas de erro, digamos uma para Throwable e outra para IOException e a aplicação lançar FileNotFoundException, então será tratada pelo manipulador de erro de IOException. Você também pode usar uma página JSP como manipulador de exceções, basta fornecer o local do arquivo JSP em vez do mapeamento do servlet. Isso é tudo para o tratamento de exceções de servlet em aplicativos da web, espero que tenha gostado.

Baixe o Projeto de Exemplo de Tratamento de Exceções de Servlet

Confira outros artigos desta série:

  1. Aplicação Web Java
  2. Tutorial de Servlet Java
  3. Gerenciamento de Sessão em Java
  4. Filtro Servlet
  5. Ouvintes de Servlet
  6. Cookies em Servlets
  7. Exemplo de Upload e Download de Arquivos em Servlet

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