Важно обращать внимание на обработку исключений в Spring MVC, чтобы убедиться, что серверные исключения не передаются клиенту. Сегодня мы рассмотрим обработку исключений в Spring с использованием @ExceptionHandler, @ControllerAdvice и HandlerExceptionResolver. Любое веб-приложение требует хорошего дизайна для обработки исключений, потому что мы не хотим предоставлять страницу, созданную контейнером, когда возникает необработанное исключение в нашем приложении.
Обработка исключений в Spring
Иметь четко определенный подход к обработке исключений – это огромный плюс для любого веб-фреймворка. Сказано это, фреймворк Spring MVC хорошо справляется с обработкой исключений и ошибок в наших веб-приложениях. Фреймворк Spring MVC предоставляет следующие способы, которые помогают нам обеспечить надежную обработку исключений.
- На основе контроллера – Мы можем определять методы обработчика исключений в наших классах контроллеров. Все, что нам нужно сделать, это аннотировать эти методы аннотацией
@ExceptionHandler
. Эта аннотация принимает класс Exception в качестве аргумента. Таким образом, если у нас определен один из них для класса Exception, то все исключения, вызванные нашим методом обработчика запросов, будут обработаны. Эти методы обработчика исключений такие же, как и другие методы обработчика запросов, и мы можем создавать ответы об ошибке и отвечать с разными страницами ошибок. Мы также можем отправлять JSON-ответ об ошибке, о чем мы рассмотрим позже в нашем примере. Если определено несколько методов обработчика исключений, то используется метод обработчика, который находится ближе к классу Exception. Например, если у нас определены два метода обработчика для IOException и Exception, и наш метод обработчика запросов вызывает IOException, то будет выполнен метод обработчика для IOException. - Глобальный обработчик исключений – Обработка исключений – это поперечно-резиновый аспект, ее следует выполнять для всех точек среза в нашем приложении. Мы уже рассмотрели Spring AOP, и поэтому Spring предоставляет аннотацию
@ControllerAdvice
, которую мы можем использовать с любым классом для определения нашего глобального обработчика исключений. Методы обработчика в Глобальном контроллере Advice такие же, как и методы обработчика исключений на основе контроллера, и используются, когда класс контроллера не способен обработать исключение. - HandlerExceptionResolver – Для общих исключений, большинство раз мы обслуживаем статические страницы. Фреймворк Spring предоставляет интерфейс
HandlerExceptionResolver
, который мы можем реализовать для создания глобального обработчика исключений. Причина этого дополнительного способа определения глобального обработчика исключений заключается в том, что фреймворк Spring также предоставляет классы реализации по умолчанию, которые мы можем определить в нашем файле конфигурации бина Spring, чтобы получить преимущества обработки исключений фреймворка Spring.SimpleMappingExceptionResolver
является классом реализации по умолчанию, который позволяет нам настраивать исключенияMappings, где мы можем указать, какой ресурс использовать для определенного исключения. Мы также можем переопределить его, чтобы создать собственный глобальный обработчик с нашими прикладными изменениями, такими как ведение журнала сообщений об исключениях.
Давайте создадим проект Spring MVC, где мы рассмотрим реализацию обработки исключений и ошибок на основе контроллера, на основе AOP и на основе обработчика исключений. Мы также напишем метод обработчика исключений, который будет возвращать JSON-ответ. Если вы новичок в JSON в Spring, прочтите Spring Restful JSON Tutorial. Наш конечный проект будет выглядеть как на изображении ниже, мы рассмотрим все компоненты нашего приложения по очереди.
Весенняя обработка исключений зависимостей Maven
Помимо стандартных зависимостей Spring MVC, нам также понадобится зависимость Jackson JSON для поддержки JSON. Наш окончательный файл pom.xml выглядит следующим образом.
<?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
Наш файл web.xml выглядит следующим образом.
<?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>
Большая часть предназначена для подключения Spring Framework к нашему веб-приложению, за исключением определенной для ошибки 404. Таким образом, когда наше приложение будет генерировать ошибку 404, эта страница будет использоваться в качестве ответа. Эта конфигурация используется контейнером, когда наше веб-приложение Spring генерирует код ошибки 404.
Обработка исключений в Spring – модельные классы
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;
}
}
Поскольку мы будем возвращать JSON-ответ, давайте создадим класс Java Bean с деталями исключения, который будет отправлен в качестве ответа.
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;
}
}
Обработка исключений в Spring – Кастомный класс исключений
Давайте создадим кастомный класс исключений для использования в нашем приложении.
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);
}
}
Обратите внимание, что мы можем использовать аннотацию @ResponseStatus
с классами исключений для определения HTTP-кода, который будет отправлен нашим приложением, когда такой тип исключения бросается нашим приложением и обрабатывается нашими реализациями обработки исключений. Как видите, я устанавливаю HTTP-статус как 404, и у нас определена страница ошибки для этого случая, поэтому наше приложение должно использовать страницу ошибки для этого типа исключения, если мы не возвращаем никакого представления. Мы также можем переопределить код статуса в нашем методе обработчика исключений, рассматривая его как код статуса HTTP по умолчанию, когда наш метод обработчика исключений не возвращает представление в качестве ответа.
Обработчик исключений класса контроллера Spring MVC
Давайте рассмотрим наш класс контроллера, где мы будем бросать разные типы исключений.
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{
//намеренно вызываем различные типы исключений
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;
}
}
Обратите внимание, что для обработчика EmployeeNotFoundException я возвращаю ModelAndView, следовательно, код состояния HTTP будет отправлен как OK (200). Если бы он возвращал void, тогда код состояния HTTP был бы отправлен как 404. Мы рассмотрим такой тип реализации в нашем глобальном обработчике исключений. Поскольку я обрабатываю только EmployeeNotFoundException в контроллере, все остальные исключения, выброшенные нашим контроллером, будут обработаны глобальным обработчиком исключений.
@ControllerAdvice и @ExceptionHandler
Вот наш глобальный обработчик исключений. Обратите внимание, что класс аннотирован аннотацией @ControllerAdvice. Также методы аннотированы аннотацией @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");
//возвращаем код ошибки 404
}
}
Обратите внимание, что для SQLException я возвращаю страницу ошибки database_error.jsp с кодом состояния HTTP 200. Для IOException мы возвращаем void с кодом состояния 404, поэтому в этом случае будет использоваться наша страница ошибки. Как видите, здесь я не обрабатываю никакие другие типы исключений, эту часть я оставил для реализации HandlerExceptionResolver.
HandlerExceptionResolver
Мы просто расширяем SimpleMappingExceptionResolver и переопределяем один из методов, но мы можем также переопределить его самый важный метод resolveException
для ведения журнала и отправки различных видов страниц. Но это то же самое, что использование реализации ControllerAdvice, поэтому я отказываюсь от этого. Мы будем использовать его для конфигурации страницы просмотра для всех остальных исключений, не обработанных нами, отвечая общей страницей ошибки.
Файл конфигурации обработки исключений Spring
Наш файл конфигурации бина Spring выглядит следующим образом. Код 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>
Обратите внимание на конфигурацию бинов для поддержки JSON в нашем веб-приложении. Единственная часть, относящаяся к обработке исключений, – это определение бина simpleMappingExceptionResolver, где мы определяем generic_error.jsp в качестве страницы просмотра для класса Exception. Это гарантирует, что любое исключение, не обработанное нашим приложением, не приведет к отправке страницы сгенерированной сервером в качестве ответа.
Страницы просмотра исключений Spring MVC
Пришло время рассмотреть последнюю часть нашего приложения, наши страницы просмотра, которые будут использоваться в нашем приложении. Код 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 используется для ответа с действительными данными, т. е. когда мы получаем id как 10 в запросе клиента. Код 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 используется для генерации представления для кода состояния http 404, для нашей реализации это должен быть ответ, когда мы получаем id как 3 в запросе клиента. Код 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 используется, когда метод обработчика запросов нашего класса контроллера вызывает исключение EmployeeNotFoundException. Мы должны получить эту страницу в ответ, когда значение id равно 1 в запросе клиента. Код 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 используется, когда наше приложение вызывает SQLException, как настроено в классе GlobalExceptionHandler. Мы должны получить эту страницу в ответ, когда значение id равно 2 в запросе клиента. Код 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>
Эта страница должна быть возвращена в качестве ответа, когда возникает любое исключение, не обрабатываемое нашим кодом приложения, и бин simpleMappingExceptionResolver заботится об этом. Мы должны получить эту страницу в ответе, когда значение id в запросе клиента отличается от 1, 2, 3 или 10.
Запуск приложения обработки исключений Spring MVC
Просто разверните приложение в контейнере сервлетов, который вы используете, я использую Apache Tomcat 7 для этого примера. Ниже показаны различные страницы ответа, возвращаемые нашим приложением в зависимости от значения id. ID=10, допустимый ответ. ID=1, используется обработчик исключений на основе контроллера
ID=2, используется глобальный обработчик исключений с представлением в качестве ответа
ID=3, используется страница ошибки 404
ID=4, используется simpleMappingExceptionResolver для представления ответа
Как видите, мы получили ожидаемый ответ во всех случаях.
Ответ обработчика исключений Spring в формате JSON
Мы почти завершили наше руководство, за исключением последнего момента, где я объясню, как отправлять ответ в формате JSON из методов обработчика исключений. В нашем приложении уже настроены все зависимости JSON, и jsonMessageConverter сконфигурирован. Все, что нам нужно сделать, это реализовать метод обработчика исключений. Для простоты я перепишу метод handleEmployeeNotFoundException() в классе EmployeeController для возврата ответа в формате JSON. Просто обновите метод обработчика исключений в EmployeeController кодом ниже и повторно разверните приложение.
@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;
}
Теперь, когда мы используем id равный 1 в запросе клиента, мы получаем следующий ответ в формате JSON, как показано на изображении ниже. Это все, что касается обработки исключений в Spring и обработки исключений Spring MVC. Пожалуйста, скачайте приложение по следующему URL и экспериментируйте с ним, чтобы узнать больше.