【spring boot】捕获全局异常@RestControllerAdvice

 

 

一.由来

场景:  使用 Java的validation做入参的校验  ,但是这种入参校验在还没有进入controller就会字段校验不通过,从而直接返回异常信息给前端,

    前端的异常提醒, 类似于下面这种 很不友好的 

后端接口报错提示信息:

 

 

 

 

 

 

 

 

二.解决方法

1.解决如上问题,需要对异常做捕获处理,Spring boot 提供了@RestControllerAdvice 可以完成 全局异常捕获处理

 

2.具体实现

 

 

2.1  定义请求入参GlobalParams

【比如,使用Java的validation做入参的校验 这种场景】

package com.sxd.swapping.globalException.param;

import lombok.Data;

import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;


/**
 * 使用 Java的validation做入参的校验
 * 测试一下全局异常怎么捕获这种入参类型的校验(因为此处入参校验未通过,压根就不会进Controller)
 */
@Data
public class GlobalParams {

    @NotNull(message = "ID不能为空")
    private Long id;

    @NotEmpty(message = "集合不能为空")
    private List<String>  myStrList;



}
View Code

 

 

2.2 定义请求响应GlobalResult 

【可一定要getter/setter方法】

package com.sxd.swapping.globalException.result;

import lombok.Data;

/**
 * 自定义一个 统一响应体
 */
@Data
public class GlobalResult {

    public static final String SUCCESS_CODE = "0000";

    public static final String ERROR_CODE = "9999";

    /**
     * 状态码
     */
    private String code;

    /**
     * 状态码描述
     */
    private String message;

    /**
     * 响应结果
     */
    private Object data;

    private GlobalResult(String code, String message) {
        this(code, message, null);
    }

    private GlobalResult(String code, String message, Object data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }


    public static GlobalResult build(String code, String message) {
        return new GlobalResult(code, message);
    }

    public static GlobalResult build(String code, String message, Object data) {
        return new GlobalResult(code, message, data);
    }

    public static GlobalResult success() {
        return build(SUCCESS_CODE, "处理成功");
    }

    public static GlobalResult success(String code, String message) {
        return build(code, message);
    }

    public static GlobalResult success(Object data) {
        return build(SUCCESS_CODE, "处理成功", data);
    }

    public static GlobalResult error() {
        return build(ERROR_CODE, "处理失败");
    }

    public static GlobalResult error(String message) {
        return error(ERROR_CODE, message);
    }

    public static GlobalResult error(String code, String message) {
        return build(code, message);
    }
}
View Code

 

 

2.3 定义全局异常捕获GlobalAdvice

【可捕获一种特定异常,也可捕获多种异常,依顺序从上往下】

package com.sxd.swapping.globalException.advice;

import com.sxd.swapping.globalException.result.GlobalResult;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.List;

/**
 * 全局异常捕获
 *@RestControllerAdvice都是对Controller进行增强的,可以全局捕获spring mvc抛的异常。
 *
 * ExceptionHandler 可以全局仅捕获一种异常,也可以全局捕获多种异常,从上到下 依次处理
 *
 */
@RestControllerAdvice
public class GlobalAdvice {


    /**
     * ExceptionHandler的作用是用来捕获指定的异常
     * 这里示例 捕获 Java的validation做入参的校验 的校验失败的异常
     * 统一处理,免得返回前端
     * @param e
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public GlobalResult handleStoreAuthException(MethodArgumentNotValidException e) {
        List<ObjectError> allErrors = e.getBindingResult().getAllErrors();
        StringBuilder detailMsg = new StringBuilder();
        if (CollectionUtils.isNotEmpty(allErrors)) {
            allErrors.stream().forEach(i -> detailMsg.append(i.getDefaultMessage()).append(";"));
        }
        return GlobalResult.build(GlobalResult.ERROR_CODE, detailMsg.toString());
    }


    /**
     * ExceptionHandler的作用是用来捕获指定的异常
     * 这里示例 捕获 Exception异常
     * @param e
     * @return
     */
    @ExceptionHandler(Exception.class)
    public GlobalResult handleStoreAuthException(Exception e) {
        return GlobalResult.build(GlobalResult.ERROR_CODE, e.getMessage());
    }
}
View Code

 

 

2.4 定义接口GlobalExceptionController

package com.sxd.swapping.globalException.controller;

import com.sxd.swapping.globalException.param.GlobalParams;
import com.sxd.swapping.globalException.result.GlobalResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;


@Slf4j
@Controller
@RequestMapping("/myglobal/exception")
public class GlobalExceptionController {


    @ResponseBody
    @PostMapping(value = "/test")
    public GlobalResult myTest(@Valid @RequestBody GlobalParams params){

        Long id = params.getId();
        id = id / 0;
        log.info("业务处理!!!");
        return GlobalResult.success();
    }


}
View Code

 

 

 

三.验证结果

 

 

前端控件也可返回友好的异常提醒

 

 

 

posted @ 2021-04-07 16:22  Angel挤一挤  阅读(843)  评论(0编辑  收藏  举报