0
点赞
收藏
分享

微信扫一扫

2019-09-26/springcloud zuul全局异常处理

奋斗De奶爸 2021-10-09 阅读 31

在平常的springboot项目中,我们通常会定义一个全局异常处理的Handler,返回自定义的的json格式:

import cn.wjp.common.system.Result;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

@ControllerAdvice
public class GlobalExceptionHandler {
    /**
     * 全局异常捕捉处理
     * @param e
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public Result errorHandler(Exception e) {
        e.printStackTrace();//便于调试
        return Result.getFailedResultFromException(e);
    }
}

从异常中获取错误信息的工具类:

import cn.wjp.common.system.exception.BusinessException;
import cn.wjp.common.system.exception.ErrorMsg;
import cn.wjp.common.system.utils.ExceptionUtil;
import java.io.Serializable;
@Getter
@Setter
public class Result<T> implements Serializable {
    /**
     * 错误码.
     */
    private String code;
    /**
     * 提示信息.
     */
    private String msg;
    /**
     * 具体的内容.
     */
    private T data;

    public static Result getFailedResultFromException(Exception e) {
        Result r = new Result();
        String errMessage = e.getMessage()==null?"":e.getMessage();
        //如果是自定义异常,把状态码返回给前端,便于区分不同的错误
        if(e instanceof BusinessException){
            BusinessException exception =(BusinessException)e;
            String code = exception.getCode();
            r.setCode(code);
            r.setMsg(exception.getMsg());
        }else{//否则,当作一般性的错误,状态码是固定的
            r.setCode(ErrorMsg.ERROR.getCode()+"");
            r.setMsg(ErrorMsg.ERROR.getMsg()+","+errMessage);
        }
        r.setData(ExceptionUtil.getStackTrace(e));
        return r;
    }

}

import java.io.PrintWriter;
import java.io.StringWriter;
public class ExceptionUtil {
    /**
     * 获取异常堆栈信息 
     * @param throwable
     * @return
     */
    public static String getStackTrace(Throwable throwable) {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        try {
            throwable.printStackTrace(pw);
            return sw.toString();
        } finally {
            pw.close();
        }
    }
}

如果是在springcloud项目中呢,我们如何处理全局异常,我的一个办法是继续在每个服务模块中写上述的全局异常处理代码(通过编写公共模块,引入pom即可),在此基础上,可以在zuul上定义过滤器,处理全局异常:

import com.alibaba.fastjson.JSON;
import cn.wjp.common.system.Result;
import com.netflix.zuul.context.RequestContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.netflix.zuul.filters.post.SendErrorFilter;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;
import javax.servlet.http.HttpServletResponse;

/**
 * 重写错误过滤器  使它返回标准的格式
 */
@Component
public class ErrorFilter extends SendErrorFilter {
    private final static Logger logger = LoggerFactory.getLogger(ErrorFilter.class);

    @Override
    public Object run() {
        try{
            RequestContext ctx = RequestContext.getCurrentContext();
            //直接复用异常处理类
            Throwable throwable = ctx.getThrowable();
            ExceptionHolder exceptionHolder = findZuulException(throwable);
            Exception exception = null;
            if(throwable instanceof Exception){
                exception = (Exception)throwable.getCause();
            }
            logger.info("异常信息:{}", throwable);
            Result result;
            if(exception!=null){
                result = Result.getFailedResultFromException(exception);
            }else{
                result = Result.getFailedResult(exceptionHolder.getErrorCause());
            }
            HttpServletResponse response = ctx.getResponse();
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write(JSON.toJSONString(result));
        }catch (Exception ex) {
            ReflectionUtils.rethrowRuntimeException(ex);
        }
        return null;
    }
}

这样不论后台报什么错,都能返回我们想要的格式。不足的一点就是,当服务不可用或者正在启动,当你访问该服务模块的时候,会返回自定义json,但是我们却无法得知到底出了什么问题,都是统一的forwardException,表示在网关处转发请求失败。

举报

相关推荐

0 条评论