springboot整合全局异常处理

一、项目结构

springboot整合全局异常处理_第1张图片

二、全局异常

(1)启动类

package com.mgx;

import com.mgx.common.dto.Result;
import com.mgx.utils.ErrorUtil;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * @author mgx
 */
@ControllerAdvice
@MapperScan("com.mgx.mapper")
@SpringBootApplication
public class SpringbootMgxApplication {

    public static void main(String[] args) {
        System.out.println("开始启动");
        SpringApplication.run(SpringbootMgxApplication.class, args);
        System.out.println("启动成功");
    }

    /**
     * 全局异常处理
     *
     * @param exception Exception
     * @return R
     */
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public Result defaultExceptionHandler(Exception exception) {
        return ErrorUtil.handleException(exception);
    }

}

⚠️注意:@ControllerAdvice是@Controller 的增强版。@ControllerAdvice主要用来处理全局数据,一般搭配@ExceptionHandler、@ModelAttribute以及@InitBinder使用。全局异常处理,将配合@ExceptionHandler定义全局异常捕获机制。

(2)CuzException类

package com.mgx.exception;

import com.mgx.common.enums.MsgCode;

/**
 * @author mgx
 */
public class CuzException extends RuntimeException {

    private MsgCode msgCode;

    @Override
    public String getMessage() {
        return msgCode.getMsg();
    }

    public CuzException(MsgCode msgCode) {
        this.msgCode = msgCode;
    }

    public MsgCode getMsgCode() {
        return msgCode;
    }

    public void setMsgCode(MsgCode msgCode) {
        this.msgCode = msgCode;
    }
}

(3)ErrorUtil

package com.mgx.utils;

import com.mgx.common.dto.Result;
import com.mgx.common.enums.MsgCode;
import com.mgx.exception.CuzException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.sql.SQLException;
import java.util.Enumeration;

/**
 * @author mgx
 */
@Slf4j
public class ErrorUtil {

    private static Result getParamErrorMessage(MethodArgumentNotValidException e) {
        //按需重新封装需要返回的错误信息
        StringBuilder stringBuilder = new StringBuilder();
        //解析原错误信息,封装后返回,此处返回非法的字段名称,错误信息
        for (FieldError error : e.getBindingResult().getFieldErrors()) {
            if (stringBuilder.length() > 1) {
                stringBuilder.append(";  ");
            }
            stringBuilder.append(error.getDefaultMessage());
        }
        return Result.failure().code(MsgCode.Code_500.getCode()).message(stringBuilder.toString()).build();
    }

    public static Result handleException(Exception exception) {
        try {
            // 打印全部异常信息
            log.error("系统异常:", exception);
            throw exception;
        } catch (CuzException e) {
            MsgCode msgCode = e.getMsgCode();
            return Result.failure().code(msgCode == null ? MsgCode.Code_500.getCode() : msgCode.getCode()).message(msgCode == null ? e.getMessage() : msgCode.getMsg()).build();
        } catch (IllegalAccessException e) {
            return Result.failure().code(MsgCode.Code_503.getCode()).build();
        } catch (MethodArgumentNotValidException e) {
            printException();
            return getParamErrorMessage(e);
        } catch (HttpMessageNotReadableException e) {
            printException();
            return Result.failure().code(MsgCode.Code_2002.getCode()).build();
        } catch (HttpRequestMethodNotSupportedException e) {
            return Result.failure().code(MsgCode.Code_2004.getCode()).build();
        } catch (MissingServletRequestParameterException e) {
            return Result.failure().code(MsgCode.Code_2003.getCode()).build();
        } catch (IllegalArgumentException e) {
            return Result.failure().code(MsgCode.Code_2001.getCode()).build();
        } catch (BindException e) {
            return Result.failure().code(MsgCode.Code_500.getCode()).message(e.getAllErrors().get(0).getDefaultMessage()).build();
        } catch (SQLException | DataIntegrityViolationException | BadSqlGrammarException e) {
            return Result.failure().code(MsgCode.Code_2005.getCode()).build();
        } catch (Exception e) {
            return Result.failure().code(MsgCode.Code_500.getCode()).build();
        }
    }

    private static void printException(){
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if(attributes == null){
            return;
        }
        HttpServletRequest request = attributes.getRequest();
        // 记录下请求内容
        log.error("URL : " + request.getRequestURL().toString());
        log.error("HTTP_METHOD : " + request.getMethod());
        log.error("IP : " + request.getRemoteAddr());
        Enumeration enu = request.getParameterNames();
        while (enu.hasMoreElements()) {
            String name = enu.nextElement();
            log.error("name:{},value:{}", name, request.getParameter(name));
        }
    }
}

三、测试

(1)下面的SQL明显是错误的,那么我们调用含该SQL的接口,看会返给我们什么

springboot整合全局异常处理_第2张图片

接口调用测试

springboot整合全局异常处理_第3张图片

(2)没有该数据,接口逻辑中抛异常,看会返给我们什么

springboot整合全局异常处理_第4张图片

接口调用测试

springboot整合全局异常处理_第5张图片

(3)自定义SQL语法错误的全局异常,与返回一致,全局异常处理成功。 

你可能感兴趣的:(spring,boot,java,spring)