你的位置:首页 > 信息动态 > 新闻中心
信息动态
联系我们

SpringBoot项目异常捕捉全局异常、空指针、自定义异常、表单校验消息等

2021-11-27 3:14:54

场景:
在开发中,通常我们需要对异常分类捕捉处理,例如全局异常、空指针异常、运行时异常、自定义业务异常、springframework.validation验证表单消息等,捕捉记录日志文件后,再把捕捉到的异常消息统一响应到前端。这就需要我们配置相应的策略


捕捉异常并打印记录日志,代码如下:

package com.hkl.modules.exception;

import cn.hutool.core.util.ObjectUtil;
import com.hkl.enums.ResultCode;
import com.hkl.exception.BizException;
import com.hkl.vo.resp.CommonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
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.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Optional;


/**
 * <p>捕捉异常并处理</p >
 * <p>Description:</p >
 * <p>Author:hkl</p >
 * <p>Date: 2021-11-27</p >
 */
@Slf4j
@ControllerAdvice
public class ExceptionAdvice {

    /**
     * <p>捕捉全局异常</p >
     * @author hkl
     * @date 2021-11-27
     * @param ex 捕捉的异常信息回应对象
     */
    @ResponseBody
    @ExceptionHandler(value = {Exception.class})
    public CommonResult<String> exceptionHandler(Exception ex) {
        log.info("捕捉的异常信息:" + ex.getMessage());
        //打印异常信息
        printStackTraceInfo(ex.getStackTrace());
        //获取servlet容器
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        return new CommonResult(ResultCode.FAIL.getCode(), ResultCode.FAIL.getMsg(), ex.getMessage(), request.getRequestURI());
    }

    /**
     * <p>捕捉空指针异常(空指针异常需要单独捕捉处理,异常消息在fillInStackTrace()方法中)</p >
     * @author hkl
     * @date 2021-11-27
     * @param nullEx 捕捉的异常信息回应对象
     */
    @ResponseBody
    @ExceptionHandler(value = {NullPointerException.class})
    public CommonResult<String> exceptionHandler(NullPointerException nullEx) {
        //打印异常信息。空指针异常比较特殊,必须放在下面一行代码 log.info() 之前才可以正常打印出异常类的路径(暂不知为何)
        printStackTraceInfo(nullEx.getStackTrace());
        log.info("捕捉的异常信息:" + nullEx.getMessage());
        //获取servlet容器
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        return new CommonResult(ResultCode.FAIL.getCode(), ResultCode.FAIL.getMsg(), String.valueOf(nullEx.getMessage()), request.getRequestURI());
    }

    /**
     * <p>捕捉自定义异常</p >
     * @author hkl
     * @date 2021-11-27
     * @param bizEx 捕捉的异常信息回应对象
     */
    @ResponseBody
    @ExceptionHandler(value = BizException.class)
    public CommonResult<String> exceptionHandler(BizException bizEx) {
        log.info("捕捉的异常信息:" + bizEx.getMessage());
        //打印异常信息
        printStackTraceInfo(bizEx.getStackTrace());
        //获取servlet容器
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        return new CommonResult(ResultCode.FAIL.getCode(), ResultCode.FAIL.getMsg(), bizEx.getMessage(), request.getRequestURI());
    }

    /**
     * <p>捕捉springframework.validation验证表单消息</p >
     * @author hkl
     * @date 2021-11-27
     * @param ex 捕捉的异常信息回应对象
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public CommonResult<String> exceptionHandler(MethodArgumentNotValidException ex) {
        log.error("异常信息:{}", ex.getMessage());
        //打印异常信息
        printStackTraceInfo(ex.getStackTrace());
        //获取Servlet容器
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        //获取request请求
        HttpServletRequest request = attributes.getRequest();

        CommonResult<String> commonResult = new CommonResult<>();
        return commonResult
                .setCode(ResultCode.FAIL.getCode())
                .setMessage(ResultCode.FAIL.getMsg())
                .setPath(request.getRequestURI())
                .setData(ex.getBindingResult().getFieldError().getDefaultMessage());
    }


    /**
     * <p>打印异常栈追踪的信息</p >
     * @author hkl
     * @date 2021/11/27
     * @param stackTraceElements 追踪到的栈异常信息集合
    */
    private void printStackTraceInfo(StackTraceElement[] stackTraceElements){
        log.error("追踪栈异常信息:");
        for(StackTraceElement stackTraceElement : Optional.ofNullable(stackTraceElements).orElse(new StackTraceElement[0])){
            if(ObjectUtil.isNotNull(stackTraceElement)){
                String errMsg = String.valueOf(stackTraceElement);
                //只打印此项目业务中捕捉到的异常信息
                if(errMsg.contains("com.hkl")){
                    log.error(errMsg);
                }
            }
        }
    }


}