עיבוד חריגות ב- Spring MVC חשוב מאוד כדי לוודא שאין שגיאות שרת מתקבלות על ידי הלקוח. היום נתעקב אחרי כיצד לטפל בחריגות ב-Spring באמצעות @ExceptionHandler, @ControllerAdvice ו-HandlerExceptionResolver. כל יישום אינטרנט מחייב עיצוב טוב של טיפול בחריגות מכיוון שאנו לא רוצים לספק עמוד שנוצר על ידי הקונטיינר כאשר חריגה לא מטופלת נזרקת על ידי היישום שלנו.
עיבוד חריגות ב-Spring
לקביעת גישת טיפול בחריגות מוגדרת היטב היא יתרון גדול לכל מסגרת יישום אינטרנט, ועם זאת, מסגרת Spring MVC מספקת יכולות יציבות בניהול חריגות ושגיאות ביישומים האינטרנטיים שלנו. מסגרת Spring MVC מספקת את הדרכים הבאות לעזור לנו להשיג טיפול חזק בחריגות.
- מבוסס קונטרולר – אנו יכולים להגדיר שיטות לטיפול בחריגות במחלקות הקונטרולר שלנו. כל שנדרש הוא להוסיף את האנוטציה
@ExceptionHandler
לשיטות אלו. האנוטציה מקבלת את מחלקת החריגה כארגומנט. אז אם הגדרנו כזו אחת עבור מחלקת החריגה, אז כל החריגות שיושבו על ידי שיטת הטיפול בבקשות שלנו ייטופלו. שיטות אלו לטיפול בחריגות הן דומות לשאר שיטות לטיפול בבקשות ואנו יכולים לבנות תגובת שגיאה ולהגיב עם דף שגיאה שונה. ניתן גם לשלוח תגובת שגיאה בפורמט JSON, אותו נבחן מאוחר יותר בדוגמה שלנו. אם קיימות מספר של שיטות לטיפול בחריגות מוגדרות, אז השיטה המטפלת הקרובה ביותר למחלקת החריגה תשמש. לדוגמה, אם יש לנו שתי שיטות מטפלות מוגדרות עבור IOException ו- Exception ושיטת הטיפול בבקשות שלנו מזיזה IOException, אז שיטת הטיפול ב- IOException תתבצע. - מטפל גלובלי בחריגות – טיפול בחריגות הוא עניין חוצה תחום, ועליו להתבצע עבור כל נקודת החיתוך ביישום שלנו. כבר חקרנו את Spring AOP ולכן Spring מספק את האנוטציה
@ControllerAdvice
שאנו יכולים להשתמש בה עם כל מחלקה כדי להגדיר את מטפל החריגות הגלובלי שלנו. שיטות המטפלות במדריך הקונטרולר הגלובלי זהות לשיטות המטפלות בחריגות מבוססות קונטרולר ומשמשות כאשר מחלקת הקונטרולר אינה מסוגלת לטפל בחריגה. - HandlerExceptionResolver – לשגיאות גנריות, לעיתים רבות אנו מספקים דפים סטטיים. מסגרת Spring מספקת ממשק
HandlerExceptionResolver
שאנו יכולים ליישם כדי ליצור מטפל של חריגות גלובלי. הסיבה לפעולה נוספת זו להגדרת מטפל גלובלי בחריגות היא שמסגרת Spring מספקת גם קבצי יישום ברירת מחדל שאנו יכולים להגדיר בקובץ התצורה של חץ הזרימה של הבורג.SimpleMappingExceptionResolver
הוא המחלקה הממומשת כברירת המחדל, היא מאפשרת לנו להגדיר exceptionMappings שבהם אנו יכולים לציין איזו משאב להשתמש באיזו חריגה מסוימת. אנו יכולים גם לדרוס אותו כדי ליצור מטפל גלובלי משלנו עם השינויים המיוחדים של היישום שלנו, כגון רישום של הודעות חריגה.
בואו ניצור פרויקט Spring MVC בו נבדוק את המימוש של שיטות טיפול בחריגות ובשגיאות של הבקר. נכתוב גם את שיטת הטיפול בחריגות המבוססת על AOP ואת הפתרון המבוסס על מטפל בחריגות. ניצור גם שיטת מטפל בחריגות שתחזיר תגובת JSON. אם אתה חדש ב-JSON ב-Spring, קרא את מדריך ה-JSON Restful של Spring. הפרויקט הסופי שלנו יראה כמו התמונה למטה, ונבחן את כל רכיבי היישום שלנו אחד ליד השני.
זרימת טיפול בחריגות בספרינג תלויות ב־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, דף זה יועבר כתגובה. התצורה הזו משמשת על ידי הקונטיינר כאשר אפליקציית האינטרנט שלנו מזריקה קוד שגיאת 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;
}
}
since (אחריות) we (נחזיר) will be returning (מענה JSON) JSON (גם) response too, (בואו ניצור) let’s create (פול) a java bean with (פרטי יוצאי דופן) exception details (שישלחו) that will be sent (כמענה).
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 Exception Handling – Custom Exception Class
Let’s create (מחלקת יוצאי דופן) a custom exception class (שישמש) to be used (על ידי) by our application.
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);
}
}
Notice that (אנו יכולים להשתמש) we can use @ResponseStatus
(הערה) annotation with (מחלקות יוצאי דופן) exception classes (כדי להגדיר) to define (את הקוד של ה-HTTP) the HTTP code (שישלח) that will be sent (על ידי) by our application (כאשר) when (סוג זה של) this type of exception (מיוצא) is thrown (על ידי) by our application (ונתפס) and handled (על ידי) by our exception handling implementations. (כפי שאתה יכול לראות) As you can see (אני מגדיר) that I am setting (סטטוס HTTP) HTTP status (כ-404) as 404 (ולנו יש) and we have (הגדירו) an error-page defined (עבור זאת, לכן) for this, so (היישום שלנו) our application (צריך להשתמש) should use (בעמוד שגיאה) the error page (עבור סוג זה של) for this type of exception (אם אנו לא) if we are not (מחזירים) returning (שום דעת) any view. (ניתן גם) We can also (לדרוס) override (את קוד הסטטוס) the status code (בשיטת מטפל היוצאת) in our exception handler method, (תחשבו בזה) think of it (כקוד HTTP) as default HTTP status code (ברגע ששיטת המטפל) when our exception handler method (לא מחזירה) is not returning (שום עמוד תצוגה) any view page (כתשובה).
Spring MVC Exception Handling Controller Class Exception Handler
Let’s look (בואו נסתכל) at our controller class (במחלקת הבקר) where we will throw (בה נזרוק) different type (סוגים שונים של) of exceptions.
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). אם היה מחזיר ריק, אז קוד מצב 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, אנו מחזירים ריק עם קוד סטטוס כ-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 באפליקציית האינטרנט שלנו. החלק היחיד הקשור לטיפול בחריגות הוא הגדרת ה-pimpleMappingExceptionResolver bean, בו אנו מגדירים את generic_error.jsp כדף התצוגה למחלקת החריגה. זהו מבטיח שכל חריגה שאינה נתפסת על ידי האפליקציה שלנו לא תוביל לשליחת דף שגיאה הנוצר על ידי השרת כתשובה.
עמודי תצוגה ב-JSP לטיפול בחריגות ב-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 משמש ליצירת תצוגה עבור קוד סטטוס 404 של HTTP, עבור המימוש שלנו זה אמור להיות התגובה כאשר נקבל 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 משמש כאשר מתבצעת יצירת דף שגיאה, בהעברת מחלקת טיפול בבקשה במחלקתנו מזהה עובד שאינו קיים. אנו אמורים לקבל דף זה כתגובה כאשר ערך 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 טופלת בזה. אנחנו צריכים לקבל את הדף הזה כתגובה כאשר ערך הזיהוי בבקשת הלקוח הוא כלום אחר מ-1, 2, 3 או 10.
מפעיל את היישום לטיפול בחריגות ב- Spring MVC
רק הפעל את היישום בתוך תכונת הסרבלט שבה אתה משתמש, אני משתמש ב-Apache Tomcat 7 לדוגמה זו. התמונות למטה מציגות את הדפים השונים של תגובה שמחזיר היישום שלנו על פי ערך ה- id. ID=10, תגובה חוקית. ID=1, משתמש בטפסיק המבוסס על בקר יוצר חריגה
ID=2, משתמש בטפסיק המבוסס על טפסיק גלובלי עם צפיה כתגובה
ID=3, נעשה שימוש בדף שגיאת 404
ID=4, משתמש בטפסיק simpleMappingExceptionResolver לתצוגת תגובה
כפי שניתן לראות, קיבלנו את התגובה הצפויה בכל המקרים.
תגובת יוצא דופן של מטפל בחריגות בפורמט JSON
כמעט סיימנו את המדריך שלנו, חוץ מהחלק האחרון בו אני אסביר איך לשלוח תגובה בפורמט JSON ממתפס בחריגות. האפליקציה שלנו מכילה את כל התלות ב-JSON והממיר jsonMessageConverter מוגדר, כל שנשאר לעשות הוא לממש את שיטת מתפס החריגות. לצורך פשטות, אני אכתוב מחדש את שיטת ההתמודדות עם חריגת חיפוש העובד ב- 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 הבאה כפי שמוצג בתמונה למטה. זהו הכול לנושא התמודדות עם חריגות בספרינג ותמיכה בתקלות ב- MVC של ספרינג, אנא הורידו את האפליקציה מה-URL למטה ושחקו איתה כדי ללמוד עוד.