Spring MVC Exception Handling – @ControllerAdvice, @ExceptionHandler, HandlerExceptionResolver

Spring MVC Exception Handling ist sehr wichtig, um sicherzustellen, dass Serverausnahmen nicht an den Client gesendet werden. Heute werden wir uns die Ausnahmebehandlung in Spring ansehen, die @ExceptionHandler, @ControllerAdvice und HandlerExceptionResolver verwendet. Jede Webanwendung benötigt ein gutes Design für die Ausnahmebehandlung, da wir keine vom Container generierte Seite bereitstellen möchten, wenn eine unbehandelte Ausnahme von unserer Anwendung ausgelöst wird.

Spring Exception Handling

Ein gut definierter Ansatz zur Ausnahmebehandlung ist ein großer Pluspunkt für jedes Webanwendungsframework. Das gesagt, das Spring MVC Framework liefert gute Ergebnisse, wenn es um Ausnahme- und Fehlerbehandlung in unseren Webanwendungen geht. Das Spring MVC Framework bietet folgende Möglichkeiten, um eine robuste Ausnahmebehandlung zu erreichen.

  1. Controller-basiert – Wir können Ausnahmehandler-Methoden in unseren Controller-Klassen definieren. Alles, was wir tun müssen, ist, diese Methoden mit der @ExceptionHandler-Annotation zu kennzeichnen. Diese Annotation nimmt die Exception-Klasse als Argument. Wenn wir also eine davon für die Exception-Klasse definiert haben, werden alle von unserer Request-Handler-Methode geworfenen Ausnahmen behandelt. Diese Ausnahmehandler-Methoden sind genauso wie andere Request-Handler-Methoden, und wir können Fehlerantworten erstellen und mit verschiedenen Fehlerseiten antworten. Wir können auch JSON-Fehlerantworten senden, darauf werden wir in unserem Beispiel später eingehen. Wenn mehrere Ausnahmehandler-Methoden definiert sind, wird die Methode ausgeführt, die der Exception-Klasse am nächsten liegt. Zum Beispiel, wenn wir zwei Handler-Methoden für IOException und Exception definiert haben und unsere Request-Handler-Methode IOException auslöst, wird die Handler-Methode für IOException ausgeführt.
  2. Globaler Ausnahmehandler – Die Fehlerbehandlung ist eine übergreifende Angelegenheit, sie sollte für alle Punkte in unserer Anwendung erfolgen. Wir haben bereits einen Blick auf Spring AOP geworfen, und deshalb bietet Spring die @ControllerAdvice-Annotation, die wir mit jeder Klasse verwenden können, um unseren globalen Ausnahmehandler zu definieren. Die Handler-Methoden im Global Controller Advice sind genauso wie Controller-basierte Ausnahmehandler-Methoden und werden verwendet, wenn die Controller-Klasse die Ausnahme nicht behandeln kann.
  3. HandlerExceptionResolver – Für generische Ausnahmen werden in den meisten Fällen statische Seiten bereitgestellt. Das Spring Framework bietet die Schnittstelle HandlerExceptionResolver, die wir implementieren können, um einen globalen Ausnahmebehandler zu erstellen. Der Grund für diese zusätzliche Möglichkeit, einen globalen Ausnahmebehandler zu definieren, ist, dass das Spring-Framework auch Standardimplementierungsklassen bereitstellt, die wir in unserer Spring-Bean-Konfigurationsdatei definieren können, um die Vorteile der Ausnahmebehandlung des Spring-Frameworks zu nutzen. SimpleMappingExceptionResolver ist die Standardimplementierungsklasse. Sie ermöglicht es uns, Ausnahmemappings zu konfigurieren, in denen wir angeben können, welche Ressource für eine bestimmte Ausnahme verwendet werden soll. Wir können sie auch überschreiben, um unseren eigenen globalen Handler mit unseren applikationsspezifischen Änderungen zu erstellen, wie z.B. das Protokollieren von Ausnahmemeldungen.

Erstellen wir ein Spring-MVC-Projekt, in dem wir uns die Implementierung von Controller-basierter, AOP-basierter und Ausnahmelösungs-basierter Ansätze zur Ausnahme- und Fehlerbehandlung ansehen werden. Wir werden auch eine Ausnahmebehandlungsmethode schreiben, die eine JSON-Antwort zurückgibt. Wenn Sie neu in JSON in Spring sind, lesen Sie Spring Restful JSON Tutorial. Unser finales Projekt wird wie im folgenden Bild aussehen, wir werden alle Komponenten unserer Anwendung nacheinander betrachten.

Spring-Ausnahmeverarbeitung Maven-Abhängigkeiten

Abgesehen von den Standard-Spring-MVC-Abhängigkeiten benötigen wir auch die Jackson JSON-Abhängigkeit für die JSON-Unterstützung. Unsere finale pom.xml-Datei sieht wie folgt aus.

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

Spring-MVC-Ausnahmeverarbeitungs-Bereitstellungsbeschreibung

Unsere web.xml-Datei sieht wie folgt aus.

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

Der größte Teil dient dem Einbinden des Spring-Frameworks in unsere Webanwendung, außer der error-page, die für den 404-Fehler definiert ist. Wenn unsere Anwendung einen 404-Fehler wirft, wird diese Seite als Antwort verwendet. Diese Konfiguration wird vom Container verwendet, wenn unsere Spring-Webanwendung den Fehlercode 404 wirft.

Spring-Ausnahmeverarbeitung – Modellklassen

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

Da wir auch JSON-Antworten zurückgeben werden, erstellen wir eine Java-Bean mit Ausnahmedetails, die als Antwort gesendet werden sollen.

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

Ausnahmenbehandlung in Spring – Benutzerdefinierte Ausnahmeklasse

Erstellen wir eine benutzerdefinierte Ausnahmeklasse, die von unserer Anwendung verwendet wird.

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

Beachten Sie, dass wir die @ResponseStatus-Annotation mit Ausnahmeklassen verwenden können, um den HTTP-Code zu definieren, der von unserer Anwendung gesendet wird, wenn dieser Typ von Ausnahme von unserer Anwendung ausgelöst und von unseren Ausnahmebehandlungsimplementierungen behandelt wird. Wie Sie sehen können, setze ich den HTTP-Status auf 404 und wir haben eine Fehlerseite dafür definiert, sodass unsere Anwendung die Fehlerseite für diesen Ausnahmetyp verwenden sollte, wenn wir keine Ansicht zurückgeben. Wir können auch den Statuscode in unserer Ausnahmehandlermethode überschreiben, denken Sie an ihn als Standard-HTTP-Statuscode, wenn unsere Ausnahmehandlermethode keine Ansichtsseite als Antwort zurückgibt.

Ausnahmehandlungscontrollerklasse für Spring MVC

Werfen wir einen Blick auf unsere Controllerklasse, in der wir verschiedene Arten von Ausnahmen auslösen werden.

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{
		//absichtlich verschiedene Arten von Ausnahmen auslösen
		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;
	}	
}

Hinweis: Für den EmployeeNotFoundException-Handler gebe ich ein ModelAndView zurück, und daher wird der HTTP-Statuscode als OK (200) gesendet. Wenn void zurückgegeben würde, wäre der HTTP-Statuscode 404. Wir werden diese Art der Implementierung in unserem globalen Ausnahmehandler betrachten. Da ich nur EmployeeNotFoundException im Controller behandele, werden alle anderen Ausnahmen, die vom Controller ausgelöst werden, vom globalen Ausnahmehandler behandelt.

@ControllerAdvice und @ExceptionHandler

Hier ist unsere Klasse für den globalen Ausnahmehandler-Controller. Beachten Sie, dass die Klasse mit der Annotation @ControllerAdvice versehen ist. Auch die Methoden sind mit der Annotation @ExceptionHandler versehen.

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");
		//Rückgabe des Fehlercodes 404
	}
}

Beachten Sie, dass für SQLException die response-Seite database_error.jsp mit dem HTTP-Statuscode 200 zurückgegeben wird. Für IOException geben wir void mit dem Statuscode 404 zurück, sodass in diesem Fall unsere error-page verwendet wird. Wie Sie sehen können, behandele ich hier keine anderen Arten von Ausnahmen. Diesen Teil habe ich der Implementierung von HandlerExceptionResolver überlassen.

HandlerExceptionResolver

Wir erweitern einfach SimpleMappingExceptionResolver und überschreiben eine der Methoden. Aber wir können auch die wichtigste Methode resolveException überschreiben, um Protokollierung und das Senden verschiedener Arten von Ansichtsseiten zu ermöglichen. Das ist jedoch dasselbe wie die Verwendung der Implementierung von ControllerAdvice, daher lasse ich es. Wir werden es verwenden, um die Ansichtsseite für alle anderen von uns nicht behandelten Ausnahmen zu konfigurieren, indem wir mit einer generischen Fehlerseite antworten.

Spring Exception Handling-Konfigurationsdatei

Unsere Spring Bean-Konfigurationsdatei sieht wie folgt aus. Spring.xml-Code:

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

Beachten Sie die für die Unterstützung von JSON konfigurierten Beans in unserer Webanwendung. Der einzige Teil, der die Ausnahmebehandlung betrifft, ist die Bean-Definition simpleMappingExceptionResolver, in der wir generic_error.jsp als Ansichtsseite für die Exception-Klasse definieren. Dadurch wird sichergestellt, dass eine nicht behandelte Ausnahme durch unsere Anwendung nicht dazu führt, dass die vom Server generierte Fehlerseite als Antwort gesendet wird.

Spring MVC Exception Handling JSP View Pages

Es ist Zeit, den letzten Teil unserer Anwendung zu betrachten, unsere Ansichtsseiten, die in unserer Anwendung verwendet werden sollen. home.jsp-Code:

<%@ 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 wird verwendet, um mit gültigen Daten zu antworten, d. h., wenn wir die ID 10 im Client-Anforderung erhalten. 404.jsp-Code:

<%@ 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 wird zur Generierung der Ansicht für den HTTP-Statuscode 404 verwendet. Für unsere Implementierung sollte dies die Antwort sein, wenn wir die ID 3 in der Client-Anforderung erhalten. error.jsp-Code:

<%@ 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 wird verwendet, wenn unsere Controller-Klasse eine Anforderungsmethodenbehandlermethode die EmployeeNotFoundException auslöst. Wir sollten diese Seite als Antwort erhalten, wenn der ID-Wert in der Client-Anforderung 1 ist. database_error.jsp-Code:

<%@ 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 wird verwendet, wenn unsere Anwendung eine SQLException auslöst, wie in der GlobalExceptionHandler-Klasse konfiguriert. Wir sollten diese Seite als Antwort erhalten, wenn der ID-Wert in der Client-Anforderung 2 ist. generic_error.jsp-Code:

<%@ 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>

Dies sollte die Seite als Antwort sein, wenn eine Ausnahme auftritt, die nicht von unserem Anwendungscode behandelt wird und der simpleMappingExceptionResolver-Bean sich darum kümmert. Wir sollten diese Seite als Antwort erhalten, wenn der id-Wert im Client-Anforderung irgendetwas außer 1, 2, 3 oder 10 ist.

Ausführen der Spring MVC Exception Handling-Anwendung

Einfach die Anwendung im Servlet-Container bereitstellen, den du verwendest. Ich benutze Apache Tomcat 7 für dieses Beispiel. Die folgenden Bilder zeigen die verschiedenen Antwortseiten, die von unserer Anwendung basierend auf dem ID-Wert zurückgegeben werden. ID=10, gültige Antwort. ID=1, Controller-basierter Ausnahmebehandler verwendet ID=2, globaler Ausnahmebehandler verwendet mit Ansicht als Antwort ID=3, 404 Fehlerseite verwendet ID=4, simpleMappingExceptionResolver für Antwortansicht verwendet Wie du sehen kannst, haben wir in allen Fällen die erwartete Antwort erhalten.

Feder Ausnahmebehandler JSON-Antwort

Wir sind fast mit unserem Tutorial fertig, außer dem letzten Teil, in dem ich erkläre, wie man JSON-Antworten aus den Ausnahmebehandlermethoden sendet. Unsere Anwendung verfügt über alle JSON-Abhängigkeiten, und jsonMessageConverter ist konfiguriert. Alles, was wir tun müssen, ist, die Ausnahmebehandlermethode zu implementieren. Zur Vereinfachung werde ich die Methode handleEmployeeNotFoundException() des EmployeeControllers neu schreiben, um eine JSON-Antwort zurückzugeben. Aktualisieren Sie einfach die Ausnahmebehandlermethode des EmployeeControllers mit dem unten stehenden Code und deployen Sie die Anwendung erneut.

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

Jetzt erhalten wir beim Verwenden von id als 1 in der Clientanfrage folgende JSON-Antwort, wie im Bild unten gezeigt. Das ist alles für die Feder-Ausnahmebehandlung und die Feder-MVC-Ausnahmebehandlung. Bitte laden Sie die Anwendung von der unten stehenden URL herunter und spielen Sie damit herum, um mehr zu erfahren.

Spring-Ausnahmebehandlungsprojekt herunterladen

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