SpringBoot全局异常处理

参考文章:

https://blog.csdn.net/chinrui/article/details/71036544

https://blog.csdn.net/chenhaotao/article/details/78784493

http://www.cnblogs.com/java-zhao/archive/2016/08/13/5769018.html

大值思路:

通过使用@ControllerAdvice定义统一的异常处理类,可以不用在每个Controller中逐个定义异常处理方式

代码实现:

  1. 创建一个BizLogicException类,继承自Exception
package com.springcloud.blog.exception;

import java.io.Serializable;
import java.util.ArrayList;

import com.springcloud.blog.bean.SystemMessage;

/**
 * 描述: 异常处理
 * @author hyp
 * @date 2018年7月22日21:36:34
 * @version v0.1
 */
public class BizLogicException extends Exception implements Serializable {

    private static final long serialVersionUID = -5458946175270060619L;
    
    private ArrayList<SystemMessage> messageList = new ArrayList<SystemMessage>();
    
    public ArrayList<SystemMessage> getMessageList() {
        return messageList;
    }

    public void setMessageList(ArrayList<SystemMessage> messageList) {
        this.messageList = messageList;
    }

    public BizLogicException(ArrayList<SystemMessage> messageList) {
        super(messageList.get(0).getMessage());
        this.messageList = messageList;
    }
    
    public BizLogicException(SystemMessage systemMessage) {
        super(systemMessage.getMessage());
        if(systemMessage != null) {
            this.messageList.add(systemMessage);
        }
    }
}

然后就可以可以在代码中,可能会出现异常的地方进行异常抛出,不必捕获

throw new BizLogicException(new SystemMessage("error","系统出现异常"));

测试运行,然后在控制台打印出来错误信息,但是定义的错误信息却不能返回出去,因此需要定义一个类,进行全局的错误捕获

  1. 创建一个GlobalExceptionHandler类,增加@ControllerAdvice注解
package com.springcloud.blog.config;

import java.text.MessageFormat;

import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
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 com.fasterxml.jackson.databind.exc.InvalidFormatException;
import com.springcloud.blog.bean.ServiceResponseBase;
import com.springcloud.blog.bean.SystemMessage;
import com.springcloud.blog.consts.CommonConsts;
import com.springcloud.blog.exception.BizLogicException;
import com.springcloud.blog.utils.Pub;

/**
 * 描述:全局异常处理
 * 参考地址:http://www.cnblogs.com/java-zhao/archive/2016/08/13/5769018.html
 * 
 * @ControllerAdvice是controller的一个辅助类,最常用的就是作为全局异常处理的切面类
 * @ControllerAdvice可以指定扫描范围
 * @ControllerAdvice约定了几种可行的返回值,如果是直接返回model类的话,
 * 需要使用@ResponseBody进行json转换 返回String,表示跳到某个view 返回modelAndView 返回model + @ResponseBody
 * @author: 和彦鹏
 * @date: 和2018年7月22日22:24:53
 * @version:v0.1
 */
@ControllerAdvice
public class GlobalExceptionHandler {
    
    /**
     * 日志
     */
    private final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
    
    @ExceptionHandler//处理所有异常
    @ResponseBody // 在返回自定义相应类的情况下必须有,这是@ControllerAdvice注解的规定
    public ServiceResponseBase exceptionHandler(Exception e, HttpServletResponse response) {
        ServiceResponseBase resp = new ServiceResponseBase();
        
        if(e instanceof BizLogicException) {
            BizLogicException bizLogicException = (BizLogicException)e;
            resp.setResponseCode(CommonConsts.RESPONSE_CODE_WARNING);
            resp.setMessageList(bizLogicException.getMessageList());
        }
        // 验证出错
        else if(e instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException methodArgumentNotValidException = (MethodArgumentNotValidException)e;
            BindingResult result = (BindingResult) methodArgumentNotValidException.getBindingResult();
            if (result.hasErrors()) {
                ServiceResponseBase serviceResponseBase = new ServiceResponseBase();
                for (ObjectError error : result.getAllErrors()) {
                    Pub.addSystemMessage(error.getCodes()[0], error.getDefaultMessage(), serviceResponseBase);
                }
                resp.setResponseCode(CommonConsts.RESPONSE_CODE_WARNING);
                resp.setMessageList(serviceResponseBase.getMessageList());
            }
        }
        
      //jacksonMapper转换出错
        else if(e.getCause() instanceof InvalidFormatException) {
            InvalidFormatException invalidFormatException = (InvalidFormatException)e.getCause();
            ServiceResponseBase serviceResponseBase = new ServiceResponseBase();
            // 字段[{0}]的值[{1}]不能转换成[{2}]类型
            Pub.addSystemMessage(new SystemMessage("ClassCaseException", 
                    MessageFormat.format("字段[{0}]的值[{1}]不能转换成[{2}]类型", new Object[]{
                            invalidFormatException.getPathReference()//字段
                            , invalidFormatException.getValue()//值
                            //类型
                            , invalidFormatException.getTargetType().getName()})), serviceResponseBase);
            resp.setResponseCode(CommonConsts.RESPONSE_CODE_WARNING);
            resp.setMessageList(serviceResponseBase.getMessageList());
        }
        else if(e instanceof HttpRequestMethodNotSupportedException) {
            resp.setResponseCode(CommonConsts.RESPONSE_CODE_WARNING);
            Pub.addSystemMessage("SERVER_ERROR", "访问资源有误,请确认资源路径。", resp);
        }
        else {
            resp.setResponseCode(CommonConsts.RESPONSE_CODE_WARNING);
            Pub.addSystemMessage("SERVER_ERROR", "系统异常,请联系管理员!", resp);
        }
        log.error(e.getMessage(), e);
        return resp;
    }
}

贴上Pub类代码

package com.springcloud.blog.utils;

import java.util.ArrayList;
import java.util.List;

import com.github.pagehelper.Page;
import com.springcloud.blog.bean.PageControllerInfo;
import com.springcloud.blog.bean.ServiceResponseBase;
import com.springcloud.blog.bean.SystemMessage;
import com.springcloud.blog.consts.CommonConsts;

public class Pub {

    public static void addSystemMessage(String key, String message, ServiceResponseBase responseDto) {
        ArrayList<SystemMessage> systemMessages = responseDto.getMessageList();
        if (systemMessages == null) {
            systemMessages = new ArrayList<SystemMessage>();
        }
        SystemMessage systemMessage = new SystemMessage(key, message);
        systemMessages.add(systemMessage);
        responseDto.setMessageList(systemMessages);
        responseDto.setResponseCode(CommonConsts.RESPONSE_CODE_WARNING);
    }
    
    public static void addSystemMessage(SystemMessage message, ServiceResponseBase responseDto) {
        ArrayList<SystemMessage> systemMessages = responseDto.getMessageList();
        if (systemMessages == null) {
            systemMessages = new ArrayList<SystemMessage>();
        }
        systemMessages.add(message);
        responseDto.setMessageList(systemMessages);
        responseDto.setResponseCode(CommonConsts.RESPONSE_CODE_WARNING);
    }
    
    public static <E> PageControllerInfo getPageControllerInfo(List<E> list) throws Exception {
        if (list == null) {
            throw new Exception("getPageControllerInfo方法的参数不能为空!");
        }
        if (!(list instanceof Page<?>)) {
            return null;
        }
        
        Page<E> page = (Page<E>) list;
        PageControllerInfo pageControllerInfo = new PageControllerInfo();
        pageControllerInfo.setPageNum(page.getPageNum());
        pageControllerInfo.setPageSize(page.getPageSize());
        pageControllerInfo.setTotalRecordCount(page.getTotal());
        pageControllerInfo.setTotalPages(page.getPages());
        return pageControllerInfo;
    }
}

这样,如果代码中如果有异常,则会把错误消息直接抛出来

{
    "responseCode": "300",
    "messageList": [
        {
            "key": "error",
            "message": "系统出现异常"
        }
    ],
    "version": null
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值