1、注意特殊情况,在定时任务或者内部之间调用,没有request的时候,不要处理直接返回。
2、在GET请求,参数确放在Body里面传递的情况,restTemplate是不认识的,所以这里要转化下处理,然后清空body数据
3、在请求过程中如果出现java.io.IOException: too many bytes written异常,请参考 保持请求头造成请求头和content-length不一致
/**
* 解决服务调用丢失请求头的问题
* @author 大仙
*
*/
@Component
public class FeignConfiguration implements RequestInterceptor{
private final Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private ObjectMapper objectMapper;
@Override
public void apply(RequestTemplate template) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder
.getRequestAttributes();
// 注意: RequestContextHolder依赖于 ThreadLocal, 所以在hystrix的隔离策略为THREAD、MQ的消费者、定时任务调用feignClient时,此处应为null
if (attributes == null) {
return;
}
HttpServletRequest request = attributes.getRequest();
Enumeration<String> headerNames = request.getHeaderNames();
if (headerNames != null) {
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
String values = request.getHeader(name);
template.header(name, values);
}
}
logger.info("保持请求头");
//feign 不支持 GET 方法传 POJO, json body转query
if (template.method().equals("GET") && template.requestBody().asBytes() != null) {
try {
JsonNode jsonNode = objectMapper.readTree(template.requestBody().asBytes());
Request.Body.empty();
Map<String, Collection<String>> queries = new HashMap<>();
buildQuery(jsonNode, "", queries);
template.queries(queries);
} catch (IOException e) {
//提示:根据实践项目情况处理此处异常,这里不做扩展。
e.printStackTrace();
}
}
}
/**
* 改造
* @param jsonNode
* @param path
* @param queries
*/
private void buildQuery(JsonNode jsonNode, String path, Map<String, Collection<String>> queries) {
// 叶子节点
if (!jsonNode.isContainerNode()) {
if (jsonNode.isNull()) {
return;
}
Collection<String> values = queries.get(path);
if (null == values) {
values = new ArrayList<>();
queries.put(path, values);
}
values.add(jsonNode.asText());
return;
}
// 数组节点
if (jsonNode.isArray()) {
Iterator<JsonNode> it = jsonNode.elements();
while (it.hasNext()) {
buildQuery(it.next(), path, queries);
}
} else {
Iterator<Map.Entry<String, JsonNode>> it;
it = jsonNode.fields();
while (it.hasNext()) {
Map.Entry<String, JsonNode> entry = it.next();
if (StringUtils.hasText(path)) {
buildQuery(entry.getValue(), path + "." + entry.getKey(), queries);
} else {
// 根节点
buildQuery(entry.getValue(), entry.getKey(), queries);
}
}
}
}
}