import com.cmb.rum.logger.exception.BusinessException;
import com.cmb.rum.logger.exception.ErrorDetail;
import com.cmb.rum.logger.exception.GenericError;
import feign.Response;
import feign.Util;
import feign.codec.ErrorDecoder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import java.io.IOException;
import java.util.Map;
import java.util.stream.Collectors;
@Slf4j
public class FeignErrorDecoder implements ErrorDecoder {
private static final String SPLIT_CHAR = "#";
@Autowired
private ApplicationContext context;
private Map<String, ErrorDecodeStrategy> strategyMap;
@Override
public Exception decode(String s, Response response) {
String body = null;
try {
if (response.body() != null) {
ErrorDecodeStrategy strategy = getDecoder(s);
if (strategy != null) {
strategy.handleResponse(response);
}
body = Util.toString(response.body().asReader());
log.error("调用外部服务异常,请求信息:{},异常返回:{}", response.request().toString(), body);
}
} catch (IOException e) {
log.error("解析外部服务异常返回body失败,请求信息:{}", response.request().toString(), e);
}
return new BusinessException(new ErrorDetail(GenericError.BAD_REQUEST, "异常请求:" + response.request().toString() + "异常返回:" + body), response.status());
}
private ErrorDecodeStrategy getDecoder(String s) {
if (strategyMap == null) {
strategyMap = context.getBeansOfType(ErrorDecodeStrategy.class).values().stream().collect(Collectors.toMap(ErrorDecodeStrategy::getName, x -> x));
}
String clientClassName = s.split(SPLIT_CHAR)[0];
return strategyMap.get(clientClassName);
}
}
@Bean
@Primary
public ErrorDecoder errorDecoder() {
return new FeignErrorDecoder();
}
注入到springboot容器
import feign.Response;
/**
* Feign异常解码策略
*/
public interface ErrorDecodeStrategy {
/**
* 对应处理什么Client的如YstServiceClient
*
* @return
*/
String getName();
/**
* 处理返回的结果
*
* @param response
*/
void handleResponse(Response response);
}
import com.cmb.rum.logger.exception.BusinessException;
import com.cmb.rum.logger.exception.ErrorDetail;
import com.cmbchina.corporate.info.client.YstServiceClient;
import com.cmbchina.corporate.info.client.dto.yst.YstErrorResponse;
import com.cmbchina.corporate.info.exception.YstErrorCode;
import com.fasterxml.jackson.databind.ObjectMapper;
import feign.Response;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.IOException;
import static com.cmbchina.corporate.info.exception.YstErrorCode.ServerError;
/**
* 移事通错误异常处理策略
*
*/
@Service
@Slf4j
public class YstErrorDecodeStrategy implements ErrorDecodeStrategy {
@Resource
private ObjectMapper objectMapper;
@Override
public String getName() {
return YstServiceClient.class.getSimpleName();
}
@Override
public void handleResponse(Response response) {
try {
YstErrorResponse errorResponse = objectMapper.readValue(response.body().asReader(), YstErrorResponse.class);
YstErrorCode ystErrorCode = YstErrorCode.valueOf(errorResponse.getCode());
throw new BusinessException(new ErrorDetail(ystErrorCode, errorResponse.getMessage()), ystErrorCode.getCode());
} catch (IOException e) {
log.error("yst异常返回解析失败,{}, {}", response, e.getMessage());
throw new BusinessException(new ErrorDetail(ServerError, ServerError.getDescription()), ServerError.getCode());
}
}
}