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());
}
}
算是一个省劲靠谱的异常管理