在后端发生异常或者是请求出错时,前端通常显示如下

对于用户来说非常不友好。本文主要讲解如何在SpringBoot应用中使用统一异常处理。
第一种:使用@ControllerAdvice和@ExceptionHandler注解
第二种: 使用ErrorController类来实现。
package com.hanzhenya.learnspringboot.advice;
import com.hanzhenya.learnspringboot.util.ResultInfo;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
 * @Description: 切面异常处理
 * @author: 韩振亚
 * @date: 2021年03月29日 13:38
 */
@RestControllerAdvice
public class GlobalControllerAdvice{
        private static final String BAD_REQUEST_MSG = "客户端请求参数错误";
        // <1> 处理 form data方式调用接口校验失败抛出的异常 
        @ExceptionHandler(BindException.class)
        public ResultInfo bindExceptionHandler(BindException e) {
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
        List collect = fieldErrors.stream().map(o ->o.getDefaultMessage()).collect(Collectors.toList());
       return new ResultInfo().success(HttpStatus.BAD_REQUEST.value(), BAD_REQUEST_MSG, collect);
        }
        // <2> 处理 json 请求体调用接口校验失败抛出的异常 
     @ExceptionHandler(MethodArgumentNotValidException.class)
     public ResultInfo methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
        List collect = fieldErrors.stream().map(o ->o.getDefaultMessage()).collect(Collectors.toList());
        return new ResultInfo().success(HttpStatus.BAD_REQUEST.value(), BAD_REQUEST_MSG, collect);
        }
        // <3> 处理单个参数校验失败抛出的异常
         @ExceptionHandler(ConstraintViolationException.class)
         public ResultInfo constraintViolationExceptionHandler(ConstraintViolationException e) {
         Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
        List collect = constraintViolations.stream().map(o -> o.getMessage()).collect(Collectors.toList());
        return new ResultInfo().success(HttpStatus.BAD_REQUEST.value(), BAD_REQUEST_MSG, collect);
        }
        }
注解@ControllerAdvice表示这是一个控制器增强类,当控制器发生异常且符合类中定义的拦截异常类,将会被拦截。
可以定义拦截的控制器所在的包路径
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ControllerAdvice {
    @AliasFor("basePackages")
    String[] value() default {};
    @AliasFor("value")
    String[] basePackages() default {};
    Class<?>[] basePackageClasses() default {};
    Class<?>[] assignableTypes() default {};
    Class<? extends Annotation>[] annotations() default {};
}
注解ExceptionHandler定义拦截的异常类
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExceptionHandler {
    Class<? extends Throwable>[] value() default {};
} 
系统默认的错误处理类为BasicErrorController,将会显示如上的错误页面。
这里编写一个自己的错误处理类,上面默认的处理类将不会起作用。
getErrorPath()返回的路径服务器将会重定向到该路径对应的处理类,本例中为error方法。
@Slf4j
@RestController
public class HttpErrorController implements ErrorController {
    private final static String ERROR_PATH = "/error";
    @ResponseBody
    @RequestMapping(path  = ERROR_PATH )
    public BaseResult error(HttpServletRequest request, HttpServletResponse response){
        log.info("访问/error" + "  错误代码:"  + response.getStatus());
        BaseResult result = new WebResult(WebResult.RESULT_FAIL,"HttpErrorController error:"+response.getStatus());return result;
    }
    @Override
    public String getErrorPath() {
        return ERROR_PATH;
    }
}
1.注解@ControllerAdvice方式只能处理控制器抛出的异常。此时请求已经进入控制器中。
2.类ErrorController方式可以处理所有的异常,包括未进入控制器的错误,比如404,401等错误
3.如果应用中两者共同存在,则@ControllerAdvice方式处理控制器抛出的异常,类ErrorController方式处理未进入控制器的异常。
4.@ControllerAdvice方式可以定义多个拦截方法,拦截不同的异常类,并且可以获取抛出的异常信息,自由度更大。
原文:https://www.cnblogs.com/h-z-y/p/14600658.html