SpringBoot统一拦截处理异常

为什么web项目需要统一拦截处理异常。

首先,web项目中进行异常的拦截和统一处理是常规操作和常见操作,但不是非做不可的必选动作。

那为什么是开发中经常这样操作呢?个人理解原因有二:

(1)对前端用户友好。当后端代码执行产生异常之后,不会将后端复杂的异常信息返回给前端,而是经过处理后的简化的友好的信息。

(2)对后端开发友好。将所有异常处理放在一个类中进行集中的统一处理,只需要修改一处,即可拦截所有的异常,降低了开发的复杂度。

一、自定义异常类

在web项目中,“自定义异常类”经常与“异常拦截处理”搭配使用。在出现诸如“前端提交字段不符合要求”、“结果查询为空”
、“用户名重复”等影响代码继续执行的情况时,可以直接抛出自定义异常,由统一拦截器捕获后,将信息返回给前端

package com.example.demo.exception;

import lombok.Data;

@Data
public class MyException extends RuntimeException {
    
    
    private String msg;
    private int code = 500;

    public MyException(String msg) {
    
    
        super(msg);
        this.msg = msg;
    }

    public MyException(String msg, Throwable e) {
    
    
        super(msg, e);
        this.msg = msg;
    }

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

    public MyException(String msg, int code, Throwable e) {
    
    
        super(msg, e);
        this.msg = msg;
        this.code = code;
    }
}

二、统一拦截处理异常

异常的统一拦截与处理主要通过@RestControllerAdvice@ExceptionHandler()注解来实现。

@RestControllerAdvice是@Controller注解加强类,相当于@ControllerAdviser + @ResponseBody@ControllerAdviser注解作用对象为TYPE,包括类、接口和枚举等,在运行时有效,并且可以通过Spring扫描为bean组件。其可以包含由@ExceptionHandler、@InitBinder 和@ModelAttribute标注的方法,可以处理多个Controller类,这样所有控制器的异常可以在一个地方进行处理。

//@RestControllerAdvice注解源码
@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 {
    
    };
}

Spring 3.0 引入的@ExceptionHandler注解可以让我们在一个handler方法或者类中统一处理controller抛出的异常,使得写出的代码清晰。当一个Controller中有方法加了@ExceptionHandler之后,这个Controller其他方法中没有捕获的异常就会以参数的形式传入加了@ExceptionHandler注解的那个方法中。当@RestControllerAdvice@ExceptionHandler()注解组合之后,所有controller层面的异常都会统一集中处理。如下定义的ExceptionAdvice类,就是统一处理异常的类。

package com.example.demo.config;

import com.example.emos.wx.exception.EmosException;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * 捕获全局异常,并做处理
 * @author wanglong
 * @ControllerAdvice 和 @RestControllerAdvice都是对Controller进行增强的,可以全局捕获spring mvc抛的异常。
 * RestControllerAdvice = ControllerAdvice + ResponseBody
 */
@Slf4j
@RestControllerAdvice
public class ExceptionAdvice {
    
    

    @ResponseBody
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(Exception.class)
    public String exceptionHandler(Exception e){
    
    
        log.error("执行异常",e);
        if(e instanceof MethodArgumentNotValidException){
    
    
            MethodArgumentNotValidException exception= (MethodArgumentNotValidException) e;
            //返回精简消息(具体某个字段没有通过校验的原因)
            return exception.getBindingResult().getFieldError().getDefaultMessage();
        }
        else if(e instanceof MyException){
    
    
            MyException exception= (MyException) e;
            return exception.getMsg();
        }
        else if(e instanceof UnauthorizedException){
    
    
            return "你不具备相关权限";
        }
        else{
    
    
            return "后端执行异常";
        }
    }
}

猜你喜欢

转载自blog.csdn.net/loongkingwhat/article/details/119699682