As a business, you will certainly encounter exceptions in business interface code, such as exceptions with code logic, exceptions with business logic, and so on. These exception scenarios are very, very large, so much exception logic to deal with, means that you have to write a lot of repetitive code, as a bit of a business, not just understand CURD, of course want the code to look simple and comfortable.

This article intends to share the evolution of my handling of exceptions and then give an example of uniform exception handling.

The initial approach is to define a business exception class, and when a business exception is caught, construct an error message to return using the error code and error message of the exception.

/** * error code enumeration class */
public enum ResponseCode {
    SUCCESS(0."OK"),
    SERVER_ERROR(1."server error");

    private int code;
    private String msg;

    ResponseCode(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public int getCode(a) {
        return code;
    }

    public ResponseCode setCode(int code) {
        this.code = code;
        return this;
    }

    public String getMsg(a) {
        return msg;
    }

    public ResponseCode setMsg(String msg) {
        this.msg = msg;
        return this; }}/** * Custom service exception class */
public class BizException extends RuntimeException {

    private final int code;

    public BizException(ResponseCode errCode) {
        super(errCode.getMsg());
        this.code = errCode.getCode();
    }

    public BizException(ResponseCode errCode, String msg) {
        super(msg);
        this.code = errCode.getCode();
    }

    public BizException(int code, String msg) {
        super(msg);
        this.code = code;
    }

    public int getCode(a) {
        return this.code; }}class TestService {
	public void testAMethod(a) {
		// Business exception code
		throw newBizException(ResponseCode.BIZ_CODE); }}/ * * * the general structure of the interface returned HttpResult * {" code ": 0," MSG ":" OK "} * /
class TestController {

	@Autowired
	private TestService testService;

	public HttpResult testA(a) {
		try {
			testService.testAMethod();
		} catch (BizException e) {
			return HttpResult(e.getCode(), e.getMsg());
		} catch (Exception e) {
			return HttpResult(ResponseCode.SERVER_ERROR);
		}

		returnHttpResult(ResponseCode.SUCCESS); }}Copy the code

It turns out that an optimization is needed. First, as the business code grows, these tries… Catch looks bloated.

Second, when the underlying code had abnormal also want to capture live in the outer, then one layer at a time out, until the business interface returns returns the error message, if it is a special complex business logic interface, the exception handling code is throughout the entire system, makes the exception code looks very not beautiful, code readability is poor.

Over time, I wondered if there was a way to unify these judgments in a way that would make the code look pretty, just like there was a way to validate interceptors. The answer is yes, which is to use ExceptionHandler and RestControllerAdvice annotations.

First, define a class: Exceptiondemo class (RestControllerAdvice) {return exceptionHandler; return exceptionHandler; return exceptionHandler; Handle the exception logic accordingly.

Specific implementation code examples are as follows:


@RestControllerAdvice
public class SpringMvcExceptionDemo {

    @ExceptionHandler
    public Object exceptionHandler(Exception e, HttpServletRequest request, HttpServletResponse response) {
        if (e instanceof BizException) {
            BizException be = (BizException) e;
            return new HttpResult(be.getCode(), be.getMessage());
        }
        if (e instanceof IllegalArgumentException) {
            return new HttpResult(ResponseCode.PARAM_ERROR.getCode(), e.getMessage());
        }

        return newHttpResult(ResponseCode.SERVER_ERR); }}public HttpResult testA(a) {
	testService.testAMethod();
	return HttpResult(ResponseCode.SUCCESS);
}

Copy the code

This way, you only need to throw an exception where the business exception should be thrown, and the interceptor handles the exception uniformly, reducing a lot of repetitive code and improving the readability of the code.

RestControllerAdvice and ExceptionHandler

RestControllerAdvice is an annotation in the Spring framework that contains ControllerAdvice and ResponseBody and helps us handle exceptions in restful APIS by adding a crosscutting point ExceptionHandler. The time to execute is in doDispatch, and the processDispatchResult method is called. If there is an exception, the method with the ExceptionHandler annotation is called to determine it.

The flow chart is as follows:

Core processing code:

for (HandlerExceptionResolver handlerExceptionResolver : this.handlerExceptionResolvers) {
	exMv = handlerExceptionResolver.resolveException(request, response, handler, ex);
	if(exMv ! =null) {
		break; }}Copy the code

conclusion

The code and principle are relatively simple, and the purpose of unified handling of exceptions is just to eliminate repetitive code blocks and write more concise code. Now I insist on this idea when WRITING code, hoping to explore more skills, and welcome to discuss other skills together.

Original article, writing is limited, talent and learning shallow, if the article is not straight, hope to inform.

If this article has been helpful to you, please feel free to like it. Thank you

More exciting content, please pay attention to the individual public number.