I heard wechat search “Java fish boy” will change strong oh!

This article is in the JavaStarter, which has my complete Java series, study or interview can see oh

(I) Overview

Exception handling is one of the most important aspects of a system, and when a project becomes very large, exception handling and logging systems allow you to quickly locate problems. For the user or the interface caller, elegant exception handling allows the caller to quickly know where the problem is. This article shows you how to handle exceptions gracefully.

(2) Use a generic return body

We want all errors to be returned to the client as Json, so we take the last written generic return body and create a new class CommonResult to record the return body.

@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult {
    private int code;
    private String message;
    private Object data;
}
Copy the code

Create a new enumeration class ResponseCode that integrates code and Message.

public enum ResponseCode {

    // System module
    SUCCESS(0."Operation successful"),
    ERROR(1."Operation failed"),
    SERVER_ERROR(500."Server exception"),

    // Generic module 1xxxx
    ILLEGAL_ARGUMENT(10000."Parameter is not valid"),
    REPETITIVE_OPERATION(10001."Do not repeat operation"),
    ACCESS_LIMIT(10002."Too frequent. Please try again later."),
    MAIL_SEND_SUCCESS(10003."Email sent successfully"),

    // User module 2xxxx
    NEED_LOGIN(20001."Login invalid"),
    USERNAME_OR_PASSWORD_EMPTY(20002."Username or password cannot be empty."),
    USERNAME_OR_PASSWORD_WRONG(20003."Incorrect user name or password"),
    USER_NOT_EXISTS(20004."User does not exist"),
    WRONG_PASSWORD(20005."Password error"),; ResponseCode(Integer code, String msg) {this.code = code;
        this.msg = msg;
    }

    private Integer code;
    private String msg;
    public Integer getCode(a) {
        return code;
    }
    public void setCode(Integer code) {
        this.code = code;
    }
    public String getMsg(a) {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg; }}Copy the code

(3) User-defined runtime exceptions

Customize a runtime exception class by passing in the exception argument to the constructor.

public class MyException extends RuntimeException{
    private String msg;

    public MyException(String msg) {
        super(msg); }}Copy the code

(4) Write a unified exception handling class

Exception handling class is the core of exception handling. SpringBoot provides a ControllerAdvice annotation to intercept exceptions. The use of RestControllerAdvice annotation ensures that the Json format is returned.

If the intercepted exception is MyException, the error result is returned in Json format.

@RestControllerAdvice
public class ExceptionController {

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(value = Exception.class)
    public CommonResult exceptionHandler(Exception e){
        // If the exception thrown is a custom exception, it is returned in JSON format
        if (e instanceof MyException){
            return new CommonResult(ResponseCode.ERROR.getCode(),ResponseCode.ERROR.getMsg(),"Custom error is:"+e.getMessage());
        }
        // If neither, print the exception
        return new CommonResult(ResponseCode.ERROR.getCode(),ResponseCode.ERROR.getMsg(),"The error message is:"+e.getMessage()); }}Copy the code

(5) Testing

To see what happens, here’s a manual exception to test, create the IndexController, and manually throw the exception

@RestController
public class IndexController {

    @RequestMapping(value = "/index",method = RequestMethod.GET)
    public String index(a){
        throw new MyException("Test"); }}Copy the code

View the result of the call:

(6) verification of entity classes

There is a scenario where the length of the user name and password is limited, and the format of the phone number is limited. If you do not meet the requirements, you cannot register. This functionality can be limited on the front end, but it also needs to be limited on the back end interface in case the front end is not limited.

Import two verification dependency packages:

<! -- check --> <! -- https://mvnrepository.com/artifact/javax.validation/validation-api -->
<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>2.01..Final</version> </dependency> <! -- https://mvnrepository.com/artifact/org.hibernate/hibernate-validator -->
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.1. 0.Final</version>
</dependency>
Copy the code

Write an entity class with a validation parameter that validates the package on each attribute.

@Data
public class Register {

    @length (Max = 20,min = 4,message = "user name needs to be between 4 and 20 characters ")
    @notblank (message = "user name cannot be null ")
    private String username;

    @notblank (message = "phone number cannot be empty ")
    @ the Pattern (regexp = "^ 1 [3 4 5 | | | 8] [0-9] \ \ d {8} $", message =" phone number format is not correct ")
    private String phone;

    @length (Max = 20,min = 4,message = "password must be between 4 and 20 characters ")
    @notblank (message = "password cannot be empty ")
    private String password;
}
Copy the code

We add the @valid annotation to the method that we need to use for validation, such as this POST request I want to verify.

@PostMapping("/register")
public CommonResult register(@Valid @RequestBody Register register){
    // A series of registered businesses
    userService.registerUser(register);
    return new CommonResult(ResponseCode.SUCCESS.getCode(),ResponseCode.SUCCESS.getMsg(),"");
}
Copy the code

@ Valid in the case of calibration failure will report illegal abnormal parameters, or catch exceptions in the unification of exception handling, if MethodArgumentNotValidException, just take out the corresponding message data.

@RestControllerAdvice
public class ExceptionController {

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(value = Exception.class)
    public CommonResult exceptionHandler(Exception e){
        // If it is a parameter check exception, throw a check error
        if (e instanceof MethodArgumentNotValidException){
            MethodArgumentNotValidException methodArgumentNotValidException= (MethodArgumentNotValidException) e;
            return new CommonResult(ResponseCode.ERROR.getCode(),ResponseCode.ERROR.getMsg(),
                    "Check error:"+methodArgumentNotValidException.getBindingResult().getFieldError().getDefaultMessage());
        }// If it is a custom exception, give the specific reason for the exception
        else if (e instanceof MyException){
            return new CommonResult(ResponseCode.ERROR.getCode(),ResponseCode.ERROR.getMsg(),"Custom error is:"+e.getMessage());
        }
        // If neither, print the exception
        return new CommonResult(ResponseCode.ERROR.getCode(),ResponseCode.ERROR.getMsg(),"The error message is:"+e.getMessage()); }}Copy the code

(7) Test and verification

The next step is to test the validation functionality, accessed via Postman

If the input parameter does not meet the previous Settings, a specific error message is given. Instead of throwing an unacceptable error:

(8) Summary

Exception handling is the last thing many people think about when they write code and simply implement requirements, which leads to many unpredictable bugs. Well, that’s it for this issue, and I’ll see you next time.