Gestione delle eccezioni Spring MVC – @ControllerAdvice, @ExceptionHandler, HandlerExceptionResolver

La gestione delle eccezioni di Spring MVC è molto importante per assicurarsi di non inviare eccezioni del server al client. Oggi esamineremo la gestione delle eccezioni di Spring utilizzando @ExceptionHandler, @ControllerAdvice e HandlerExceptionResolver. Ogni applicazione web richiede una buona progettazione per la gestione delle eccezioni perché non vogliamo servire una pagina generata dal contenitore quando viene generata un’eccezione non gestita dalla nostra applicazione.

Gestione delle eccezioni di Spring

Avere un approccio ben definito alla gestione delle eccezioni è un grande punto di vantaggio per qualsiasi framework di applicazione web, detto questo il framework Spring MVC offre diverse modalità per aiutarci a ottenere una gestione delle eccezioni robusta nelle nostre applicazioni web.

  1. Controller Based – Possiamo definire metodi gestori delle eccezioni nelle nostre classi controller. Tutto ciò di cui abbiamo bisogno è annotare questi metodi con l’annotazione @ExceptionHandler. Questa annotazione prende come argomento la classe Exception. Quindi, se abbiamo definito uno di questi per la classe Exception, allora tutte le eccezioni generate dal nostro metodo gestore delle richieste saranno gestite. Questi metodi gestori delle eccezioni sono simili ad altri metodi gestori delle richieste e possiamo costruire una risposta di errore e rispondere con una pagina di errore diversa. Possiamo anche inviare una risposta di errore JSON, di cui parleremo più avanti nel nostro esempio. Se sono definiti più metodi gestori delle eccezioni, viene utilizzato il metodo gestore più vicino alla classe Exception. Ad esempio, se abbiamo due metodi gestori definiti per IOException ed Exception e il nostro metodo gestore delle richieste genera IOException, allora verrà eseguito il metodo gestore per IOException.
  2. Global Exception Handler – La gestione delle eccezioni è una preoccupazione trasversale, dovrebbe essere fatta per tutti i punti di taglio nella nostra applicazione. Abbiamo già esaminato Spring AOP e proprio per questo motivo Spring fornisce l’annotazione @ControllerAdvice che possiamo utilizzare con qualsiasi classe per definire il nostro gestore globale delle eccezioni. I metodi gestori in Global Controller Advice sono gli stessi dei metodi gestori delle eccezioni basati sul controller e vengono utilizzati quando la classe del controller non è in grado di gestire l’eccezione.
  3. HandlerExceptionResolver – Per le eccezioni generiche, la maggior parte delle volte serviamo pagine statiche. Il framework Spring fornisce l’interfaccia HandlerExceptionResolver che possiamo implementare per creare un gestore globale delle eccezioni. La ragione dietro a questo modo aggiuntivo di definire un gestore globale delle eccezioni è che il framework Spring fornisce anche classi di implementazione predefinite che possiamo definire nel nostro file di configurazione dei bean Spring per ottenere i benefici della gestione delle eccezioni del framework Spring. SimpleMappingExceptionResolver è la classe di implementazione predefinita, ci permette di configurare exceptionMappings dove possiamo specificare quale risorsa utilizzare per una particolare eccezione. Possiamo anche sovrascriverlo per creare il nostro gestore globale con le modifiche specifiche dell’applicazione, come il logging dei messaggi di eccezione.

Creiamo un progetto Spring MVC dove esamineremo l’implementazione degli approcci di gestione delle eccezioni e degli errori basati sul Controller, basati sull’AOP e basati sul risolutore delle eccezioni. Scriveremo anche un metodo gestore delle eccezioni che restituirà una risposta JSON. Se sei nuovo di JSON in Spring, leggi Spring Restful JSON Tutorial. Il nostro progetto finale avrà un aspetto simile all’immagine sotto, esamineremo tutti i componenti della nostra applicazione uno per uno.

Gestione delle eccezioni di primavera Maven Dipendenze

Oltre alle dipendenze standard di Spring MVC, avremmo anche bisogno della dipendenza Jackson JSON per il supporto JSON. Il nostro file pom.xml finale appare come segue.

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

Gestione delle eccezioni di Spring MVC Descrittore di distribuzione

Il nostro file web.xml appare come segue.

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

La maggior parte è per collegare il Framework Spring per la nostra applicazione web, tranne la definizione di error-page per l’errore 404. Quindi, quando la nostra applicazione genererà un errore 404, questa pagina verrà utilizzata come risposta. Questa configurazione è utilizzata dal container quando la nostra applicazione web Spring genera il codice di errore 404.

Gestione delle eccezioni di Spring – Classi Modello

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;
	}
}

Dato che restituiremo anche una risposta JSON, creiamo una bean Java con i dettagli dell’eccezione che verranno inviati come risposta.

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;
	}
}

Gestione delle eccezioni di Spring – Classe di eccezioni personalizzata

Creiamo una classe di eccezione personalizzata da utilizzare dalla nostra applicazione.

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);
	}
}

Nota che possiamo utilizzare l’annotazione @ResponseStatus con classi di eccezioni per definire il codice HTTP che verrà inviato dalla nostra applicazione quando questo tipo di eccezione viene lanciato dalla nostra applicazione e gestito dalle nostre implementazioni di gestione delle eccezioni. Come puoi vedere, sto impostando lo stato HTTP come 404 e abbiamo una pagina di errore definita per questo, quindi la nostra applicazione dovrebbe utilizzare la pagina di errore per questo tipo di eccezione se non stiamo restituendo alcuna vista. Possiamo anche sovrascrivere il codice di stato nel nostro metodo gestore delle eccezioni, pensalo come il codice di stato HTTP predefinito quando il nostro metodo gestore delle eccezioni non restituisce alcuna pagina vista come risposta.

Gestione delle eccezioni del controller di Spring MVC Classe Gestore Eccezioni

Osserviamo la nostra classe controller dove getteremo diversi tipi di eccezioni.

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{
		//deliberately throwing different types of exception
		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;
	}	
}

Si noti che per il gestore EmployeeNotFoundException, sto restituendo ModelAndView e quindi il codice di stato http verrà inviato come OK (200). Se avesse restituito void, allora il codice di stato http sarebbe stato inviato come 404. Esamineremo questo tipo di implementazione nel nostro gestore globale delle eccezioni. Poiché sto gestendo solo EmployeeNotFoundException nel controller, tutte le altre eccezioni generate dal nostro controller verranno gestite dal gestore globale delle eccezioni.

@ControllerAdvice e @ExceptionHandler

Ecco la nostra classe di gestione globale delle eccezioni del controller. Si noti che la classe è annotata con l’annotazione @ControllerAdvice. Inoltre, i metodi sono annotati con l’annotazione @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");
		//ritorno del codice di errore 404
	}
}

Notare che per SQLException, sto restituendo database_error.jsp come pagina di risposta con codice di stato HTTP 200. Per IOException, stiamo restituendo void con codice di stato 404, quindi la nostra error-page verrà utilizzata in questo caso. Come puoi vedere, non sto gestendo nessun altro tipo di eccezione qui, quella parte l’ho lasciata per l’implementazione di HandlerExceptionResolver.

HandlerExceptionResolver

Stiamo semplicemente estendendo SimpleMappingExceptionResolver e sovrascrivendo uno dei metodi, ma possiamo sovrascrivere il suo metodo più importante resolveException per il logging e l’invio di diversi tipi di pagine di visualizzazione. Ma è lo stesso che utilizzare l’implementazione di ControllerAdvice, quindi lo lascio. Lo useremo per configurare la pagina di visualizzazione per tutte le altre eccezioni non gestite da noi rispondendo con la pagina di errore generica.

File di configurazione per la gestione delle eccezioni di Spring

Il nostro file di configurazione del bean di Spring ha questo aspetto. Codice 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>

Fai attenzione ai bean configurati per supportare JSON nella nostra applicazione web. L’unica parte relativa alla gestione delle eccezioni è la definizione del bean simpleMappingExceptionResolver dove stiamo definendo generic_error.jsp come pagina di visualizzazione per la classe Exception. Questo assicura che qualsiasi eccezione non gestita dalla nostra applicazione non comporterà l’invio di una pagina di errore generata dal server come risposta.

Spring MVC Gestione delle Eccezioni Pagina di Visualizzazione JSP

È ora di esaminare l’ultima parte della nostra applicazione, le nostre pagine di visualizzazione che verranno utilizzate nella nostra applicazione. Codice 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>

home.jsp viene utilizzato per rispondere con dati validi, ovvero quando otteniamo id come 10 nella richiesta del client. Codice 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>

404.jsp viene utilizzato per generare la visualizzazione per il codice di stato http 404, per la nostra implementazione questo dovrebbe essere la risposta quando otteniamo id come 3 nella richiesta del client. Codice 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>

error.jsp viene utilizzato quando il metodo del gestore della richiesta della classe del controller sta generando EmployeeNotFoundException. Dovremmo ottenere questa pagina in risposta quando il valore dell’id è 1 nella richiesta del client. Codice 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>

database_error.jsp viene utilizzato quando la nostra applicazione sta generando SQLException, come configurato nella classe GlobalExceptionHandler. Dovremmo ottenere questa pagina come risposta quando il valore dell’id è 2 nella richiesta del client. Codice 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>

Questa dovrebbe essere la pagina come risposta quando si verifica un’eccezione non gestita dal nostro codice dell’applicazione e il bean simpleMappingExceptionResolver se ne occupa. Dovremmo ottenere questa pagina come risposta quando il valore dell’id nella richiesta del client è diverso da 1, 2, 3 o 10.

Esecuzione dell’applicazione di gestione delle eccezioni di Spring MVC

Just deploy the application in the servlet container you are using; I am using Apache Tomcat 7 for this example. Le immagini seguenti mostrano le diverse pagine di risposta restituite dalla nostra applicazione in base al valore di id. ID=10, risposta valida. ID=1, gestore delle eccezioni basato sul controller utilizzato ID=2, gestore globale delle eccezioni utilizzato con vista come risposta ID=3, utilizzata pagina di errore 404 ID=4, simpleMappingExceptionResolver utilizzato per la vista della risposta Come puoi vedere, abbiamo ottenuto la risposta attesa in tutti i casi.

Gestore delle eccezioni di primavera per la risposta JSON

Siamo quasi alla fine del nostro tutorial, tranne l’ultimo pezzo dove spiegherò come inviare una risposta JSON dai metodi gestori delle eccezioni. La nostra applicazione ha tutte le dipendenze JSON e il jsonMessageConverter è configurato, tutto ciò che dobbiamo fare è implementare il metodo gestore delle eccezioni. Per semplicità, riscriverò il metodo handleEmployeeNotFoundException() del controller dell’impiegato per restituire una risposta JSON. Basta aggiornare il metodo gestore delle eccezioni del controller dell’impiegato con il codice seguente e distribuire nuovamente l’applicazione.

	@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;
	}

Ora, quando utilizziamo l’id come 1 nella richiesta del client, otteniamo la seguente risposta JSON come mostrato nell’immagine sottostante. Questo è tutto per la gestione delle eccezioni di primavera e la gestione delle eccezioni di Spring MVC, si prega di scaricare l’applicazione dall’URL sottostante e sperimentare con essa per imparare di più.

Scarica il progetto di gestione delle eccezioni di primavera

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