dubbo转springcloud 异常管理

1统一异常管理的问题!

之前dubbo 是service遇到异常直接抛出一个自定义异常,消费web端直接用一个统一异常管理类解析返还给前端。


@ControllerAdvice(basePackages = {"com.*.web.controller"})
@ResponseBody
public class ExceptionAdvice {
    @ExceptionHandler(RuntimeException.class)
    public Object handleException(RuntimeException e) {
        return ResultUtils.Error(e.getMessage());
    }
    //自己写的用户认证异常
    @ExceptionHandler(TokenAuthException.class)
    public Object handleException(TokenAuthException e) {
        return ResultUtils.Error(2001, e.getMessage());
    }
}

但是用springcloud之后因为是走的http协议而内部默认实现是FeignException的异常而,其中的内容


public class FeignException extends RuntimeException {
    private static final long serialVersionUID = 0L;
    private int status;

    protected FeignException(String message, Throwable cause) {
        super(message, cause);
    }

    protected FeignException(String message) {
        super(message);
    }

    protected FeignException(int status, String message) {
        super(message);
        this.status = status;
    }

    public int status() {
        return this.status;
    }

    static FeignException errorReading(Request request, Response ignored, IOException cause) {
        return new FeignException(String.format("%s reading %s %s", cause.getMessage(), request.method(), request.url()), cause);
    }

    public static FeignException errorStatus(String methodKey, Response response) {
        String message = String.format("status %s reading %s", response.status(), methodKey);

        try {
            if (response.body() != null) {
                //这里是我们默认的返回body 他并没有存储,使得需要二次解析
                String body = Util.toString(response.body().asReader());
                message = message + "; content:\n" + body;
            }
        } catch (IOException var4) {
            ;
        }

        return new FeignException(response.status(), message);
    }

    static FeignException errorExecuting(Request request, IOException cause) {
        return new RetryableException(String.format("%s executing %s %s", cause.getMessage(), request.method(), request.url()), cause, (Date)null);
    }
}

因为走的是FeignException ,并且没有单独解析。
所以造成异常我没自己写就很复杂。

解决

自己定义已个异常封装。

public class ResponseException extends RuntimeException {

    private String body;
    private int status;

    public ResponseException(int status, String body) {
        this.body = body;
        this.status = status;
    }

    public String getBody() {
        return body;
    }

    public int getStatus() {
        return status;
    }
}

再把这个异常注册声明

@Configuration
public class FeignErrorDecoder implements ErrorDecoder {
    @Override
    public Exception decode(String s, Response response) {
        String body = null;
        try {
            if (response.body() != null) {
                body = Util.toString(response.body().asReader());
            }
        } catch (IOException var4) {
            ;
        }
        return new ResponseException(response.status(),body);
    }

}

最后在我们的统一异常管理中加入反射处理

@ControllerAdvice(basePackages = {"com.*.web.controller"})
@ResponseBody
public class ExceptionAdvice {
    @ExceptionHandler(RuntimeException.class)
    public Object handleException(RuntimeException e) {
        return ResultUtils.Error(e.getMessage());
    }

    /**
     * 反射适配远端异常!
     * @param e
     * @return
     * @throws ClassNotFoundException
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    @ExceptionHandler(ResponseException.class)
    public Object handleException(ResponseException e) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        String body = e.getBody();
        JSONObject jsonObject = JSONObject.parseObject(body);
        String classname = jsonObject.getString("exception");
        ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
        Class aClass = contextClassLoader.loadClass(classname);
        Object o = jsonObject.toJavaObject(aClass);
        Method handleException = this.getClass().getDeclaredMethod("handleException", aClass);
        if (handleException != null) {

            return handleException.invoke(this, o);
        }
        return handleException((RuntimeException)o);
    }

    //自己写的用户认证异常
    @ExceptionHandler(TokenAuthException.class)
    public Object handleException(TokenAuthException e) {
        return ResultUtils.Error(2001, e.getMessage());
    }
}

算是一个省劲靠谱的异常管理

你可能感兴趣的:(dubbo转springcloud 异常管理)