Detailed explanation of SpringMVC’s three exception handling methods

Table of contents

1. What is an exception?

2. Why global exception handling is needed

3. SpringMVC exception classification

4. Exception handling ideas

5. Examples of three exception handling methods

① Configure SimpleMappingExceptionResolver processor

② Implement HandlerExceptionResolver interface

③ Use @ControllerAdvice+@ExceptionHandler to implement global exceptions

6. Response encapsulation class


1. What is an exception?

        See the word Ruyi, which is the error reported during encoding. Exceptions are mainly divided into two types: compile-time exception and run-time exception RuntimeException. The former will report red if it does not comply with the standard code during coding, which is an error that can be seen by the naked eye. The latter mainly reduces the occurrence of runtime exceptions through standardized code development and testing.

        In Spring MVC, exception handling refers to a mechanism to capture, handle and respond to exceptions that may occur during request processing. It can decouple all types of exception handling from each processing process, which not only ensures that the functions of the relevant processing processes are relatively single, but also realizes the unified processing and maintenance of exception information.

2. Why global exception handling is needed

        During development, whether it is the dao layer, service layer or controller layer, exceptions may be thrown. Using global exception handling has the following advantages:

  1. Unified exception handling logic: Through global exception handling, the exception handling logic in the application can be concentrated in one place, avoiding writing the same or similar exception handling code in each specific business code. This can improve the maintainability of the code, reduce code redundancy, and make the code clearer and easier to understand.

  2. Improve the fault tolerance of the system: Global exception handling can capture unhandled exceptions in the application and avoid the transmission of exceptions causing the application to crash or unknown errors. By properly handling exceptions, the system can remain stable and continue to run normally when exceptions occur, improving the system's fault tolerance and robustness.

  3. Unified exception return format: Global exception handling can define a unified exception return format and return exception information to the client or user in a consistent manner. This can provide more friendly and consistent error prompts, improve user experience, and facilitate the client to handle and display exceptions.

  4. Security and handling of security vulnerabilities: Global exception handling can capture and handle security vulnerabilities or anomalies in applications, such as unauthorized access, illegal operations, etc. Through appropriate exception handling, some potential security problems can be prevented and the security and protection capabilities of the system can be improved.

  5. Exception logging and monitoring: Global exception handling can uniformly record exception information in the application, including exception type, occurrence location, request parameters, etc., to facilitate subsequent exception analysis, troubleshooting, and system monitoring. By effectively recording and monitoring exceptions, potential problems can be discovered and solved in a timely manner, and the reliability and stability of the system can be improved.

        In general, global exception handling can improve the maintainability, fault tolerance and security of the system, provide a better user experience, and facilitate system monitoring and troubleshooting. When developing applications, rational use of the global exception handling mechanism can effectively handle exceptions and ensure the stability of the application.

3. SpringMVC exception classification

In Spring MVC, exceptions can be divided into two categories: application exceptions and system exceptions .

  1. Application Exceptions: Application exceptions are exceptions caused by the application's own business logic and are usually expected exceptions. These exceptions can be classified according to specific business requirements, such as user input validation failure, resource not found, insufficient permissions, etc. Application exceptions can be represented by custom exception classes, and custom exception information can be added to better understand the cause of the exception and handle the exception.

  2. System exception: System exception refers to exceptions caused by the system operating environment or external factors, usually unexpected exceptions. These exceptions may include database connection failures, network connection abnormalities, internal server errors, etc. System exceptions cannot be solved by the application's own logic and need to be captured and handled through appropriate exception handling mechanisms.

        In Spring MVC, application exceptions and system exceptions can be distinguished and handled through reasonable exception classification and handling mechanisms. Typically, application exceptions can @ExceptionHandlerbe handled through annotations or custom exception handlers, while system exceptions can be HandlerExceptionResolvercaught and handled through global exception handlers (implementations of interfaces). This enables fine handling of different types of exceptions and improves system reliability and user experience.

4. Exception handling ideas

        Exceptions in the system's dao, service, and controller are all thrown upward through throws Exception. Finally, the springmvc front-end controller hands it over to the exception handler for exception handling. Springmvc provides a global exception handler ( a system has only one exception handler ) for unified exception handling.

  1. Determine the scope and level of exception handling: First, you need to determine the scope of exception handling, that is, at which level exception handling should be placed. In Spring MVC, exception handling can occur in the Controller layer, Service layer or DAO layer, depending on your application architecture and requirements. Generally speaking, application exceptions can be handled in the Controller layer, while system exceptions can be handled in the global exception handler.

  2. Define exception classes: Depending on your application needs, you can define custom exception classes to represent different types of exceptions. Custom exception classes can inherit from Exceptionor RuntimeExceptionand add appropriate properties and methods to better describe exception information. For example, you can define an ValidationExceptionexception to indicate a user input validation failure.

  3. Exception catching and handling: In the code, use try-catchblocks to catch exceptions that may occur and catchhandle them accordingly in the blocks. For application exceptions, you can use @ExceptionHandlerannotations in methods in the Controller layer to catch and handle specific types of exceptions. For system exceptions, you can implement the interface in the global exception handler HandlerExceptionResolverand resolveExceptionperform exception handling logic in the method.

  4. Exception handling logic: In exception handling logic, you can take appropriate handling measures based on specific exception types. For example, for application exceptions, you can return a specific error page or error message to the user, or record exception logs for subsequent analysis. For system exceptions, you can return a general error page or error message, or perform some system-level exception handling operations.

  5. Exception information delivery and display: During exception handling, you can pass exception information to the front-end page or other components for display. Exception information can be conveyed through ModelAndViewobjects, @ResponseBodyannotations, or other means. When displaying exception information, it can be formatted according to specific needs so that users can clearly understand the cause of the exception.

  6. Unit testing and exception simulation: In order to verify the correctness of exception handling, it is recommended to write corresponding unit tests and simulate various abnormal situations. Through unit testing, you can ensure the correctness and stability of exception handling logic.

        In summary, the idea of ​​exception handling is to classify exception types, determine the scope and level of exception handling, define custom exception classes, capture and handle exceptions, and display exception handling logic and exception information according to specific situations. Through reasonable exception handling, the reliability of the system can be improved.

5. Examples of three exception handling methods

Before demonstrating the following, how to report an error without exception handling:

1. Manually write an error message in any method or controller

2. Run the path

This is an error message without any exception handling. It would certainly be unsightly to echo this interface to the customer, so please continue reading.

① Configure SimpleMappingExceptionResolver processor

        SpringMVC comes with an exception handler called SimpleMappingExceptionResolver, which implements the HandlerExceptionResolver interface. All global exception handlers need to implement this interface.

1. spring-mvc.xml:

    <!-- springmvc提供的简单异常处理器 -->
    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <!-- 定义默认的异常处理页面 -->
        <property name="defaultErrorView" value="error"/>
        <!-- 定义异常处理页面用来获取异常信息的变量名,也可不定义,默认名为exception -->
        <property name="exceptionAttribute" value="xw"/>
        <!-- 定义需要特殊处理的异常,这是重要点 -->
        <property name="exceptionMappings">
            <props>
                <prop key="java.lang.RuntimeException">error</prop>
            </props>
            <!-- 还可以定义其他的自定义异常 -->
        </property>
    </bean>

Note: The page jump is taken over by SpringMVC, so the default exception handling page defined here should be configured as a logical view name.

2. Create error.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%--错误信息--%>
${xw}<br>
<img src="static/imgs/R.jpg">
</body>
</html>

The interface after configuring exception handling:

② Implement HandlerExceptionResolver interface

1. Create a custom exception class named GlobalException, which inherits from the RuntimeException class.

        In Java, custom exception classes usually need to inherit from the Exception class or its subclasses. RuntimeException is a subclass of Exception, which represents abnormal situations that may occur during program execution. By inheriting the RuntimeException class, GlobalException can be treated as an unchecked exception, that is, it does not need to be explicitly declared or caught in the method signature.

        The GlobalException class provides multiple constructors for creating different types of exception objects. Each constructor calls the corresponding constructor of the parent class RuntimeException in order to pass the exception information to the parent class for processing.

package com.ycxw.exception;

public class GlobalException extends RuntimeException {
    public GlobalException() {
    }

    public GlobalException(String message) {
        super(message);
    }

    public GlobalException(String message, Throwable cause) {
        super(message, cause);
    }

    public GlobalException(Throwable cause) {
        super(cause);
    }

    public GlobalException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
}

        By providing different constructors, the GlobalException class can create exception objects under different circumstances and pass relevant exception information and reasons.

        The advantage of custom exception classes is that specific types of exceptions can be defined according to the needs of the application to better describe and handle different exception situations. In the code, when an exception occurs in a method or operation, a GlobalException object can be thrown, and corresponding exception handling logic can be performed on the upper layer.

2. Define a class named GlobalExceptionHandler and implement the HandlerExceptionResolver interface. At the same time, use the @Component annotation to mark the class as a Spring component for automatic scanning and registration in the application.

@Component
public class GlobalExceptionHandler implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest,
                                         HttpServletResponse httpServletResponse,
                                         Object o, Exception e) {
        ModelAndView mv = new ModelAndView();
        mv.setViewName("error");
        if (e instanceof GlobalException){
            GlobalException globalException = (GlobalException) e;
            mv.addObject("xw",globalException.getMessage());
            mv.addObject("msg","全局异常....");
        }else if (e instanceof RuntimeException){
            RuntimeException runtimeException = (RuntimeException) e;
            mv.addObject("xw",runtimeException.getMessage());
            mv.addObject("msg","运行时异常....");
        }
        return mv;
    }
}
  1. This code defines a class named GlobalExceptionHandler and implements the HandlerExceptionResolver interface. At the same time, use the @Component annotation to mark the class as a Spring component for automatic scanning and registration in the application.
  2. The HandlerExceptionResolver interface is an interface provided by the Spring MVC framework for handling exceptions. By implementing this interface, you can customize the global exception handler to capture and handle exceptions generated during request processing.
  3. In the code, the resolveException method is a method of the HandlerExceptionResolver interface and is used to handle exceptions. It accepts parameters such as HttpServletRequest, HttpServletResponse, Object and Exception, and returns a ModelAndView object.
  4. Inside the method, an empty ModelAndView object mv is first created. Then, the view's name is set to "error", which means that when an exception occurs, the view named "error" will be rendered.
  5. Next, use instanceof to determine the type of exception and perform different processing logic. If the exception is of type GlobalException, add the exception information and the custom "Global Exception...." message to the mv object. If the exception is of type RuntimeException, add the exception information and the "Runtime Exception...." message to the mv object.
  6. Finally, the mv object is returned so that the framework can render it and return it to the client.

        By implementing the HandlerExceptionResolver interface and defining the resolveException method, you can customize the global exception handling logic and handle exceptions uniformly in the application. This provides a better user experience and reduces duplicate exception handling code in your code.

Use the previous error message:

3. Throw a global error message

③ Use @ControllerAdvice+@ExceptionHandler to implement global exceptions

        A class named GlobalExceptionResolver is defined and marked as a global exception handler using the @ControllerAdvice annotation.

package com.ycxw.exception;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.HashMap;
import java.util.Map;

@ControllerAdvice
public class GlobalExceptionResolver {

// 返回错误json数据
    @ResponseBody
    @ExceptionHandler
    public Map handler(Exception e){
        Map map = new HashMap();
        if (e instanceof GlobalException){
            GlobalException globalException = (GlobalException) e;
            map.put("xw",globalException.getMessage());
            map.put("msg","全局异常....");
        }else if (e instanceof RuntimeException){
            RuntimeException runtimeException = (RuntimeException) e;
            map.put("xw",runtimeException.getMessage());
            map.put("msg","运行时异常....");
        }else {
            map.put("xw",e.getMessage());
            map.put("msg","其它异常....");
        }
        return map;
    }
}
  1. @ControllerAdvice is an annotation provided by the Spring MVC framework and is used to define global controller enhancements. By using the @ControllerAdvice annotation, this class can be applied to all controllers and provide unified exception handling logic.
  2. In the code, use the @ResponseBody annotation to mark the handler method as a method that returns JSON data. The @ExceptionHandler annotation is used to specify the exception type handled by this method.
  3. The handler method accepts a parameter e of Exception type and returns a Map object. Within the method, different processing logic is performed based on the type of exception.
  4. If the exception is of type GlobalException, add the exception information and the custom "Global Exception...." message to the map object. If the exception is of type RuntimeException, add the exception information and the "Runtime Exception...." message to the map object. If the exception does not belong to the above two types, add the exception information and "Other Exception...." message to the map object.
  5. Finally, the map object is returned to the client as JSON data.

        By using the @ControllerAdvice annotation and @ExceptionHandler annotation, you can customize the global exception handling logic and return the exception information to the client in JSON format. This provides better error handling and exception information presentation.

6. Response encapsulation class

        The function of the response encapsulation class is to uniformly encapsulate and format the response data so that it can be uniformly processed in the application and returned to the client.

  • Typically, in an application, different interfaces may return different data structures and formats. This will cause the client to write a lot of repetitive code to parse and process different response formats when processing response data, increasing the complexity of development and maintenance.
  • In order to solve this problem, you can use the response encapsulation class to uniformly encapsulate the response data. The response encapsulation class is usually a custom class that contains response-related information, such as status codes, messages, data, etc.
  • By encapsulating the response data into a fixed data structure, the format of the response data returned by all interfaces can be consistent. In this way, the client only needs to process the unified response data structure, and does not need to pay attention to the specific return formats of different interfaces.
  • Response encapsulation classes can also provide additional functions, such as exception handling, error code definition, multi-language support, etc. By defining unified exception handling logic in the response encapsulation class, exceptions in the application can be captured and handled, and the exception information is encapsulated into response data and returned to the client. At the same time, error codes can be defined in the response encapsulation class, and internationalization processing can be performed based on the error codes to support error prompts in multi-language environments.

        In short, the role of the response encapsulation class is to provide a unified response data format, simplify the client's processing logic, provide additional functions such as exception handling and multi-language support, and improve the maintainability and scalability of the application.

For example: 

package com.ycxw.utils;

import java.util.HashMap;

public class R extends HashMap {
    public R data(String key, Object value) {
        this.put(key, value);
        return this;
    }
 
    public static R ok(int code, String msg) {
        R r = new R();
        r.data("success", true).data("code", code).data("msg", msg);
        return r;
    }
 
    public static R error(int code, String msg) {
        R r = new R();
        r.data("success", false).data("code", code).data("msg", msg);
        return r;
    }
 
    public static R ok(int code, String msg,Object data) {
        R r = new R();
        r.data("success", true).data("code", code).data("msg", msg).data("data", data);
        return r;
    }
 
    public static R ok(int code, String msg, long count, Object data) {
        R r = new R();
        r.data("success", true).data("code", code).data("msg", msg).data("count", count).data("data", data);
        return r;
    }
}

Write a unified response method:

    // 响应封装类
    @ResponseBody
    @ExceptionHandler
    public R handler(Exception e){
        if (e instanceof GlobalException){
            GlobalException globalException = (GlobalException) e;
            return R.ok(505,"全局异常....",globalException.getMessage());
        }else if (e instanceof RuntimeException){
            RuntimeException runtimeException = (RuntimeException) e;
            return R.ok(505,"运行时异常....",runtimeException.getMessage());
        }else {
            return R.ok(505,"其他异常....",e.getMessage());
        }
    }

Run the test:

Guess you like

Origin blog.csdn.net/Justw320/article/details/132864372