preface

In daily project development, exceptions are common, but how to deal with exceptions more efficiently, so that we can quickly locate bugs, is very important, not only to improve our development efficiency, but also to make your code look more comfortable, SpringBoot projects have certain exception handling, This may not be appropriate for us as developers, so we need to uniformly catch and handle these exceptions.

The default error handling mechanism for SpringBoot

Return to error page

The default returnWhitelabel Error PageThe style of the page is too monotonous and the user experience is not good.If we need to put all of the exception to the same jump to a custom error page, we’ll need to SRC/main/resources/templates directory to create the error. The HTML page.

Note: The name must be error

<! DOCTYPEhtml>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
        <! --SpringBoot stores exception information by default -->
	<span th:text="${exception}" />
</body>
</html>
Copy the code

Returns a JSON format API

The result string in Json format is inconsistent with the unified format stipulated by the front-end personnel

Source code analysis

SpringBoot automatically sends requests to /error when an exception occurs on a page. SpringBoot has a built-in BasicErrorController to handle exceptions uniformly. You can also customize this path

@RequestMapping( produces = {"text/html"} )
    public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
        HttpStatus status = this.getStatus(request);
        Map<String, Object> model = Collections.unmodifiableMap(this.getErrorAttributes(request, this.getErrorAttributeOptions(request, MediaType.TEXT_HTML)));
        response.setStatus(status.value());
        ModelAndView modelAndView = this.resolveErrorView(request, response, status, model);
        returnmodelAndView ! =null ? modelAndView : new ModelAndView("error", model);
    }

    @RequestMapping
    public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
        HttpStatus status = this.getStatus(request);
        if (status == HttpStatus.NO_CONTENT) {
            return new ResponseEntity(status);
        } else {
            Map<String, Object> body = this.getErrorAttributes(request, this.getErrorAttributeOptions(request, MediaType.ALL));
            return newResponseEntity(body, status); }}Copy the code

So we can see exactly the contrast between the two methods: one returns an error page, and the other returns an error character, and the default error path is /error and if you have custom we’ll use custom

server.error.path=/custom/error
Copy the code

Custom error handling

SpringBoot provides the ErrorAttribute type. Customizing the ErrorAttribute type bean is still the default two response modes, with the response content item changed

package cn.soboys.core;


import cn.hutool.core.bean.BeanUtil;
import cn.soboys.core.ret.Result;
import cn.soboys.core.ret.ResultCode;
import cn.soboys.core.ret.ResultResponse;
import org.springframework.boot.web.error.ErrorAttributeOptions;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

/ * * *@author kenx
 * @version 1.0
 * @date2021/6/18 14:14 * Global error */
@Component
public class GlobalErrorHandler extends DefaultErrorAttributes {


    /** * Custom error return page *@param request
     * @param response
     * @param handler
     * @param ex
     * @return* /
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        return super.resolveException(request, response, handler, ex);
    }

    /** * Custom error return format **@param webRequest
     * @param options
     * @return* /
    @Override
    public Map<String, Object> getErrorAttributes(WebRequest webRequest, ErrorAttributeOptions options) {
        Map<String, Object> errorAttributes = super.getErrorAttributes(webRequest, options);
        Result result = ResultResponse.failure(ResultCode.NOT_FOUND, errorAttributes.get("path"));
        Map map = BeanUtil.beanToMap(result, true.true);
        returnmap; }}Copy the code

Custom business exception classes

Inheritance RuntimeException

package cn.soboys.core.authentication;

import cn.soboys.core.ret.ResultCode;
import lombok.Data;

/ * * *@author kenx
 * @version 1.0
 * @date2021/6/22 13:58 * Authentication exception */
@Data
public class AuthenticationException extends RuntimeException {

    public AuthenticationException(String message) {
        super(message); }}Copy the code

Global catch exception

The @RestControllerAdvice and @ControllerAdvice provided by SpringBoot are used together with @ExceptionHandler

@RestControllerAdvice and @ControllerAdvice are different than @RestController and @Controller and if you want to return json you can also use the @responseBody annotation on the method itself

What kind of exception do you need to catch by saying @ExceptionHandler to specify the exception class that you need to catch

Generally speaking, when a small Exception is not specified to catch, a large Exception that contains the Exception will be executed. For example, an Exception contains all Exception classes and is the superparent of all exceptions. When an Exception is not specified, the method that caught the Exception will be executed

@ExceptionHandler Handle exceptions

@Controller
public class DemoController {
	@RequestMapping("/show")
	public String showInfo(a) {
		String str = null;
		str.length();
		return "index";
	}

	@RequestMapping("/show2")
	public String showInfo2(a) {
		int a = 10 / 0;
		return "index";
	}

	/ * * * Java. Lang. ArithmeticException this method needs to return a ModelAndView: purpose is abnormal information allows us to encapsulate and see * figure Exception e specified argument: will produce Exception object injected into the method of * /
	@ExceptionHandler(value = { java.lang.ArithmeticException.class })
	public ModelAndView arithmeticExceptionHandler(Exception e) {
		ModelAndView mv = new ModelAndView();
		mv.addObject("error", e.toString());
		mv.setViewName("error1");
		return mv;
	}

	/ * * * Java. Lang. NullPointerException this method needs to return a ModelAndView: purpose is abnormal information allows us to encapsulate and see * figure Exception e specified argument: will produce Exception object injected into the method of * /
	@ExceptionHandler(value = { java.lang.NullPointerException.class })
	public ModelAndView nullPointerExceptionHandler(Exception e) {
		ModelAndView mv = new ModelAndView();
		mv.addObject("error", e.toString());
		mv.setViewName("error2");
		returnmv; }}Copy the code

Advantages: You can customize the key for storing exception information and the name of the jump view

Disadvantages: You need to write a large number of exception handling methods, not across controllers. If the same exception occurs in two controllers, you need to rewrite the exception handling method

@ControllerAdvice+@ExceptionHandler Handle exceptions

/ * * *@author kenx
 * @version 1.0
 * @date2021/6/17 20:19 * Unified handling of global exceptions */
@RestControllerAdvice
public class GlobalExceptionHandler {
 /** * Authentication exception *@param e
     * @return* /
    @ExceptionHandler(AuthenticationException.class)
    public Result UnNoException(AuthenticationException e) {
        return ResultResponse.failure(ResultCode.UNAUTHORIZED,e.getMessage());
    }

    / * * * *@paramE Unknown exception capture *@return* /
    @ExceptionHandler(Exception.class)
    public Result UnNoException(Exception e) {
        returnResultResponse.failure(ResultCode.INTERNAL_SERVER_ERROR, e.getMessage()); }}Copy the code

Advantages: You can customize the key for storing exception information, the name of the jump view, and the unified interception and capture across controllers, which are generally used

Follow the public channel ape Life to learn more good articles