feign拦截器
请求拦截
/**
* 服务间header传递配置
*/
@Slf4j
@Configuration //由各个项目自己配置
public class FeignConfiguration implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
if (UserContext.getHeaders()!=null) {
UserContext.getHeaders().forEach(template::header);
}
try {
// 服务调用异常辅助信息
Target<?> target = template.feignTarget();
FeignMetaVO feignMetaVO = new FeignMetaVO(target.name(), target.type().getSimpleName(), template.url(), template.method(),
JSON.toJSONString(template.queries()), new String(template.body(), StandardCharsets.UTF_8));
UserContext.setExtra(UserContextExtraKeyEnum.FEIGN_META.getCode(), JSON.toJSONString(feignMetaVO));
// 以下部分,保留一段时间后删除,仅服务调用异常时打印
FeignMetaVO simpleInfo = ConvertUtils.sourceToTarget(feignMetaVO, FeignMetaVO.class);
simpleInfo.setBody("仅服务调用异常时打印此字段"); // 请求体内容可能很多,所以平时不打印,仅服务调用异常时打印
log.info("Feign调用调试信息:{}", simpleInfo);
UserContext.addCallChainNode(target.name()); // 添加调用链路节点,用于打印调用链路
} catch (Exception e) {
// 忽略异常
}
}
}
响应拦截
方式一
注入自定义解码器
@Slf4j
@Configuration
@ConditionalOnClass({Feign.class})
@AutoConfigureBefore(FeignAutoConfiguration.class)
public class FeignConfig {
@Autowired
private ObjectFactory<HttpMessageConverters> messageConverters;
@Bean
public Decoder feignDecoder() {
return new OptionalDecoder(new ResponseEntityDecoder(new MyDecoder(this.messageConverters)));
}
}
继承SpringDecoder自定义解码器
class MyDecoder extends SpringDecoder {
MyDecoder(ObjectFactory<HttpMessageConverters> messageConverters) {
super(messageConverters);
}
@Override
public Object decode(Response response, Type type) throws IOException, FeignException {
// 这里可以从response对象里面获取响应头和响应体
// 获取响应头
Map<String, Collection<String>> headers = response.headers();
return super.decode(response, type);
}
}
方式二
https://zhuanlan.zhihu.com/p/528834129
附
提取堆栈摘要
private String compressStack(RuntimeException ex) {
String stacktrace = ExceptionUtil.stacktraceToString(ex, 3000);// 只保留有效堆栈,限制3000字符(经验值),不够再改
String format = stacktrace.replace(" ", "");
String repack = Arrays.stream(format.split("\n")).filter(row -> !row.startsWith("at") || row.contains("xianniu")).collect(Collectors.joining("\n"));
return repack;
}