Global exception handling in SpringBoot

Keywords: Java Android Spring JSON

Analysis of exception handling

How to handle exceptions

Problem introduction

  • There are two ways to deal with exceptions in code, one is throws throw directly, the other is try. catch.
  • In a java project, there may be human logic exceptions, details of exceptions, or guarantees that the program will continue to execute downward when exceptions occur. The second approach is used.
  • However, every exception in the code is captured, which makes the code redundant and unmaintainable.
    Solutions
  • Define a global exception handling class to return uniform exception information.
  • Processing logic is to determine whether there will be an exception, and then to carry out subsequent specific business.

Business example

In order to realize the logic of global exception handling, this paper only mentions simple business.

A company department needs to increase its employees. Processing procedures are as follows: 1. Query the employees according to their numbers, 2. Judge whether the employees have information, that is, whether it is not empty, 3. If there is information, it means that it already exists, no need to add, if not, add directly.

The code is as follows:

public class MyService {
    // Injection of dao layer
    @Autowired
    EmployeeecMapper employeeecMapper;

    /**
     * Adding Employee Information
     * @param employee Employee object
     * @return Number of rows affected
     */
    public int add(Employee employee) {
        // Query employee objects based on id
        Employeeec emp = employeeecMapper.selectByPrimaryKey(employee.getId());
        // Determine if the employee already exists
        if (emp != null){
            // Has, throws an exception, exception information for the existing employee
            throw new RuntimeException("Exception code: 1201, error message: the employee already exists");
        }
        // No, insert the employee
        return employeeecMapper.insert(emp);
    }
}

Exception handling process

There are runtime and business logic anomalies in business. The former is difficult to detect when it is not running, and the latter can be defined when it is running through business. Therefore, anomalies can be divided into unpredictable and knowable anomalies. The process is as follows:

  1. Customize the global exception class and use @Controller Advice to enhance the controller
  2. Customize error code and error information. The two exceptions will eventually be expressed in a unified information format, error code + error information.
  3. For predictable exceptions, the programmer actively throws them in the code and captures them by Spring MVC.
  4. Unpredictable exceptions are usually due to bug s in the system or some external factors (such as network fluctuations, server downtime, etc.). The type of exception is Runtime Exception (runtime exceptions).

Knowable exception

Define exception information class, variable is error code and error information, when capturing custom exception, return the object directly

Agnostic anomaly

Define a map, store common exceptions in it, and define error codes. For other unusual exceptions, which are not found in map, the same exception object can be returned.

Exception handling code flow

Knowable exception

1. Define the interface between printing exception information and returning result

public interface ResultCode {
    // Is the operation successful?
    boolean success();

    // Operational Result Code
    long code();

    // Prompt information
    String message();
}
public interface Response {
    public static final boolean SUCCESS = true;
    public static final int SUCCESS_CODE = 10000;
}

2. Define the enumeration class for printing exception information and the return result class

@ToString
public enum  CommonCode implements ResultCode {
    NO_PAGE(false,404,"No information"),
    FAIL(false,500,"Operation failed!"),
    SUCCESS(true,200,"Successful operation!");

    // Result information
    boolean success;
    long code;
    String message;
    
    // Parametric structure
    CommonCode(boolean success, long code, String message) {
        this.success = success;
        this.code = code;
        this.message = message;
    }

    @Override
    public boolean success() {
        return true;
    }

    @Override
    public long code() {
        return code;
    }

    @Override
    public String message() {
        return message;
    }
}
@Data
@ToString
public class ResponseResult implements Response {

    boolean success = SUCCESS;

    long code = SUCCESS_CODE;

    String message;

    public ResponseResult(ResultCode resultCode){
        this.success = resultCode.success();
        this.code = resultCode.code();
        this.message = resultCode.message();
    }
}

3. Defining error exception classes

public class CustomException extends RuntimeException{

    @Autowired
    ResultCode resultCode;
    
    // Parametric structure
    public CustomException(ResultCode resultCode){
        this.resultCode = resultCode;
    }
    
    // getter
    public ResultCode getResultCode(){
        return resultCode;
    }
}

4. Define exception throw classes

public class ExceptionCast {

    // Static method
    public static void cast(ResultCode resultCode){
        throw new CustomException(resultCode);
    }
}

5. Define exception capture class, use Controller Advice Controller enhanced annotations, and add Exception Handler annotations on the method of capturing CustomException exception, then all exceptions of this class can be captured and json data returned.

@ControllerAdvice 
public class ExceptionCatch {

    /**
     * Capture CustomException class exceptions
     * @param customException
     * @return Result information, json data
     */
    @ExceptionHandler(CustomException.class)
    @ResponseBody
    public ResponseResult customException(CustomException customException){
        ResultCode resultCode = customException.getResultCode();
        return new ResponseResult(resultCode);
    }
}

6. Throw an exception in the business

public class MyService {

    @Autowired
    EmployeeecMapper employeeecMapper;

    public int add(Employee employee) {
        Employeeec emp = employeeecMapper.selectByPrimaryKey(employee.getId());
        if (emp != null){
            ExceptionCast.cast(CommonCode.FAIL);
        }
        return employeeecMapper.insert(emp);
    }
}

Unknown exception handling

1. Similar to known exceptions, first add error codes to the CommonCode class, such as

UNAUTHORISE(false,510,"No authority"),

2. Adding the capture method of unknown exception to the exception capture class. In this method, a read-only map is defined to store the mapping of error codes of exception types. The elements that are not in the map are uniformly defined by error code 999.

UNKNOWNERROR(false,999,"Unknown anomaly"),
@ControllerAdvice
public class ExceptionCatch {

    // Define map and store common error information. This type of map is not modifiable
    private static ImmutableMap<Class<? extends Throwable>,ResultCode> EXCEPTIONS;
    // Building Immutable Map
    protected static ImmutableMap.Builder<Class<? extends Throwable>,ResultCode> builder = ImmutableMap.builder();

    @ExceptionHandler(CustomException.class)
    @ResponseBody
    public ResponseResult customException(CustomException customException){
        ResultCode resultCode = customException.getResultCode();
        return new ResponseResult(resultCode);
    }

    /**
     * Capture non-custom class exceptions
     * @param exception
     * @return
     */
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ResponseResult exception(Exception exception){
        // Log
        LOGGER.error("catch exception ==> ",exception.getMessage());
        if (EXCEPTIONS == null){
            EXCEPTIONS = builder.build();
        }
        ResultCode resultCode = EXCEPTIONS.get(exception.getClass());
        if (resultCode != null){
            return new ResponseResult(resultCode);
        }else {
            return new ResponseResult(CommonCode.UNKNOWNERROR);
        }
    }

    static {
        builder.put(HttpMessageNotReadableException.class, CommonCode.INVALID_PARAM);
    }
}

Readers sharing

Here we recommend a Wechat Public Number, where every day there will be technology dry goods, technology trends, career, industry hotspots, career interesting and so on, all about the content of programmers to share. There are a large number of Java architecture, mobile Internet architecture related source video, interview materials, e-books until April 28 Free distribution. I think the resources are good. If you need to, scan the two-dimensional code below and pay attention to the wx public number for free __


Resource Base__

Java Architecture Information
Java source code parsing, to a variety of frameworks to learn, and then to the actual project, including but not limited to: Spring, Mybatis and other source code, Java advanced, Java architect, virtual machine, performance optimization, concurrent programming, data structure and algorithm.

Java Architecture Video Data

Java Architecture Video Data

java architecture interview materials

Mobile Internet Architecture Information
Android Advancement, Android Architecture, APP Development, NDK Module Development, Small Program Development, Wechat Development.

Android Architecture Information

Posted by neuromancer on Tue, 23 Apr 2019 12:00:35 -0700