Tratamento de Exceções Spring MVC – @ControllerAdvice, @ExceptionHandler, HandlerExceptionResolver

Spring MVC Exception Handling é muito importante para garantir que você não esteja enviando exceções do servidor para o cliente. Hoje, vamos analisar o tratamento de exceções do Spring usando @ExceptionHandler, @ControllerAdvice e HandlerExceptionResolver. Qualquer aplicação web requer um bom design para o tratamento de exceções, pois não queremos servir uma página gerada pelo contêiner quando ocorrer uma exceção não tratada em nossa aplicação.

Tratamento de Exceções no Spring

Ter uma abordagem bem definida para o tratamento de exceções é um grande ponto positivo para qualquer framework de aplicação web. Dito isso, o framework Spring MVC se destaca quando se trata de tratamento de exceções e erros em nossas aplicações web. O Spring MVC Framework oferece as seguintes maneiras para nos ajudar a alcançar um tratamento robusto de exceções.

  1. Baseado no Controlador – Podemos definir métodos de tratamento de exceção em nossas classes de controlador. Tudo que precisamos fazer é anotar esses métodos com a anotação @ExceptionHandler. Esta anotação recebe a classe Exception como argumento. Portanto, se tivermos definido um desses para a classe Exception, então todas as exceções lançadas pelo nosso método de manipulador de solicitação serão tratadas. Esses métodos de tratamento de exceção são apenas como outros métodos de manipulador de solicitação e podemos construir uma resposta de erro e responder com uma página de erro diferente. Também podemos enviar uma resposta de erro JSON, que veremos mais adiante em nosso exemplo. Se houver vários métodos de tratamento de exceção definidos, então o método de tratamento mais próximo da classe Exception é usado. Por exemplo, se tivermos dois métodos de tratamento definidos para IOException e Exception e nosso método de manipulador de solicitação lançar IOException, então o método de tratamento para IOException será executado.
  2. Tratador Global de Exceções – O tratamento de exceções é uma preocupação transversal, deve ser feito para todos os pontos de corte em nossa aplicação. Já examinamos o Spring AOP e é por isso que o Spring fornece a anotação @ControllerAdvice que podemos usar com qualquer classe para definir nosso tratador global de exceções. Os métodos manipuladores no Conselho Global do Controlador são os mesmos que os métodos de tratamento de exceção baseados em controlador e são usados quando a classe do controlador não consegue lidar com a exceção.
  3. HandlerExceptionResolver – Para exceções genéricas, na maioria das vezes, servimos páginas estáticas. O Spring Framework fornece a interface HandlerExceptionResolver que podemos implementar para criar um manipulador global de exceções. A razão por trás dessa maneira adicional de definir um manipulador global de exceções é que o Spring Framework também fornece classes de implementação padrão que podemos definir em nosso arquivo de configuração de bean Spring para obter benefícios no tratamento de exceções do Spring Framework. SimpleMappingExceptionResolver é a classe de implementação padrão, que nos permite configurar exceções onde podemos especificar qual recurso usar para uma exceção específica. Também podemos substituí-lo para criar nosso próprio manipulador global com alterações específicas do aplicativo, como o registro de mensagens de exceção.

Vamos criar um projeto Spring MVC onde examinaremos a implementação de abordagens de tratamento de exceções e erros baseadas em Controller, AOP e Exception Resolver. Também escreveremos um método de manipulador de exceções que retornará uma resposta JSON. Se você é novo em JSON no Spring, leia Spring Restful JSON Tutorial. Nosso projeto final terá a aparência da imagem abaixo, e examinaremos todos os componentes de nossa aplicação um por um.

Spring Exception Handling Maven Dependencies

Além das dependências padrão do Spring MVC, também precisaremos da dependência Jackson JSON para suporte a JSON. Nosso arquivo pom.xml final parece com o seguinte:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.journaldev.spring</groupId>
	<artifactId>SpringExceptionHandling</artifactId>
	<name>SpringExceptionHandling</name>
	<packaging>war</packaging>
	<version>1.0.0-BUILD-SNAPSHOT</version>
	<properties>
		<java-version>1.6</java-version>
		<org.springframework-version>4.0.2.RELEASE</org.springframework-version>
		<org.aspectj-version>1.7.4</org.aspectj-version>
		<org.slf4j-version>1.7.5</org.slf4j-version>
		<jackson.databind-version>2.2.3</jackson.databind-version>
	</properties>
	<dependencies>
		<!-- Jackson -->
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>${jackson.databind-version}</version>
		</dependency>
		<!-- Spring -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${org.springframework-version}</version>
			<exclusions>
				<!-- Exclude Commons Logging in favor of SLF4j -->
				<exclusion>
					<groupId>commons-logging</groupId>
					<artifactId>commons-logging</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>

		<!-- AspectJ -->
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjrt</artifactId>
			<version>${org.aspectj-version}</version>
		</dependency>

		<!-- Logging -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>${org.slf4j-version}</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>jcl-over-slf4j</artifactId>
			<version>${org.slf4j-version}</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>${org.slf4j-version}</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.15</version>
			<exclusions>
				<exclusion>
					<groupId>javax.mail</groupId>
					<artifactId>mail</artifactId>
				</exclusion>
				<exclusion>
					<groupId>javax.jms</groupId>
					<artifactId>jms</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.jdmk</groupId>
					<artifactId>jmxtools</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.jmx</groupId>
					<artifactId>jmxri</artifactId>
				</exclusion>
			</exclusions>
			<scope>runtime</scope>
		</dependency>

		<!-- @Inject -->
		<dependency>
			<groupId>javax.inject</groupId>
			<artifactId>javax.inject</artifactId>
			<version>1</version>
		</dependency>

		<!-- Servlet -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.5</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>jsp-api</artifactId>
			<version>2.1</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>

		<!-- Test -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.7</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-eclipse-plugin</artifactId>
				<version>2.9</version>
				<configuration>
					<additionalProjectnatures>
						<projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
					</additionalProjectnatures>
					<additionalBuildcommands>
						<buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
					</additionalBuildcommands>
					<downloadSources>true</downloadSources>
					<downloadJavadocs>true</downloadJavadocs>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>2.5.1</version>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
					<compilerArgument>-Xlint:all</compilerArgument>
					<showWarnings>true</showWarnings>
					<showDeprecation>true</showDeprecation>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.codehaus.mojo</groupId>
				<artifactId>exec-maven-plugin</artifactId>
				<version>1.2.1</version>
				<configuration>
					<mainClass>org.test.int1.Main</mainClass>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

I have updated Spring Framework, AspectJ, Jackson and slf4j versions to use the latest one.

Descritor de Implantação do Tratamento de Exceções do Spring MVC

Nosso arquivo web.xml parece com o seguinte:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="https://java.sun.com/xml/ns/javaee"
	xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

	<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/spring/root-context.xml</param-value>
	</context-param>
	
	<!-- Creates the Spring Container shared by all Servlets and Filters -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- Processes application requests -->
	<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring/spring.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
		
	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

	<error-page>
		<error-code>404</error-code>
		<location>/resources/404.jsp</location>
	</error-page>
</web-app>

A maior parte destina-se a integrar o Spring Framework à nossa aplicação web, exceto a página de erro definida para o erro 404. Assim, quando nossa aplicação lançar um erro 404, esta página será usada como resposta. Essa configuração é utilizada pelo contêiner quando nossa aplicação web Spring lança o código de erro 404.

Tratamento de Exceções do Spring – Classes de Modelo

I have defined Employee bean as model class, however we will be using it in our application just to return valid response in specific scenario. We will be deliberately throwing different types of exceptions in most of the cases.

package com.journaldev.spring.model;

public class Employee {

	private String name;
	private int id;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}
}

Desde que também estaremos retornando uma resposta JSON, vamos criar uma classe Java bean com detalhes da exceção que será enviada como resposta.

package com.journaldev.spring.model;

public class ExceptionJSONInfo {

	private String url;
	private String message;
	
	public String getUrl() {
		return url;
	}
	public void setUrl(String url) {
		this.url = url;
	}
	public String getMessage() {
		return message;
	}
	public void setMessage(String message) {
		this.message = message;
	}
}

Tratamento de Exceções no Spring – Classe de Exceção Personalizada

Vamos criar uma classe de exceção personalizada a ser usada por nossa aplicação.

package com.journaldev.spring.exceptions;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

@ResponseStatus(value=HttpStatus.NOT_FOUND, reason="Employee Not Found") //404
public class EmployeeNotFoundException extends Exception {

	private static final long serialVersionUID = -3332292346834265371L;

	public EmployeeNotFoundException(int id){
		super("EmployeeNotFoundException with id="+id);
	}
}

Observe que podemos usar a anotação @ResponseStatus com classes de exceção para definir o código HTTP que será enviado por nossa aplicação quando este tipo de exceção for lançado e tratado por nossas implementações de tratamento de exceção. Como você pode ver, estou definindo o status HTTP como 404 e temos uma página de erro definida para isso, então nossa aplicação deve usar a página de erro para este tipo de exceção se não estivermos retornando nenhuma visualização. Também podemos substituir o código de status em nosso método de manipulação de exceção, pense nisso como o código de status http padrão quando nosso método de manipulação de exceção não está retornando nenhuma página de visualização como resposta.

Controlador de Tratamento de Exceções Spring MVC

Vamos analisar nossa classe de controlador onde iremos lançar diferentes tipos de exceções.

package com.journaldev.spring.controllers;

import java.io.IOException;
import java.sql.SQLException;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.journaldev.spring.exceptions.EmployeeNotFoundException;
import com.journaldev.spring.model.Employee;
import com.journaldev.spring.model.ExceptionJSONInfo;

@Controller
public class EmployeeController {
	
	private static final Logger logger = LoggerFactory.getLogger(EmployeeController.class);
	
	@RequestMapping(value="/emp/{id}", method=RequestMethod.GET)
	public String getEmployee(@PathVariable("id") int id, Model model) throws Exception{
		//intencionalmente gerando diferentes tipos de exceção
		if(id==1){
			throw new EmployeeNotFoundException(id);
		}else if(id==2){
			throw new SQLException("SQLException, id="+id);
		}else if(id==3){
			throw new IOException("IOException, id="+id);
		}else if(id==10){
			Employee emp = new Employee();
			emp.setName("Pankaj");
			emp.setId(id);
			model.addAttribute("employee", emp);
			return "home";
		}else {
			throw new Exception("Generic Exception, id="+id);
		}
		
	}
	
	@ExceptionHandler(EmployeeNotFoundException.class)
	public ModelAndView handleEmployeeNotFoundException(HttpServletRequest request, Exception ex){
		logger.error("Requested URL="+request.getRequestURL());
		logger.error("Exception Raised="+ex);
		
		ModelAndView modelAndView = new ModelAndView();
	    modelAndView.addObject("exception", ex);
	    modelAndView.addObject("url", request.getRequestURL());
	    
	    modelAndView.setViewName("error");
	    return modelAndView;
	}	
}

Observe que para o manipulador EmployeeNotFoundException, estou retornando um ModelAndView e, portanto, o código de status HTTP será enviado como OK (200). Se estivesse retornando void, então o código de status HTTP teria sido enviado como 404. Vamos analisar esse tipo de implementação em nosso manipulador de exceção global. Como estou lidando apenas com EmployeeNotFoundException no controlador, todas as outras exceções lançadas pelo nosso controlador serão tratadas pelo manipulador de exceção global.

@ControllerAdvice e @ExceptionHandler

Aqui está nossa classe de controlador de manipulador de exceção global. Observe que a classe está anotada com a anotação @ControllerAdvice. Além disso, os métodos são anotados com a anotação @ExceptionHandler.

package com.journaldev.spring.controllers;

import java.io.IOException;
import java.sql.SQLException;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;

@ControllerAdvice
public class GlobalExceptionHandler {

	private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
	
	@ExceptionHandler(SQLException.class)
	public String handleSQLException(HttpServletRequest request, Exception ex){
		logger.info("SQLException Occured:: URL="+request.getRequestURL());
		return "database_error";
	}
	
	@ResponseStatus(value=HttpStatus.NOT_FOUND, reason="IOException occured")
	@ExceptionHandler(IOException.class)
	public void handleIOException(){
		logger.error("IOException handler executed");
		//retornando código de erro 404
	}
}

Perceba que, para SQLException, estou retornando database_error.jsp como página de resposta com o código de status HTTP 200. Para IOException, estamos retornando void com o código de status 404, então nossa error-page será usada nesse caso. Como você pode ver, não estou tratando nenhum outro tipo de exceção aqui, essa parte eu deixei para a implementação do HandlerExceptionResolver.

HandlerExceptionResolver

Estamos apenas estendendo SimpleMappingExceptionResolver e sobrescrevendo um de seus métodos, mas podemos sobrescrever o método mais importante resolveException para fazer log e enviar diferentes tipos de páginas de visualização. No entanto, isso é o mesmo que usar a implementação do ControllerAdvice, então estou deixando isso de lado. Vamos usá-lo para configurar a página de visualização para todas as outras exceções não tratadas por nós, respondendo com uma página de erro genérica.

Arquivo de Configuração de Tratamento de Exceção do Spring

Nosso arquivo de configuração de bean do Spring parece o seguinte. Código spring.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="https://www.springframework.org/schema/mvc"
	xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
	xmlns:beans="https://www.springframework.org/schema/beans"
	xmlns:context="https://www.springframework.org/schema/context"
	xsi:schemaLocation="https://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
		https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
		https://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

	<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
	
	<!-- Enables the Spring MVC @Controller programming model -->
	<annotation-driven />

	<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
	<resources mapping="/resources/**" location="/resources/" />

	<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
	<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<beans:property name="prefix" value="/WEB-INF/views/" />
		<beans:property name="suffix" value=".jsp" />
	</beans:bean>
	
	
	<beans:bean id="simpleMappingExceptionResolver" class="com.journaldev.spring.resolver.MySimpleMappingExceptionResolver">
		<beans:property name="exceptionMappings">
			<beans:map>
				<beans:entry key="Exception" value="generic_error"></beans:entry>
			</beans:map>
		</beans:property>
		<beans:property name="defaultErrorView" value="generic_error"/>
	</beans:bean>
	
	<!-- Configure to plugin JSON as request and response in method handler -->
	<beans:bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
		<beans:property name="messageConverters">
			<beans:list>
				<beans:ref bean="jsonMessageConverter"/>
			</beans:list>
		</beans:property>
	</beans:bean>
	
	<!-- Configure bean to convert JSON to POJO and vice versa -->
	<beans:bean id="jsonMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
	</beans:bean>
	
	<context:component-scan base-package="com.journaldev.spring" />
	
</beans:beans>

Observe os beans configurados para suportar JSON em nossa aplicação web. A única parte relacionada ao tratamento de exceções é a definição do bean simpleMappingExceptionResolver, onde estamos definindo generic_error.jsp como a página de visualização para a classe Exception. Isso garante que qualquer exceção não tratada pela nossa aplicação não resultará no envio da página de erro gerada pelo servidor como resposta.

Spring MVC Tratamento de Exceções Páginas de Visualização JSP

É hora de analisar a última parte de nossa aplicação, nossas páginas de visualização que serão usadas em nossa aplicação. Código home.jsp:

<%@ taglib uri="https://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
	<title>Home</title>
</head>
<body>
	<h3>Hello ${employee.name}!</h3><br>
	<h4>Your ID is ${employee.id}</h4>  
</body>
</html>

O home.jsp é usado para responder com dados válidos, ou seja, quando recebemos o id como 10 na solicitação do cliente. Código 404.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>404 Error Page</title>
</head>
<body>

<h2>Resource Not Found Error Occured, please contact support.</h2>

</body>
</html>

O 404.jsp é usado para gerar a visualização para o código de status http 404, para nossa implementação, isso deve ser a resposta quando obtemos o id como 3 na solicitação do cliente. Código error.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<%@ taglib uri="https://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Error Page</title>
</head>
<body>
<h2>Application Error, please contact support.</h2>

<h3>Debug Information:</h3>

Requested URL= ${url}<br><br>

Exception= ${exception.message}<br><br>

<strong>Exception Stack Trace</strong><br>
<c:forEach items="${exception.stackTrace}" var="ste">
	${ste}
</c:forEach>

</body>
</html>

O error.jsp é usado quando o método manipulador de solicitação da classe controladora está lançando a EmployeeNotFoundException. Devemos obter esta página como resposta quando o valor do id é 1 na solicitação do cliente. Código database_error.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Database Error Page</title>
</head>
<body>

<h2>Database Error, please contact support.</h2>

</body>
</html>

O database_error.jsp é usado quando nossa aplicação está lançando SQLException, conforme configurado na classe GlobalExceptionHandler. Devemos obter esta página como resposta quando o valor do id é 2 na solicitação do cliente. Código generic_error.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Generic Error Page</title>
</head>
<body>

<h2>Unknown Error Occured, please contact support.</h2>

</body>
</html>

Isso deve ser a página como resposta quando ocorrer qualquer exceção não tratada pelo código de nossa aplicação e o bean simpleMappingExceptionResolver cuida disso. Devemos obter esta página como resposta quando o valor do id na solicitação do cliente for diferente de 1, 2, 3 ou 10.

Executando a Aplicação de Tratamento de Exceção do Spring MVC

Apenas implante o aplicativo no contêiner de servlet que você está usando, estou usando o Apache Tomcat 7 como exemplo. As imagens abaixo mostram as diferentes páginas de resposta retornadas pelo nosso aplicativo com base no valor do id. ID=10, resposta válida. ID=1, manipulador de exceções baseado em controlador usado ID=2, manipulador de exceções global usado com visualização como resposta ID=3, página de erro 404 usada ID=4, simpleMappingExceptionResolver usado para visualização de resposta Como você pode ver, obtivemos a resposta esperada em todos os casos.

Resposta de Exceção do Manipulador Spring em JSON

Estamos quase terminando nosso tutorial, exceto pela última parte onde explicarei como enviar uma resposta JSON dos métodos do manipulador de exceção. Nossa aplicação tem todas as dependências JSON e o jsonMessageConverter está configurado, tudo o que precisamos fazer é implementar o método do manipulador de exceção. Para simplicidade, vou reescrever o método handleEmployeeNotFoundException() do EmployeeController para retornar uma resposta JSON. Apenas atualize o método do manipulador de exceção do EmployeeController com o código abaixo e implante a aplicação novamente.

	@ExceptionHandler(EmployeeNotFoundException.class)
	public @ResponseBody ExceptionJSONInfo handleEmployeeNotFoundException(HttpServletRequest request, Exception ex){
		
		ExceptionJSONInfo response = new ExceptionJSONInfo();
		response.setUrl(request.getRequestURL().toString());
		response.setMessage(ex.getMessage());
		
		return response;
	}

Agora, quando usamos o id como 1 na solicitação do cliente, obtemos a seguinte resposta JSON como mostrado na imagem abaixo. Isso é tudo para o Tratamento de Exceção do Spring e o Tratamento de Exceção do Spring MVC, por favor, baixe a aplicação a partir da URL abaixo e explore mais para aprender.

Projeto de Tratamento de Exceção do Spring

Source:
https://www.digitalocean.com/community/tutorials/spring-mvc-exception-handling-controlleradvice-exceptionhandler-handlerexceptionresolver