SpringCloud 微服务下自定义异常传值问题
1 需求描述
微服务A调用微服务B,此时微服务B需要抛出异常,且该异常需要携带自定义code,特殊数据data
但是直接像单服务全局捕获处理是无法使用code及data,为解决该问题需要修改相关内容。
2 自定义异常
package com.carfi.common.exception;
import com.carfi.common.constant.ApiHint;
/**
* 自定义异常
* @author ll
* @date 2019年9月6日
*
*/
public class MyException extends RuntimeException{
/**
*
*/
private static final long serialVersionUID = 1L;
private Integer code;
private Object data;
public MyException(){}
public MyException(Integer code, String msg){
super(msg);
this.code = code;
}
public MyException(Integer code, String msg, Object data){
super(msg);
this.code = code;
this.data = data;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
3 微服务B返回异常
继承DefaultErrorAttributes类,自定义返回code及data
package com.carfi.core.config;
import com.carfi.common.exception.MyException;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.WebRequest;
import java.util.Map;
/**
* com.carfi.cxyapi.config$
*
* @author ll
* @date 2021-03-29 16:20:00
**/
@Component
@Primary
public class CustomErrorAttributes extends DefaultErrorAttributes {
@Override
public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
Map<String, Object> errorAttributes = super.getErrorAttributes(webRequest, includeStackTrace);
Throwable error = this.getError(webRequest);
if (error instanceof MyException) {
errorAttributes.put("code", ((MyException) error).getCode());
errorAttributes.put("data", ((MyException) error).getData());
}
return errorAttributes;
}
}
4 微服务A处理异常
自定义解析异常
package com.carfi.common.config;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.carfi.common.constant.ApiHint;
import com.carfi.common.exception.MyException;
import feign.Response;
import feign.Util;
import feign.codec.ErrorDecoder;
import org.springframework.context.annotation.Configuration;
import java.io.IOException;
/**
* com.carfi.common.exception$
*
* @author ll
* @date 2021-03-29 15:21:49
**/
@Configuration
public class MyExceptionDecoder implements ErrorDecoder {
@Override
public Exception decode(String methodKey, Response response) {
Exception exception = null;
try {
String json = Util.toString(response.body().asReader());
Exception e = JSON.parseObject(json, Exception.class);
e.printStackTrace();
JSONObject jsonObject = JSONObject.parseObject(json);
Object data = jsonObject.get("data");
Integer code = jsonObject.getInteger("code");
String message = JSONObject.parseObject(json).getString("message");
if (message.contains("Load balancer does not have available server for client")) {
return new MyException(ApiHint.SYS_BUSY);
} else if (code == null) {
return new MyException(ApiHint.OTHER);
}
return new MyException(code, message, data);
} catch (IOException e) {
e.printStackTrace();
}
return exception;
}
}
全局异常处理
package com.carfi.cxyapi.exceptionhandler;
import com.carfi.common.constant.ApiHint;
import com.carfi.common.exception.MyException;
import com.carfi.common.pojo.ResObj;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import javax.validation.ValidationException;
@ControllerAdvice(basePackages = {"com.carfi"})
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler({Exception.class, RuntimeException.class})
@ResponseBody
public ResObj doHandler(Exception e){
ResObj error;
if(e instanceof MyException){
MyException me = (MyException) e;
error = ResObj.error(me.getCode(),me.getMessage(),me.getData());
} else if (e instanceof ValidationException) {
ValidationException ve = (ValidationException) e;
MyException myException = (MyException) ve.getCause();
error = ResObj.error(myException.getCode(), myException.getMessage());
} else {
e.printStackTrace();
if(e.getMessage().contains("Load balancer does not have available server for client")){
error = ResObj.error(ApiHint.SYS_BUSY);
}else{
error = ResObj.error(ApiHint.OTHER);
}
}
return error;
}
}